An explicit placement overrides the unmapped-is-production default for that target only; it unblocks ops-mason's only bundle without loosening the default for platform objects. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82 lines
7.3 KiB
Markdown
82 lines
7.3 KiB
Markdown
# 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 @ <manifest repository>`. 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.
|
|
|
|
## Not verified here, and possibly not true
|
|
|
|
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.
|