# Kubernetes change gate: tiered by readiness state **Decided by:** Bernd Worsch (founder), exercising `GOVERN @ estate`. **Date:** 2026-09-21. **Recorded by:** the-custodian. **Vocabulary:** SecurityCanon Mode of Authority v0.2.0 (`security-canon/infospace/vocabulary/mode-of-authority/`), which is still a draft. Where that vocabulary changes, this record follows it. This record answers gate-house's open question: which engine, if any, should own ops-mason's contact with the Kubernetes API. ## The question, stated in the canon's terms Applying manifests to a running cluster is `ADMINISTER @ realm:kubernetes/railiance01`. Changing the manifests is `CONSTRUCT @ `. A GitOps controller separates the two: `CONSTRUCT` produces the definition, and the controller reconciles the cluster to it. The question is what gates `ADMINISTER @ realm:kubernetes`, and whether that gate differs between experimental and production workloads. ## Decision 1. **No engine owns the contact.** The gate is a quality gate on a change, not an authorization decision. railiance-master ADR-0006 already keeps readiness and permission on separate axes: `production-approved` "is not an authorization decision". So no PDP belongs in this path. The contact is with `realm:kubernetes/railiance01`. This record assigns no layer to that realm and no layer to any rail. Mapping rails onto layers is statute §20.3, which ADR-0009 Decision 4 deliberately leaves unset. The first version of this record said the contact "stays a Tooling contact, owned by rail-kubernetes". That was an unintended §20.3 mapping, and it is withdrawn. 2. **The gate is tiered by ADR-0006 `readiness_state`, not by `Environment`.** railiance01 is a single cluster, and every workload on it shares one `Environment`. The canon's `Environment` dimension therefore cannot separate experimental from production here. The readiness state can. | Readiness state of the target | Path for a change | `Activation` | |---|---|---| | `declared`, `installed`, `verified` | Direct `ADMINISTER @ realm:kubernetes` by ops-mason | `APPROVED`: founder approval of the construction plan | | `production-approved` | `CONSTRUCT @ manifest repository`, reconciled by ArgoCD (`railiance-platform`) | `APPROVED` for the change; the merge is the gate | | `production-approved`, emergency | Direct `ADMINISTER` | `BREAK_GLASS`, recorded, reconciled back into the repository afterwards | Three rules settle the edges of the table (founder, 2026-09-21): - **Unmapped targets are production-tier until mapped.** The readiness contract defines states only for rails and bound rapps, and nothing yet maps a Kubernetes object or namespace to its binding. So a target without a mapping is production-tier. The friction this creates is deliberate: it is what motivates building the namespace-to-binding mapping (ops-mason MASON-WP-0006, with railiance-master). - **An evidence lapse does not loosen the path.** When a binding's evidence fails or expires, the contract returns it to its last proven state. The change path does not follow it down. Once a binding has reached `production-approved`, its changes stay on the git/ArgoCD path until the binding is explicitly re-scoped. A lapse weakens the readiness claim, and that is exactly when the gate must not loosen. - **`deprecated` keeps the tier it had before deprecation.** A deprecated production workload may still carry production traffic until it is removed. 3. **Why production goes through git: the `EvidenceBoundary` dimension.** A direct apply is `target-audited`: the only evidence of the change is held by the realm being changed. A change through the manifest repository adds `external-audited` evidence, which survives the actor and the realm. For production that is the property that matters, and it is a statement about evidence, not about trust in ops-mason. ## Explicit tier placements Some targets have no binding readiness state, but the founder has placed them in a tier explicitly. An explicit placement overrides the "unmapped is production-tier" default for that target only. | Target | Tier | Decided | Reason | |---|---|---|---| | namespace `whitehat` (whitehat-security; ops-mason bundle `whitehat-foundational-plane`) | non-production | founder, 2026-09-21 | A security-testing workload that no other layer depends on at runtime. Placing it explicitly keeps the unmapped default strict for real platform objects, and makes whitehat a deliberate exception rather than an accidental block. | A placement is revisited if the target gains dependants, or if it gets a binding with its own readiness state. If it gets a binding, the binding's state governs from then on. ## Transition for rapp-policy-nexus `rapp-policy-nexus` is `production-approved` (reef-railiance `bindings/rapps.yaml`), but ArgoCD does not manage it. Its `railiance-apps-root` applications are external-secrets, issue-core, openbao-secretstore and target-revenue. So the production path does not yet exist for the one workload that needs it. - **Until 2026-12-21:** changes to policy-nexus keep `activation=APPROVED` by founder plan approval. Each change additionally records that its target is production-tier, so the transition is visible and does not look like conformance. - **By 2026-12-21:** policy-nexus is onboarded to ArgoCD. From then on, the production row of the table applies to it. 2026-12-21 is the same review date as the ops-mason plan-approval gate, so both come up together. ## Scope of ops-mason's contact, as found ops-mason's executor is narrower than a generic `kubectl apply`: - it confines each plan to one expected namespace; - it refuses the `Pod` and `Secret` kinds; - it rejects any manifest carrying `data` or `stringData`. This decision relies on those limits. Widening them is a new decision. ## Verified 2026-09-21: ArgoCD is not on railiance01 A read-only check, run by the custodian over SSH with the founder's approval, established: - The node is `92.205.62.239`, the single k3s control-plane node. - The `argocd` namespace does not exist. - The `applications.argoproj.io` CRD does not exist. - The resource type `applications` is unknown to the API server. Only `get` was used; nothing was applied, patched or synced. **So the production row has no working path on railiance01.** Until one exists, the transition rule applies to every production-tier target there. Installing ArgoCD on railiance01 is a cluster-layer change and needs its own founder go-ahead. It is not part of this decision. ### What the records said before the check Whether ArgoCD runs on railiance01 at all is unverified, and railiance-platform's own records point the other way: - Its later records name the controller "coulombcore ArgoCD". - Its only health record, "healthy on railiance01", predates the 2026-07-02 correction, before which "railiance01" often meant coulombcore. - No evidence records `railiance-apps-root` syncing on 92.205.62.239. If ArgoCD is not on railiance01, **the production row has no working path there yet**. Until one exists, production-tier changes on railiance01 fall under the transition rule in the next paragraph, and installing ArgoCD on railiance01 is a cluster-layer change needing its own go-ahead. railiance-platform RPF-WP-0043-T01 holds the read-only check. Until the production row has a working path, the policy-nexus transition rule applies to every production-tier target on railiance01, not only to policy-nexus: `activation=APPROVED`, with each change recorded as production-tier. ## Owners - **gate-house:** the open question is answered. No engine owns the contact, and the gate is quality, not authorization. - **ops-mason:** phase 4 checks the target's readiness state and refuses a direct apply to a production-tier target, except under `BREAK_GLASS` or the policy-nexus transition. - **railiance-platform:** the ArgoCD lane is the production path, and policy-nexus onboarding is due by 2026-12-21. - **railiance-master:** ADR-0006 gains a deploy-path consequence for `production-approved`. - **rapp-policy-nexus:** the transition and its date.