# Security Layer Model v0.6 — ops-warden's review **Date:** 2026-08-29 **Reviewed:** `security-layer-model_v0.6.md` (proposed), plus v0.5 and the companion **Prior positions:** `ADR-0010` (v0.1 assent); `history/2026-08-29-layer-model-v04-review.md` **Outcome:** no objection; one conformance action taken, two findings, one accepted SHOULD. --- ## Disposition of ops-warden's v0.4 findings All three were acted on, two of them exactly as recommended. | Finding | Outcome | | --- | --- | | §9.1 forces a false `pending` onto working capability | **Adopted** — v0.5 split it into `pending` and `declared-gap`, credited to ops-warden | | §5 scope undefined for uncatalogued infrastructure | **Adopted** — "Tooling-layer system" now means a §4 Tooling row; the State Hub case is recorded, not policed | | §9.6 atomicity lands on ops-warden's signing lane | **Ruled** — the load-bearing / attributive distinction, with ops-warden's `# audit must not block signing` named as the estate's live example | The §9.6 ruling deserves a note, because it went in ops-warden's favour and that is a reason to check it rather than accept it. The test is *"no control branches on its presence"*. Verified: the only consumer of `audit.jsonl` is `warden activity` (`cli.py`), which displays. Nothing gates on a signing record — not the agent read-boundary, not `warden plan`, not the scorecard. The lane is genuinely attributive and the trade is legitimate on the standard's own terms. The two obligations that attach — declare it, never claim completeness — were already met in `wiki/AuditTrail.md`, now updated to record the ruling rather than the open question. **If a future ops-warden control ever gates on this trail, the trade has to be revisited before that ships**, and that is recorded there. `layer.yaml` is named in §11 as the estate's reference declaration form, including the "record non-Tooling clients so the check is total" property. Offered again to the repositories that have yet to declare. --- ## Conformance action taken — the stance map was not published §6.4 obligation 3 requires a declared unreachable-engine stance that is total, per zone, with no implicit default, *"published rather than held in code comments"* — and §6.4 requires **every** PEP-shaped consumer to publish its map so the maps can be inventoried. `ADR-0009` is named as the reference shape. ops-warden was not doing this. The map lived in `PolicyConfig.failure_modes`, a dataclass default in `src/warden/config.py`. That is not a code *comment*, but it is not published either — it is merely written down, and a consumer of the estate had no way to read ops-warden's stance without reading ops-warden's source. Published as `pep-stance.yaml`, with the property that makes publishing worth anything: `tests/test_layer_conformance.py` asserts the published map is **equal to the shipped default**. A published map that may drift from the code is worse than no map, because it invites reliance it cannot support. The file also records the obligation-2 position (verdict never cached; input claims cached under their own freshness rules) and the obligation-4 bound (§9.6 attributive). --- ## Finding 1 — §6.4 obligation 1 contradicts obligation 3, and ops-warden is the instance > **1. No side effect without a decision record.** A PEP MUST NOT perform the > protected action unless it holds a decision from `access-engine` identifying the > request it was rendered for. > **3. A declared unreachable-engine stance (§9.3):** total, per zone... `ops-warden` > `ADR-0009` is the reference shape. These cannot both be absolute. ops-warden's declared stance — blessed by §9.3 as *"the only thing left"* when there is no engine to ask — is `fail_open` for `z0`–`z2` and `unknown`. Applying it means issuing a certificate **without holding a decision**, which obligation 1 forbids without qualification. So the same section names ops-warden as the reference shape for obligation 3 while obligation 1 makes ops-warden's shipped behaviour a violation. §9.3 settled the substance; §6.4 restates it in a form that takes it back. **Recommendation.** Bound obligation 1 by obligation 3: > A PEP MUST NOT perform the protected action unless it holds a decision from > `access-engine` identifying the request it was rendered for, **or its declared > §9.3 stance for the applicable scope permits proceeding without one and the > application of that stance is recorded in place of the decision**. This is not a weakening. It is stricter than today's text in the case that matters: it makes the *recorded application of the stance* mandatory, rather than leaving "no decision record" as a silent state. ops-warden already does this — `ca.py` writes `policy_zone`, `policy_failure_mode` and `policy_decision_id` (present only where a decision was rendered) into both the signatures log and `audit.jsonl`, per `ADR-0009` rule 4: *a fail-open signing result is metadata, not silence*. This is the same shape as the v0.4 §9.1 finding: a rule written for the clean case, correct there, producing a false result on the adjacent case the standard has already sanctioned elsewhere. --- ## Finding 2 — §6.4 creates a register that §13 does not implement §6.4: *"Every PEP-shaped consumer MUST publish its stance map, and those maps MUST be inventoried — in `maturity-engine` once it exists, **in §13 until then**."* §13 contains no stance-map rows. It records declared contacts and unowned capabilities; there is no column, row, or section for a PEP stance. So the obligation names a register that does not exist yet, and the failure mode §6.4 itself warns about — *"`z0`–`z2` and unknown fail open" becoming the estate's real policy without anyone having compiled it* — is exactly what the missing register permits. **Recommendation.** Either add a stance-map table to §13 with the same state/owner-status discipline the gap table has, or state that the inventory waits for `maturity-engine` and mark the obligation pending under §9.1's own logic — a requirement whose register does not exist is a capability catalogued without a surface. ops-warden's row is ready to paste: | PEP | Protected action | Scope | Stance | Published | | --- | --- | --- | --- | --- | | `ops-warden` | SSH certificate issuance | security-zone | open `z0`–`z2`+unknown, closed `z3`/n-a | `ops-warden/pep-stance.yaml` | The second half matters more than the first: **ops-warden is currently the only PEP that has published one**, so an inventory today would contain one row and that is itself the finding. `ops-mason` is named PEP-shaped in the same paragraph. --- ## Accepted, not yet done — §9.6 emission cadence §9.6: *"A source SHOULD declare an expected emission cadence, and a drop below it SHOULD become a finding in its own right."* ops-warden declares none. This is a genuine SHOULD and the reasoning behind it is sound — it converts the suppression blind spot into something detectable without any Tooling contact, because the source publishes its own stream. It is not done here because a cadence asserted without evidence is worse than none: ops-warden's signing volume is operator-driven and bursty, and a fabricated baseline would generate findings that mean nothing. Deriving one from the existing trail is tractable and is recorded as ops-warden's to do, not gate-house's to chase. --- ## On the pace Six versions in two days, with four repositories' findings absorbed and credited, is the §12 loop working at a rate the estate has not seen before. Two cautions, offered as an interested consumer rather than as objections: 1. **§13 already says it should not be statute, and it is right.** The register has grown every version. Moving it to `maturity-engine` is the stated plan; until that exists, each version of the standard is also a snapshot of a backlog, and the two have very different review intervals. 2. **The standard is `proposed` again at v0.6**, and the four repositories that assented did so to v0.1. ops-warden's `ADR-0010` assent covers the three boundary items, and nothing in v0.2–v0.6 has disturbed them — the layer, the lane/rule demarcation, and doctrine-versus-runbook all stand. But the `assented_by` list carries assent forward across five revisions, and a reader could take it as assent to the current text. Worth distinguishing *assented to the boundary* from *reviewed the current revision*; ops-warden has now done both, and this note is the second.