Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 63291@bnt-lap001 Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
205 lines
8.1 KiB
Markdown
205 lines
8.1 KiB
Markdown
---
|
|
id: MASON-WP-0006
|
|
type: workplan
|
|
title: "Check the target's readiness tier before a direct Kubernetes apply"
|
|
domain: infotech
|
|
repo: ops-mason
|
|
status: proposed
|
|
flavor: implementation
|
|
owner: claude
|
|
topic_slug: ops-mason
|
|
created: "2026-09-21"
|
|
updated: "2026-09-21"
|
|
state_hub_workstream_id: "1b900161-51ff-544f-8412-ba7fcab64bb5"
|
|
---
|
|
|
|
# MASON-WP-0006 — Check the target's readiness tier before a direct Kubernetes apply
|
|
|
|
## Goal
|
|
|
|
Make phase 4 enforce the founder's Kubernetes change-gate decision
|
|
(`the-custodian/docs/kubernetes-change-gate-decision.md`, 2026-09-21, the
|
|
founder exercising `GOVERN @ estate`). Before any direct
|
|
`ADMINISTER @ realm:kubernetes/railiance01`, `ops-mason plane apply` must
|
|
establish the target's railiance-master ADR-0006 `readiness_state` and:
|
|
|
|
- allow a direct apply under `activation=APPROVED` (founder plan approval) when
|
|
the target is `declared`, `installed` or `verified`;
|
|
- refuse a direct apply to a production-tier target (`production-approved`, or
|
|
no readiness state at all), except:
|
|
- under `activation=BREAK_GLASS`, which is recorded and must be reconciled
|
|
back into the manifest repository afterwards; or
|
|
- for `rapp-policy-nexus` under the transition, which runs until 2026-12-21.
|
|
Each such change keeps `activation=APPROVED` and is recorded as
|
|
production-tier, so the transition does not look like conformance.
|
|
|
|
The production path itself (`CONSTRUCT @ manifest repository`, reconciled by
|
|
ArgoCD) belongs to railiance-platform. ops-mason only refuses; it does not
|
|
build that path.
|
|
|
|
## Boundaries
|
|
|
|
- **The executor's limits are not widened.** One expected namespace per plan,
|
|
`Pod` and `Secret` refused, no `data` or `stringData`. The decision relies on
|
|
them; widening any of them is a new founder decision.
|
|
- The readiness check is a quality gate, not an authorization decision. It does
|
|
not consult access-engine and must not be described as a PDP.
|
|
- No live change is part of this workplan. Tests use the injected runner.
|
|
|
|
## Design choice: how ops-mason obtains the readiness state
|
|
|
|
The authoritative states live in another repository,
|
|
`reef-railiance/bindings/rapps.yaml`. Three options were weighed:
|
|
|
|
1. **Read the sibling checkout at apply time.** Simple, but unpinned: the
|
|
evidence would name no revision, and the result depends on whatever the
|
|
workstation happens to have checked out.
|
|
2. **Vendor a copy of `rapps.yaml` into ops-mason.** Pinned, but it goes stale
|
|
silently. A rApp promoted to `production-approved` upstream would still read
|
|
as `verified` here and pass the gate: the failure mode is fail-open.
|
|
3. **Pin the reference in the bundle and verify it against the source at
|
|
preflight (chosen).** The bundle names the target and pins the readiness
|
|
source the same way it already pins manifests:
|
|
|
|
```yaml
|
|
readiness:
|
|
target: {kind: rapp, rapp_id: rapp-user-engine} # or {kind: platform}
|
|
source:
|
|
repo: reef-railiance
|
|
path: bindings/rapps.yaml
|
|
revision: <commit>
|
|
sha256: <digest of the file at that commit>
|
|
```
|
|
|
|
Preflight, through the existing runner:
|
|
- `git -C <reef-railiance> show <revision>:bindings/rapps.yaml` must hash to
|
|
`sha256`;
|
|
- `git -C <reef-railiance> diff --quiet <revision> HEAD -- bindings/rapps.yaml`
|
|
must show the file unchanged since the pin, so a later promotion cannot be
|
|
missed. If the file changed, the bundle is re-pinned through review;
|
|
- the `readiness_state` for the target is read from the pinned content.
|
|
|
|
**Fail closed.** A missing `readiness` block, `kind: platform`, a target not
|
|
listed in `rapps.yaml`, a source that cannot be found or verified, or an
|
|
unknown state value all resolve to the production tier. The decision says
|
|
platform objects without a readiness state default to production; an
|
|
unverifiable state is treated the same way.
|
|
|
|
The checkout location comes from a `--readiness-repo` CLI option, defaulting
|
|
to the sibling path `../reef-railiance`. It is a location, not a trust
|
|
anchor: the pinned revision and digest are.
|
|
|
|
The evidence record gains a `readiness` section: target, source repo, revision
|
|
and digest, resolved state, tier, `activation`, and a `transition` flag when the
|
|
policy-nexus rule was used.
|
|
|
|
## Open question for the founder: the whitehat plane
|
|
|
|
```task
|
|
id: MASON-WP-0006-T01
|
|
status: wait
|
|
priority: high
|
|
state_hub_task_id: "7b6fe7b4-08f7-5ad0-899d-a4862b5ddb00"
|
|
```
|
|
|
|
`bundles/whitehat-foundational-plane.yaml` is the only bundle today, and its plan
|
|
is `built`. It targets the `whitehat` namespace, which is not a rApp and carries
|
|
no ADR-0006 `readiness_state`. Under the decision it therefore defaults to the
|
|
production tier, and once T03 lands, a further direct apply of it would be
|
|
refused.
|
|
|
|
This workplan was told the check must not change behaviour for today's
|
|
non-production plans. Whether the whitehat plane is one of them is not a
|
|
question ops-mason can answer for itself. The founder chooses one of:
|
|
|
|
- (a) it is a platform object and production-tier, as the default says; future
|
|
changes to it go through the manifest repository or `BREAK_GLASS`;
|
|
- (b) it gains a readiness state from its owner (whitehat-security), in which
|
|
case `readiness.target` names that record; or
|
|
- (c) an explicit, dated exception.
|
|
|
|
T03 must not merge before this is answered.
|
|
|
|
## Extend the bundle schema with the readiness block
|
|
|
|
```task
|
|
id: MASON-WP-0006-T02
|
|
status: todo
|
|
priority: high
|
|
state_hub_task_id: "89d07bd5-5a92-5a06-9ecb-441799c14dd7"
|
|
```
|
|
|
|
Add the optional `readiness` block to `PlaneBundle.load` as described above. It
|
|
is included in the bundle digest, as the bundle file already is. Add a
|
|
`--activation {APPROVED,BREAK_GLASS}` option to `plane apply`, defaulting to
|
|
`APPROVED`, and a `--readiness-repo` option. `BREAK_GLASS` requires a
|
|
`--break-glass-reason` string. No existing refusal is relaxed.
|
|
|
|
## Enforce the tier in preflight and apply
|
|
|
|
```task
|
|
id: MASON-WP-0006-T03
|
|
status: todo
|
|
priority: high
|
|
state_hub_task_id: "163a807b-29aa-5eb7-a9a8-ef1ac70c89d3"
|
|
```
|
|
|
|
Add a pure function, `resolve_tier(state, target, activation, today)`, returning
|
|
the tier and whether a direct apply is allowed, and call it from `apply` after
|
|
the plan-approval and digest checks and before any `kubectl` write. `preflight`
|
|
reports the resolved tier without refusing, so a production-tier plane can
|
|
still be validated.
|
|
|
|
Tests, all against the injected runner:
|
|
|
|
- a `verified` rApp target applies under `APPROVED` (non-production tier);
|
|
- a `production-approved` target is refused under `APPROVED`, with no `kubectl
|
|
apply` call made;
|
|
- the same target is allowed under `BREAK_GLASS`, and the evidence records it;
|
|
- `rapp-policy-nexus` is allowed under `APPROVED` on 2026-12-20, is recorded
|
|
with `transition: true` and tier production, and is refused on 2026-12-22;
|
|
- no `readiness` block, `kind: platform`, an unlisted rApp, a digest mismatch,
|
|
and a file changed since the pin each resolve to production and are refused;
|
|
- the existing forbidden-kind, `data`/`stringData` and namespace tests still pass
|
|
unchanged.
|
|
|
|
## Record BREAK_GLASS and its reconcile-back obligation
|
|
|
|
```task
|
|
id: MASON-WP-0006-T04
|
|
status: todo
|
|
priority: medium
|
|
state_hub_task_id: "66349531-09ee-55b9-be47-537842c80f3b"
|
|
```
|
|
|
|
A `BREAK_GLASS` apply writes its reason, actor and time into the evidence
|
|
record and prints the follow-up that is owed: the same change, committed to the
|
|
manifest repository that ArgoCD reconciles. ops-mason does not open that change
|
|
itself.
|
|
|
|
## Update the docs and the declaration
|
|
|
|
```task
|
|
id: MASON-WP-0006-T05
|
|
status: todo
|
|
priority: medium
|
|
state_hub_task_id: "6d64e7f5-9cff-5bf9-9851-97d318d1df0a"
|
|
```
|
|
|
|
Update `docs/kubernetes-plane.md` with the tier table and the readiness block,
|
|
and change the `enforcement` line of the `kubernetes-plane-apply` entry in
|
|
`INTENT.md` from "not yet in code" to point at the check.
|
|
|
|
## Review on 2026-12-21
|
|
|
|
```task
|
|
id: MASON-WP-0006-T06
|
|
status: wait
|
|
priority: medium
|
|
state_hub_task_id: "49dd5f9a-307b-5baf-809e-bd3893c73341"
|
|
```
|
|
|
|
On 2026-12-21 the policy-nexus transition ends and the plan-approval exception
|
|
comes up for review. Confirm with railiance-platform that policy-nexus is
|
|
onboarded to ArgoCD. The date check in T03 ends the transition in code on that
|
|
date either way.
|