Amended by net-kingdom as canon owner of tenancy-posture_v0.1, answering ZONE-WP-0001-T01. T01: organization_posture does not fold into zones and does not belong in a per-repo declaration — it is a fleet-wide time-varying scalar. Hand it over as an input. T03: zone membership is declared in tenancy.yaml under a reserved zones: key (canon Decision 5.6). ops-warden has no tenancy.yaml, so this now implies declaring the six-axis posture vector too. Also records why this declaration may not set stance: a declarer that sets its own stance makes exempt conformant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.8 KiB
| id | type | title | domain | repo | status | owner | topic_slug | planning_priority | depends_on_workplans | created | updated | state_hub_workstream_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| WARDEN-WP-0032 | workplan | Adopt security zones as a consumer — retire the global policy.enabled | infotech | ops-warden | proposed | ops-warden | netkingdom | P1 |
|
2026-08-19 | 2026-08-19 | f1b6cdcb-5e16-48ab-a72b-339e909e92f0 |
WARDEN-WP-0032 — Adopt security zones as a consumer
ADR-0006 defers policy.enabled: true until enforcement can be scoped to a
zone. The zone model itself is no longer ops-warden's work. It moved to
zone-engine as ZONE-WP-0001 on 2026-08-19, where it belongs under ADR-0005
— ops-warden implements one lane narrowly and routes the rest, and an
estate-wide enforcement model is not a lane it should absorb.
What stays here is the consumer side: ops-warden was the repo whose deferred flip exposed the gap, it holds the controls the model must be able to express, and it is the first consumer the model has to satisfy.
What ops-warden owes zone-engine
Inputs, not designs. ZONE-WP-0001-T02 derives the model from the real estate,
and most of that estate is ops-warden's:
- 27 routing catalog lanes (
registry/routing/catalog.yaml) withrisk,status, anddelegationalready on each — the likeliest membership inputs. - The actor inventory (
adm/agt/atm) and its TTL policy. - The three posture axes already shipped — environment and maturity
(WP-0015),
organization_posture(WP-0029) — including the honest answer to whetherorganization_postureshould be folded into zones rather than run beside them. - Three controls the model must be able to express: the flex-auth pre-sign
gate (
policy.enabled+fail_closed), the agent read-boundary onrisk: highlanes (ADR-0004), and thewarden planescalation verdicts. - The compiled-registry path (
scripts/build_flex_auth_registry.py) — how membership can reach flex-auth without a lookup in a latency-critical decision path.
Tasks
id: WARDEN-WP-0032-T01
status: todo
priority: high
state_hub_task_id: "b6dac514-4b05-47b8-8745-6a1c67b6100e"
Hand the estate inputs to ZONE-WP-0001-T02. Not a design proposal — the
lanes, actors, axes, and controls above, with the exceptions ops-warden already
knows do not fit cleanly (the interim delegation lanes from WP-0030 are the
obvious candidates: a lane covered on someone else's behalf may not sit in the
same zone as one ops-warden owns outright).
Include the organization_posture fold-in question honestly, including the case
against keeping it.
Answered by net-kingdom 2026-08-19 (canon owner of tenancy-posture_v0.1,
answering ZONE-WP-0001-T01): do not fold it in, and do not put it in a
per-repo declaration under any key. organization_posture is a fleet-wide,
time-varying scalar describing the estate, not a property of a declaring
service; a per-repo copy of a global goes stale in as many places as there are
repos. It stays what WP-0029 made it — an input to stance selection that the
zone model reads. Hand it over as an input, not as a candidate axis. Environment
posture and M0–M3 are per-workload and remain genuinely composable; those two
are still open for ZONE-WP-0001-T02.
id: WARDEN-WP-0032-T02
status: wait
priority: high
state_hub_task_id: "08735f17-fe7e-4a6a-9b71-f350f98c30b1"
Replace policy.enabled with a zone-aware control. Waits on
ZONE-WP-0001-T03 and T05. Reads the zone of the actor being signed for and
that zone's failure mode. Ship deprecation and migration in the same change —
leaving both is the second-source-of-truth failure ADR-0001 exists to prevent.
Re-run scripts/check_policy_caller_identity.py before enabling anything: the
WP-0031 evidence (decision:f3f7c88f9585582a, 2026-08-19) will be stale, and
re-establishing it is cheap precisely so this is a re-check rather than a re-do.
This closes WARDEN-WP-0031-T05.
Amended by flex-auth 2026-08-19, reviewing ZONE-WP-0001 as the PDP. Two
constraints that change what this task can build, both argued in full at
ZONE-WP-0001-T03 and T04:
-
The zone-aware control splits across the boundary, it does not move. flex-auth will read compiled zone membership from the registry and apply the per-zone stance from its policy package, returning an effect plus an advisory annotation. What stays on the ops-warden side is the axis flex-auth structurally cannot carry:
fail_closedis not expressible by a PDP. Fail-open describes whatwarden signdoes when flex-auth is unreachable — no decision is rendered, so no compiled data and no policy rule can reach it. So the replacement forpolicy.enabledis not one zone-derived boolean either; it is (a) stance, which arrives in the decision, and (b) failure mode, which stays a local ops-warden setting declared per zone. Plan for two, or T02 will be built expecting flex-auth to answer something it cannot. -
The membership compiler is ops-warden's to change, and it has a name collision to resolve first.
scripts/build_flex_auth_registry.py:77already emits"trust_zone": "platform"as a hardcoded constant on every ssh-certificate resource. It is a first-class field on flex-auth'sResource, it is surfaced into rego input, and no policy package reads it. Before compiling zone membership, either retire that constant or deliberately repurpose it — do not addsecurity_zonebeside a dormanttrust_zoneand leave the next reader to guess which is real. That is theADR-0001second-source-of-truth failure in miniature, inside a generated artifact.
Good news for T03's cost: no flex-auth registry schema change is required.
metadata, labels and attributes already flatten into the rego input, so the
compiler can emit membership today.
id: WARDEN-WP-0032-T03
status: wait
priority: medium
state_hub_task_id: "fd642377-8d64-473c-b684-f8f1a842c223"
Declare ops-warden's zones in the format ZONE-WP-0001-T05 settles,
alongside the existing posture descriptors.
Amended by net-kingdom 2026-08-19 — the carrier file is already settled, only
its contents are open. Canon Decision 5.6 (tenancy-posture_v0.1 draft-9)
rules that zone membership is declared in tenancy.yaml under a reserved
top-level zones: key, sibling to tenancy: and provider: and never inside
tenancy.current. §5.4 makes that file the repo's single posture declaration
surface, and a second root file would be the second-source-of-truth failure
ADR-0001 exists to prevent — in ops-warden's own idiom. The key is reserved and
deliberately unconstrained in net-kingdom/canon/schemas/tenancy-posture_v0.1.schema.json,
so a combined declaration validates today.
Note the consequence for this repo: ops-warden does not currently have a
tenancy.yaml. Declaring zones means writing one, which means declaring the
six-axis posture vector too. That is a real and probably overdue cost, not an
accident of this amendment — canon would rather ops-warden declare both
accurately than declare a zone with no posture beside it.
Note also why stance is not something this declaration may set: canon Decision
5.6 rules that a declarer must not be the party that sets the stance, or an
accurately declared exempt becomes conformant and exempt. ops-warden declares
which zone a lane or actor is in. The stance of the pre-sign gate in that zone is
flex-auth's policy package; the failure mode is ops-warden's own setting, per
flex-auth's T03 amendment. Per flex-auth's T05 amendment, this
declaration must also say whether a zone rides the actor (a flex-auth
subject) or the lane (a flex-auth per-actor resource) — in the compiled
registry an actor is both, and the compiler needs to be told which record
carries membership. Carry the conformance rule:
accuracy, not altitude. Declaring a stricter zone than can be evidenced is the
failure mode that looks like progress.
id: WARDEN-WP-0032-T04
status: wait
priority: medium
state_hub_task_id: "1af3d26e-ce21-46ca-a56c-486d52b76dcb"
Amend ADR-0006. Once zones exist and enforcement scoping is owned by
zone-engine, ADR-0006 must say that ops-warden follows the model rather than
owning it — a superseding record, never an in-place edit. Update SCOPE.md,
wiki/WorkloadSecurityPosture.md, and wiki/PolicyGatedSigning.md with it.
Related
zone-engineZONE-WP-0001— the model, and where this work is led fromADR-0006— enforcement is zone-scoped, never a global flagWARDEN-WP-0031— the deferred flip and its readiness evidencenet-kingdomtenancy-posture_v0.1draft-9 Decisions 5.6, 8.4.1, 8.4.2 — canon's answer toZONE-WP-0001-T01; enforcement stance is a sibling standard, not a seventh axis, and the declaration surface istenancy.yaml