plane(1.1): PlaneProfile -- one TOML per cluster, env-overridable, no secrets

ops/k8s/profiles/kind.toml and k3s.toml hold the values that differ per cluster
(exec, kube_context, registry, images, router_url, ax_server, memory, atespace,
snapshots_bucket, image_pull_secret, pools); kind-images.json carries the digest
pin ops/ax/up.sh wrote. load_profile() reads OUSAST_PLANE_PROFILE (name or path,
default kind), applies OUSAST_<FIELD> and OUSAST_POOL_<NAME>_<FIELD>, and refuses
an unknown key, a credential-shaped key or value, an exec outside local|remote
and an images file without digest pins. `python -m openultrasast.plane.profile
--print FIELD` serves shell scripts. The module-audit manifest is regenerated
for the new module (counts 147/5, no orphan).

Gates: pytest full suite 2002 passed, 1 failed (the module-audit manifest, fixed
by regenerating it; tests/test_module_audit.py re-run exit 0), ruff check 0,
ruff format 0, mypy 0.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-10-02 20:16:23 +02:00
co-authored by Claude Fable 5.1
parent 6bd44caa50
commit 8eac1b2c69
7 changed files with 2250 additions and 1767 deletions
+26
View File
@@ -0,0 +1,26 @@
# The k3s profile: the plane on the maintainer's production cluster (plane-on-kubernetes design section 1;
# requirements "Target Environment"). Documented values, not secrets: the kubeconfig for the context, the GHCR
# pull secret's content and the store's keys live outside this file. Every field is overridable by OUSAST_<FIELD>,
# a pool by OUSAST_POOL_<NAME>_<FIELD>. Nothing has been applied to a k3s cluster yet; docs/deployment.md says
# which items are planned.
exec = "remote" # the same CLI from a laptop or a CI job, through the cluster's kube context
kube_context = "ousast-k3s" # the maintainer's context name for the k3s cluster
registry = "ghcr.io/norandom" # images built by GitHub Actions from tagged commits (design section 8)
images = "images.json" # the release asset {"runner": "ghcr.io/norandom/ousast-runner@sha256:...", "engine": ...}
router_url = "" # empty: port-forward to atenet-router through the kube context (ax-tunnel)
ax_server = "" # empty: the ax CLI's own tunnel through the kube context (ax-tunnel)
memory = "s3://sast-memory" # the memory store; S3_ENDPOINT and the keys come from the CI secrets or .env
atespace = "default"
snapshots_bucket = "s3://ax-snapshots" # ax's AX_SNAPSHOTS_BUCKET, ours (rendered into the ax-server patch)
image_pull_secret = "ghcr-pull" # only needed while the GHCR packages are private
[pools.default] # production sizing: four verify-class workers; the HPA (design section 5) scales it
replicas = 4
cpu = "1"
memory = "1536Mi"
[pools.engine] # two engine workers sized from the measured 2.1 GiB peak under a 3 GiB limit
replicas = 2
cpu = "2"
memory = "4Gi"
+3
View File
@@ -0,0 +1,3 @@
{
"runner": "localhost:5001/ousast-runner@sha256:412db0a1504af8f1b23a395af8d1dcbd152c1bb6d16594f2b733067163a31884"
}
+25
View File
@@ -0,0 +1,25 @@
# The kind profile: the plane on this laptop's single-node kind cluster, which ops/ax/up.sh creates and which is
# the development default (plane-on-kubernetes design section 1). Values only; a credential never goes here
# (keys stay in the environment or .env). Every field is overridable by OUSAST_<FIELD> in the environment, a pool
# by OUSAST_POOL_<NAME>_<FIELD>. This file may name the kind cluster; the code must not (tests/test_plane_literals.py).
exec = "local" # the reconciler runs on this host against the cluster below
kube_context = "kind-ousast" # kind's context for KIND_CLUSTER_NAME=ousast
registry = "localhost:5001" # the kind-local registry up.sh creates (Substrate rewrites it for the node)
images = "kind-images.json" # digest-pinned image references, written by up.sh after each build
router_url = "" # empty: port-forward to atenet-router through the kube context (ax-tunnel)
ax_server = "" # empty: the ax CLI's own tunnel through the kube context (ax-tunnel)
memory = "s3://sast-memory" # the memory store; S3_ENDPOINT and the keys come from .env
atespace = "default"
snapshots_bucket = "s3://ax-snapshots" # ax's AX_SNAPSHOTS_BUCKET, ours (rendered into the ax-server patch)
image_pull_secret = "" # the kind registry needs none
[pools.default] # ousast-pool: two gVisor workers fit the 7 GB host beside the control planes
replicas = 2
cpu = "1"
memory = "1536Mi"
[pools.engine] # engine-pool (design section 4): one worker for the Joern engine task
replicas = 1
cpu = "2"
memory = "4Gi"