These workplans exist only in the retired local hub. Their random pre-ADR-007 identifiers are refused by C-06 as stale references, so they cannot be registered. Deriving from the canonical record id takes no identity from anything: central does not hold them and the old ids die with the cache. Records central already holds were deliberately left untouched. Refs CUST-WP-0068-T06 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
429 lines
23 KiB
Markdown
429 lines
23 KiB
Markdown
---
|
||
id: WARDEN-WP-0032
|
||
type: workplan
|
||
title: "Adopt security zones as a consumer — retire the global policy.enabled"
|
||
domain: infotech
|
||
repo: ops-warden
|
||
status: finished
|
||
owner: ops-warden
|
||
topic_slug: netkingdom
|
||
planning_priority: P1
|
||
depends_on_workplans:
|
||
- WARDEN-WP-0031
|
||
created: "2026-08-19"
|
||
updated: "2026-08-22"
|
||
state_hub_workstream_id: "38c6a5f3-fb0d-5230-be85-f9e3ffc850f6"
|
||
quality_dod: DoD-Ok
|
||
quality_dod_at: "2026-08-22"
|
||
quality_dod_by: codex
|
||
quality_dod_note: "All tasks are done; the global switches and trust-zone source are retired, workload references are explicit, the owner policy is total, declarations validate, live caller identity is re-proven, and the full suite passes."
|
||
---
|
||
|
||
# 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`) with `risk`,
|
||
`status`, and `delegation` already 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
|
||
whether `organization_posture` should 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 on
|
||
`risk: high` lanes (`ADR-0004`), and the `warden plan` escalation 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
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "b03a5caa-0bb5-5cdd-bb99-32c694b0da29"
|
||
```
|
||
|
||
**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`.
|
||
|
||
**Done 2026-08-21.** Every input listed above is now carried in `ZONE-WP-0001`,
|
||
and `T02` there is `done` — which is the acceptance condition for this task, since
|
||
what was owed was inputs rather than a design.
|
||
|
||
What actually reached them: the 27 graded lanes with `risk`/`status`/`delegation`
|
||
(T05), the `M0`–`M3` ladder in `registry/policy/security-posture.yaml` — which
|
||
`ZONE-WP-0001-T02` adopted as the maturity ladder rather than
|
||
`.repo-classification.yaml` `category`, on the evidence that the latter grades a
|
||
production SSH CA below a documentation repo — the three controls, and the
|
||
compiled-registry path including the dormant `trust_zone` constant at
|
||
`scripts/build_flex_auth_registry.py:77`.
|
||
|
||
Two inputs were handed over as corrections to ops-warden's own earlier claims,
|
||
which is the part worth recording. `organization_posture` was offered as a
|
||
candidate axis and net-kingdom refused it (above); and ops-warden asserted no
|
||
registry carried a workload join key, which was true of its own catalog and false
|
||
of the estate — `rapp-*/declarations/rapp.yaml` carries eight
|
||
`workload_identity` declarations. `scripts/report_workload_join.py` then measured
|
||
the join rather than asserting it: **1 of 27 lanes** matches a declared workload.
|
||
That number is `ZONE-WP-0001-T03`'s critical path, and it came out of correcting
|
||
this repo's own input rather than out of supplying a new one.
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T02
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "b3f41c85-a293-58ad-ac27-9f8110c51266"
|
||
```
|
||
|
||
**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`:
|
||
|
||
1. **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_closed` is not expressible by a PDP.**
|
||
Fail-open describes what `warden sign` does when flex-auth is *unreachable* —
|
||
no decision is rendered, so no compiled data and no policy rule can reach it.
|
||
So the replacement for `policy.enabled` is 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.
|
||
|
||
2. **The membership compiler is ops-warden's to change, and it has a name
|
||
collision to resolve first.** `scripts/build_flex_auth_registry.py:77` already
|
||
emits `"trust_zone": "platform"` as a hardcoded constant on every
|
||
ssh-certificate resource. It is a first-class field on flex-auth's `Resource`,
|
||
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 add `security_zone` beside a dormant `trust_zone` and
|
||
leave the next reader to guess which is real. That is the `ADR-0001`
|
||
second-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.
|
||
|
||
**Consumer implementation landed in the working tree 2026-08-22.** The config
|
||
loader rejects the retired `policy.enabled` and global `policy.fail_closed`
|
||
keys. `scripts/build_flex_auth_registry.py` now emits the normative
|
||
`workload_id`, `security_zone`, `security_zone_declared`,
|
||
`security_zone_admission`, `security_zone_reason`, and
|
||
`security_zone_revision` attributes; the dormant `trust_zone` field is gone.
|
||
The PEP reads compiled resource membership and applies its local per-zone
|
||
failure mode. Sign and audit records retain the zone, selected failure mode,
|
||
outcome, and decision id.
|
||
|
||
The legacy `--no-policy` proxy switch remains only as a rejected compatibility
|
||
flag. It can no longer bypass the gate: unresolved credential targets take the
|
||
explicit `unknown` profile and its configured failure mode.
|
||
|
||
**Done 2026-08-22.** flex-auth package v2 (commit `e521e7b`) supplies total
|
||
stance over every v0.1 zone plus `unknown`, preserves native enforcement for
|
||
`not-applicable`, and returns `audit_only` for advisory decisions. The required
|
||
live caller check passed through the existing tunnel with command-mode caller
|
||
identity and decision `decision:f3f7c88f9585582a`. The operator config was then
|
||
migrated from the two rejected global keys to `zone_registry_path`, and the
|
||
same live check passed against that real config. Full repo tests pass and
|
||
sign/audit evidence records zone, failure mode, outcome, and decision id.
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T03
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "d04a737b-ecdf-5747-ba25-20dadd99d3bc"
|
||
```
|
||
|
||
**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.
|
||
|
||
**Done 2026-08-22.** `tenancy.yaml` now declares ops-warden as an independently
|
||
governed operational execution unit with its Kubernetes service-account
|
||
binding, and admits it to `z1-operational` at `M1`, `medium`, `internal`.
|
||
`docs/evidence/security-zone-admission-2026-08-22.md` records why this is the
|
||
highest evidenced admission rather than an aspirational `M2`. The declaration
|
||
passes net-kingdom's current `tenancy-posture_v0.1` validator.
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T04
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "c7879127-3dba-55c0-853c-a10775736873"
|
||
```
|
||
|
||
**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.
|
||
|
||
**Done 2026-08-22.** ADR-0006 is marked superseded without rewriting its
|
||
decision. ADR-0009 accepts `security-zones_v0.1` as a consumer, records the
|
||
PDP/PEP split and unknown handling, and is indexed as its successor. `SCOPE.md`,
|
||
`wiki/WorkloadSecurityPosture.md`, `wiki/PolicyGatedSigning.md`, configuration
|
||
guidance, access guidance, and affected playbooks now describe the zone-aware
|
||
control and do not instruct operators to use a global bypass.
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T05
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "1d968627-83f4-59cd-84ca-0f9f35e435ff"
|
||
```
|
||
|
||
**Grade the five exposed lanes now — do not wait for the model.**
|
||
`RISK-F-0003`: `is_high_risk` is `risk == "high"` and `risk` is optional, so the
|
||
14 ungraded lanes never reach the agent read-boundary. Five are `exec_capable`
|
||
and can therefore stream a value to an agent session: `openbao-api-key`,
|
||
`whynot-design-npm-publish`, `key-cape-oidc-login`,
|
||
`issue-core-ingestion-api-key`, `reuse-surface-hub-write-token`.
|
||
|
||
The durable answer is a maturity-derived default (`ZONE-WP-0001-T03`), and it is
|
||
the right answer. It is also months away, and this is a live control gap in a
|
||
shipped ADR. Grade these five explicitly, then the remaining nine.
|
||
|
||
Grading is judgement, not backfill — each lane's grade should be justified in the
|
||
entry, and the operator should sanction the high/standard calls rather than
|
||
having them inferred. Verify separately whether OpenBao's
|
||
`agent-high-risk-boundary` policy covers these paths; `RISK-F-0003` deliberately
|
||
does not assume it does, because those paths were graded by the same omission.
|
||
|
||
**Done 2026-08-19, operator-sanctioned.** All 14 ungraded lanes graded on merit,
|
||
each with its justification in the entry: 17 `high`, 10 `standard`, **0
|
||
ungraded**. `warden access <lane> --fetch` with `WARDEN_AGENT_ID` set now exits 7
|
||
on lanes that were silently outside the control an hour earlier.
|
||
|
||
Graded on merit, not defensively. A first pass marked
|
||
`issue-core-ingestion-api-key` and `reuse-surface-hub-write-token` `high`; the
|
||
existing test `test_high_risk_lanes_classified` asserted the opposite and was
|
||
right — ordinary internal workload secrets are `standard`. Both were regraded
|
||
down. `high` means disclosure into a logged context is damaging beyond what
|
||
rotation recovers: provider keys with spend, admin PATs, tenant commercial data,
|
||
supply-chain publish rights. `inter-hub-bootstrap-ssh` is `high` **conservatively**
|
||
— ops-warden could not establish that no key material moves in the envelope, and
|
||
that is recorded in the entry so it is regraded with evidence rather than assumed
|
||
down.
|
||
|
||
The rule is now `ADR-0007`: build-stage permissiveness stops at credential
|
||
disclosure. Not yet verified: whether OpenBao's `agent-high-risk-boundary`
|
||
policy covers these paths (T06).
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T06
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "4294084c-bf3f-5aa6-b84d-5173121882ff"
|
||
```
|
||
|
||
**Make absence impossible, once the model says what absence means.** Waits on
|
||
`ZONE-WP-0001-T03`. Either invert the default (absent `risk` resolves through the
|
||
lane owner's maturity, per the operator direction) or require `risk` at catalog
|
||
load and in CI. Whichever lands, the failure mode to kill is the current one:
|
||
adding a lane without a grade silently places it outside a control, with nothing
|
||
at load or in CI noticing.
|
||
|
||
Feed back to `ZONE-WP-0001-T03` whether ops-warden can supply the join it needs —
|
||
today no lane references a workload or an environment, so the `M0`–`M3` ladder
|
||
has nothing to attach to from this side.
|
||
|
||
**Enforcement half done 2026-08-20.** It did not need the zone model: `ADR-0007`
|
||
already decided absence is a defect, which is enough to make the code fail safe
|
||
and to gate CI.
|
||
|
||
The real mechanism turned out to be sharper than `RISK-F-0003` described.
|
||
`is_high_risk` was `risk == "high"`, but `risk` was **not** absent at the model
|
||
layer — `RouteEntry.risk` carried a dataclass default of `"standard"`. So an
|
||
omitted grade was not unhandled; it was actively resolved to the permissive
|
||
value. Fail-open by construction, which is why nothing warned.
|
||
|
||
Now: the default is `"ungraded"`, and `is_high_risk` returns true for anything
|
||
not in an explicit low-risk vocabulary (`standard` / `low` / `accepted`). An
|
||
omitted grade **and** a grade from a newer catalog both resolve to high, so the
|
||
boundary fails safe in both directions. `is_graded` exposes the distinction, and
|
||
`test_every_repo_catalog_lane_is_explicitly_graded` is the CI gate that stops an
|
||
ungraded lane being committed. Four regression tests cover it.
|
||
|
||
`accepted` is in the low-risk vocabulary deliberately, ready for the
|
||
maturity-derived default: an experimental-context lane may be explicitly
|
||
accepted, which is a graded decision rather than an omission.
|
||
|
||
**Second layer checked 2026-08-20 — it does not cover them.** The OpenBao side
|
||
was compared statically (policy file vs catalog): `agent-high-risk-boundary`
|
||
denies 5 data paths covering **6** of the **17** high-risk lanes. Eight
|
||
high-risk lanes with concrete KV paths are not denied — and **four of those were
|
||
already graded `high` before the regrade**, so the divergence is pre-existing
|
||
rather than something the grading introduced. It had simply never been
|
||
comparable before.
|
||
|
||
This matters more than the ops-warden half: `warden access` exits 7 for all 17,
|
||
but that only protects the ops-warden path. The OpenBao policy is what protects a
|
||
direct `bao kv get`, which is the actual 2026-07-16 vector.
|
||
|
||
Routed to `risk-nexus` as **`RISK-F-0004`**, `fix_owner: railiance-platform` —
|
||
the policy is theirs, and ops-warden does not amend another repo's control.
|
||
|
||
**Live confirmation done 2026-08-21 — and the blocker was not real.** The
|
||
token was not expired: `bao token lookup` returned a valid `platform-admin`
|
||
token from an OIDC login, and `bao policy read agent-high-risk-boundary`
|
||
succeeded. No `bao login` was needed. Worth recording as a small instance of the
|
||
lesson `.claude/rules/finding-routing.md` already states — *re-read a blocker
|
||
before trusting it*. This one was a stale claim about the world, carried for a
|
||
day in both this workplan and `RISK-F-0009`.
|
||
|
||
The verification script also did not exist. It was described here as "ready",
|
||
and nothing was committed. `scripts/check_agent_read_boundary.py` now exists,
|
||
with tests, and is the invariant `RISK-F-0009` asked for rather than a one-off
|
||
audit: exit 1 when any high-risk lane has no corresponding deny. It prefers the
|
||
deployed policy and falls back to the file only with a loud warning, because
|
||
deployment drift is the thing it exists to catch. Capabilities-only by
|
||
construction — it reads the policy document and lane metadata, never a secret
|
||
value, and never mints a token.
|
||
|
||
Three results, one against ourselves:
|
||
|
||
1. **Coverage confirmed at 6 of 17** against the live policy — the headline was
|
||
right and is no longer inferred from a checkout.
|
||
2. **Six lanes uncovered, not eight.** `RISK-F-0009` counted `openbao-api-key`
|
||
(a `<domain>/<workload>/<bundle>` pattern) and `ops-warden-warden-sign-token`
|
||
(a broker grant, not KV) among the concrete uncovered paths, while its own
|
||
prose said the first was a pattern. Neither can be expressed as a deny.
|
||
Corrected: 6 covered, 6 uncovered, 5 with no address.
|
||
3. **The deployed policy has drifted from the file.** The file denies
|
||
`platform/workloads/core-hub/runtime`; the server does not. No ops-warden
|
||
lane maps there, so our numbers are unchanged — it matters as evidence, since
|
||
`RISK-F-0009` named exactly this divergence as its unconfirmed risk.
|
||
|
||
Still not established, and not ops-warden's to establish: whether any agent
|
||
token carries `agent-high-risk-boundary`, and whether any carries it together
|
||
with a `workload-kv-read-*` policy. Confirming that means minting or inspecting
|
||
tokens — a write against railiance-platform's OpenBao. Exposure stays theoretical
|
||
to the same degree as before.
|
||
|
||
**Platform half closed 2026-08-22.** `RAILIANCE-WP-0022` consumed the generated
|
||
high-risk path input and deployed the completed deny policy. The platform-owned
|
||
invariants report **19 high-risk lanes, 14 concrete entries, 0 uncovered**. A
|
||
dedicated `coding-agent-railiance-platform` AppRole then proved deny-wins with
|
||
exactly `agent-high-risk-boundary` plus one workload read policy: data access was
|
||
denied while metadata remained readable; its single-use test identity was
|
||
self-revoked and no test tokens remained. Decision `f0955252` records the
|
||
operational identity. No KV value was read.
|
||
|
||
The local invariant agrees against the platform policy file: 19 high-risk lanes,
|
||
14 concrete entries covered, 5 without a concrete address, 0 uncovered. This
|
||
session could not independently read the deployed policy, so live-state evidence
|
||
is the platform-owned readback above rather than a claim inferred from the local
|
||
file.
|
||
|
||
**Done 2026-08-22.** The settled model makes the two layers complementary:
|
||
catalog CI continues to require an explicit `risk` field so omission cannot
|
||
silently weaken the agent boundary, while `RouteEntry.risk_for_zone` implements
|
||
the normative maturity-derived fallback for consumers evaluating unresolved or
|
||
future inputs (`z0` + satisfied + synthetic-only → `standard`; satisfied `z3`
|
||
→ `critical`; everything else → `high`). An explicit catalog grade always wins.
|
||
The platform deny policy and its live proof above close the direct-OpenBao half.
|
||
|
||
```task
|
||
id: WARDEN-WP-0032-T07
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "6b4bbbed-2864-5fe9-82be-22ff9543f6f4"
|
||
```
|
||
|
||
**Adopt Repo Manager's workload-reference owner interface.** Accepted with one
|
||
documented amendment against repo-manager revision `890f3b0`: managed
|
||
deployables use the exact `(rapp_id, workload_identity.name)` pair and optional
|
||
deployable name; an independently governed operational execution unit may use
|
||
an exact local `tenancy.yaml` declaration. Native actions, actors, grants,
|
||
patterns, and non-workload resources are explicitly `not-applicable`; unresolved
|
||
workload-applicable references remain `unknown`. No path, owner name, or
|
||
repository-name inference is allowed.
|
||
|
||
Every one of the 27 catalog lanes now carries an explicit `workload_ref`: 3
|
||
resolved (2 exact managed RAPP references and ops-warden's direct operational
|
||
declaration), 17 unknown with reasons, and 7 not-applicable with reasons.
|
||
`scripts/report_workload_join.py` resolves only those explicit references,
|
||
Repo Manager validates the interface and resolves both managed tuples exactly,
|
||
and regression tests reject malformed or inferred joins. This incorporates
|
||
net-kingdom's draft-12 correction received 2026-08-22: local tenancy declaration
|
||
is not an escape hatch for a managed running deployable.
|
||
|
||
## Related
|
||
|
||
- `zone-engine` `ZONE-WP-0001` — the model, and where this work is led from
|
||
- `ADR-0006` — enforcement is zone-scoped, never a global flag
|
||
- `WARDEN-WP-0031` — the deferred flip and its readiness evidence
|
||
- `net-kingdom` `tenancy-posture_v0.1` draft-9 Decisions 5.6, 8.4.1, 8.4.2 — canon's
|
||
answer to `ZONE-WP-0001-T01`; enforcement stance is a sibling standard, not a
|
||
seventh axis, and the declaration surface is `tenancy.yaml`
|