An inflated count in a document whose subject is accuracy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
232 lines
12 KiB
Markdown
232 lines
12 KiB
Markdown
# Estate partition — ZONE-WP-0001-T02
|
||
|
||
**Date:** 2026-08-19 · **Corpus:** ops-warden `registry/routing/catalog.yaml`
|
||
(27 entries), `inventory.yaml` (4 actors), `registry/policy/security-posture.yaml`
|
||
(3 env postures, 4 maturity levels).
|
||
|
||
The test set by T02: *the model must partition what exists without a residue of
|
||
unexplained exceptions, and the exceptions found are the most informative
|
||
output.* This is the raw result, before any model is fitted to it.
|
||
|
||
---
|
||
|
||
## 1. What the data actually says
|
||
|
||
Cross-tabulating the three declared fields that could plausibly drive
|
||
membership — `delegation.mode`, `risk`, `exec_capable` — fills **9 of 27
|
||
possible cells**. The estate clusters hard.
|
||
|
||
| delegation | risk | exec_capable | n | character |
|
||
| --- | --- | --- | --- | --- |
|
||
| `permanent` | ungraded | — | 1 | The one lane ops-warden decides (`ssh-cert-host-access`) |
|
||
| `native` | ungraded | — | 7 | Pure pointers: route to an owner, nothing executes |
|
||
| `native` | ungraded | `false`/`true` | 2 | Owner-fronted exec (`whynot-design-npm-publish`, `audit-core-senders`) |
|
||
| `native` | high | `false` | 1 | `database-dynamic-credentials` — owner-fronted, dangerous |
|
||
| `interim` | ungraded | `true` | 4 | **ops-warden proxying, ungraded** |
|
||
| `interim` | standard | `false` | 2 | Interim, graded, not proxyable |
|
||
| `interim` | high | `false` | 2 | Interim, dangerous, routed only |
|
||
| `interim` | high | `true` | 8 | **ops-warden proxying a high-risk credential for an absent owner** |
|
||
|
||
The three fields are **not independent**, and that is the finding. Danger
|
||
concentrates in `interim`: 10 of the 11 high-risk lanes are interim, and 8 of
|
||
those are `exec_capable`. `permanent` and `native` are almost entirely benign.
|
||
|
||
**Delegation mode is doing most of the discriminating work.** It was introduced
|
||
by WP-0030 to answer a governance question — *should ops-warden own this?* — and
|
||
it turns out to predict operational danger better than the field named `risk`.
|
||
|
||
## 2. The bands that exist
|
||
|
||
Four, derived rather than invented. Every one of the 27 lanes lands in exactly
|
||
one.
|
||
|
||
| Band | n | Defining property | What it means for a control |
|
||
| --- | --- | --- | --- |
|
||
| **Decided** | 1 | `warden_executes: true` — ops-warden is the decision point | The only place a pre-sign gate can bite at all |
|
||
| **Fronted** | 10 | `delegation.mode` is `native` — the owner has a front door | Stance is the *owner's*; ops-warden holds nothing |
|
||
| **Covered** | 12 | `interim` and `exec_capable: true` — ops-warden proxies a value it does not own | The band that actually needs rigidity, and the band a refactor most needs relaxed |
|
||
| **Signposted** | 4 | `interim`, not `exec_capable` — routed, nothing flows | Advisory at most; there is no value to leak |
|
||
|
||
The interesting boundary is **Covered vs Fronted**, and it is not a risk
|
||
judgement — it is a statement about *whether the owning component exists yet*.
|
||
That is why it moves over time and why bands must be re-derived, not assigned
|
||
once.
|
||
|
||
## 3. The existing controls already imply bands — and they disagree
|
||
|
||
Before any zone model, ops-warden's three controls each cut the estate
|
||
differently:
|
||
|
||
| Control | Lanes touched | Selector |
|
||
| --- | --- | --- |
|
||
| flex-auth pre-sign gate | **1** | `warden_executes` |
|
||
| fetch policy gate | **13** | `exec_capable` |
|
||
| agent read-boundary (`ADR-0004`) | **11** | `risk == "high"` |
|
||
| `warden plan` escalation | 27 | all |
|
||
|
||
Only **8 lanes** are in both the fetch gate and the read-boundary. The controls
|
||
were built independently and their scopes were never reconciled. A zone model
|
||
that assigns one zone per lane and expects all controls to agree with it will
|
||
misfit immediately — which answers a question T03 was going to have to ask:
|
||
**stance is per control per zone, never per zone alone.**
|
||
|
||
## 4. The residue — and it is the most valuable output
|
||
|
||
**14 of 27 lanes carry no `risk` value at all.**
|
||
|
||
This is not a modelling inconvenience. `is_high_risk` is `risk == "high"`
|
||
(`routing/models.py:123`), so an ungraded lane never triggers the agent
|
||
read-boundary. Five of the fourteen are `exec_capable: true`, meaning
|
||
`warden access --fetch` can stream a real value for them 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`.
|
||
|
||
`ADR-0004` reads as a categorical rule. The implementation is an opt-in list,
|
||
and absence fails open.
|
||
|
||
**Routed to `risk-nexus` as `RISK-F-0003`.** It is a defect in a shipped
|
||
control, not a known gap being worked — the distinction ops-warden's own
|
||
finding-routing rule draws. Severity is risk-nexus's to set.
|
||
|
||
For this task it also means: **a zone model cannot be derived from `risk` as it
|
||
stands.** Half the corpus is unlabelled on that field, and grading it is real
|
||
judgement, not backfill.
|
||
|
||
Two further gaps, less severe but structural:
|
||
|
||
- `warden_role` and `has_rotation` are **derived at load, not declared** — they
|
||
are absent from every raw entry despite appearing in `warden route --json`. A
|
||
membership compiler must read the model, not the file.
|
||
- The posture registry (`env_postures`, `M0`–`M3`) and the catalog share **no
|
||
join key**. No lane references a workload or an environment. They are
|
||
currently disjoint vocabularies.
|
||
|
||
## 5. Answers to T02's questions
|
||
|
||
### Is a zone a property of the actor, the lane, the workload, or the moment?
|
||
|
||
> **Corrected 2026-08-19 by operator direction, after this analysis was
|
||
> written.** The answer below ("the lane") mistook the corpus for the subject.
|
||
> **Security policy is always about the actual workload.** ops-warden's catalog
|
||
> is a credential surface, not a workload inventory, so lane properties were the
|
||
> only thing available to partition — and partitioning what is available is not
|
||
> the same as finding the policy subject. The bands in §2 stand as an accurate
|
||
> description of ops-warden's credential surface and remain useful membership
|
||
> *inputs*; they are not zones. See §7.
|
||
|
||
**The lane**, on the evidence available in this corpus. Every field that discriminates —
|
||
`delegation.mode`, `exec_capable`, `risk` — is a lane property. The actor
|
||
inventory holds 4 actors mapping to a single lane and cannot carry a partition.
|
||
No lane references a workload.
|
||
|
||
With two qualifications the data forces:
|
||
|
||
- **The caller is a modifier, not the zone.** The read-boundary keys on
|
||
`WARDEN_AGENT_ID` — a property of *who is asking*, orthogonal to the lane. A
|
||
zone says what the lane requires; the caller decides which requirement
|
||
applies. Collapsing them would make one lane need two zones.
|
||
- **The moment is a different object, confirmed.** Nothing in the corpus
|
||
represents it. `delegation.blocked_on` carries a free-text claim with a
|
||
`reviewed` date and no expiry — precisely the "expiry by intention" shape
|
||
`ZONE-WP-0001-T04` must not reproduce. A time-boxed relaxation is an
|
||
**exception against a zone**, never a zone.
|
||
|
||
### Do zones compose with, or fold in, environment posture and `M0`–`M3`?
|
||
|
||
**Compose — and the composition cannot be built yet.** They are per-workload;
|
||
zones as derived here are per-lane; and there is **no join key between them in
|
||
any registry today**. Folding them in would require inventing a lane→workload
|
||
mapping that does not exist, which is fabrication under §6.
|
||
|
||
The honest sequence: zones stand alone on lane properties now, and a join is
|
||
proposed only when something actually declares it. (`organization_posture` was
|
||
already ruled out of the declaration entirely by net-kingdom — it is an input.)
|
||
|
||
### Reefs
|
||
|
||
Struck by net-kingdom. Per `tenancy-posture` Decision 8.4.1, substrate location
|
||
is never by itself evidence for a level. The unreconciled pair is reef ↔ `P`/`V`
|
||
and it is canon's, tracked as `NK-WP-0027`.
|
||
|
||
## 6. What this hands to T03 and T04
|
||
|
||
- Four bands, each lane in exactly one, derived from declared fields.
|
||
- **Stance must be per control per zone** — the existing controls demonstrably
|
||
disagree about scope.
|
||
- **`Covered` is the band the model exists for**: 12 lanes where ops-warden
|
||
proxies what it does not own, holding the highest concentration of high-risk
|
||
`exec_capable` lanes, and the band a deep refactor most needs relaxed.
|
||
- **`risk` is not usable as a membership input until the 14 ungraded lanes are
|
||
graded** (`RISK-F-0003`). `delegation.mode` is usable today and is a better
|
||
predictor.
|
||
- Membership must be computed from the loaded model, not read from raw YAML.
|
||
|
||
|
||
---
|
||
|
||
## 7. Correction — the subject is the workload, and a zone is an admission standard
|
||
|
||
Operator direction, 2026-08-19, after §1–§6 were written:
|
||
|
||
> *Security policy is always about the actual workload. The repository providing
|
||
> the software may suggest security policy for running workloads in different
|
||
> situations, but the workload — and whoever is responsible for it — defines the
|
||
> level of scrutiny. Some zones may well define standards that have to be met in
|
||
> order to run as a workload in that zone.*
|
||
|
||
This reverses the direction the analysis above assumed. It had zones as a
|
||
**classification derived from** properties. They are **bands with admission
|
||
standards**: a workload does not get labelled with a zone, it *qualifies* to run
|
||
in one.
|
||
|
||
### Three roles, not one
|
||
|
||
| Role | Who | Authority |
|
||
| --- | --- | --- |
|
||
| **Suggests** | The repository providing the software | Recommends a posture for running its software in given situations. A recommendation, never a determination — it does not know where its software will run |
|
||
| **Declares** | The workload and its responsible party | Sets the level of scrutiny actually applied. **This is the policy subject.** |
|
||
| **Requires** | The zone | Defines the standard a workload must meet to be admitted. A floor, not a label |
|
||
|
||
### This is canon's existing mechanism, not a new one
|
||
|
||
`tenancy-posture_v0.1` **Decision 8.2 — split authority, machine-reconciled**
|
||
already partitions authority this way: the package repo owns substrate numbers
|
||
and enforcement, *"the consuming repo owns its workload requirements"*, and a
|
||
tier minimum is owned separately and **joined by machine** at definition and
|
||
whenever either side changes — because *"a machine-checkable constraint must not
|
||
depend on somebody remembering to collect a signature."*
|
||
|
||
And Decision 5.6, ruling on this very standard, already said stance *"behaves
|
||
like a tier minimum under Decision 8.2 — asserted elsewhere, joined by machine."*
|
||
|
||
So the zone model does not need a new prescription mechanism. It needs to **be**
|
||
a tier minimum: the zone asserts a floor, the workload asserts its posture, and
|
||
the join is mechanical. That also resolves the grade-versus-acceptance split
|
||
raised for T03 — they are simply the two sides of the join.
|
||
|
||
### What this does to the bands in §2
|
||
|
||
They survive as *inputs*, demoted from conclusions. `Decided` / `Fronted` /
|
||
`Covered` / `Signposted` accurately describe ops-warden's credential surface and
|
||
still predict where danger concentrates. What they cannot do is name the entity
|
||
policy applies to, because ops-warden's catalog contains no workloads.
|
||
|
||
The missing join found in §4 is therefore not a tidy-up. **It is the model.**
|
||
|
||
> **Corrected 2026-08-20.** "No registry carries a join key" was too strong — it
|
||
> was concluded from ops-warden's catalog alone, the one place a *workload*
|
||
> declaration would not live. `rapp-*/declarations/rapp.yaml` declares
|
||
> `workload_identity` with `data_classification` and `criticality` for eight
|
||
> workloads, and ops-warden's `dataclass_floor` already maps classification to
|
||
> `M0`–`M3`. The chain exists and spans two repos. What is genuinely missing is
|
||
> an explicit `workload:` field on catalog entries — the key is currently only
|
||
> derivable by parsing `path_template`, whose convention is inconsistent. See
|
||
> `ZONE-WP-0001-T03`.
|
||
|
||
### Build stage
|
||
|
||
The organization is in `build`. The default stance is therefore permissive, and
|
||
that is a positional fact rather than a concession: `ADR-0006` deferred a global
|
||
gate for exactly this reason. Zones tighten by **admission to a zone**, not by
|
||
raising a global floor — which is what makes the model compatible with deep
|
||
refactoring instead of hostile to it.
|