From 8e1b6211162c400184e8981b97a5ea39cc98d4cc Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 9 Sep 2026 14:42:20 +0200 Subject: [PATCH] docs: assent to v0.8 obligation 3, and price its adoption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gate-house circulated security-layer-model v0.8, whose §6.4 obligation 3 makes our `unknown: fail_open` cell non-conformant, and asked to be argued with rather than obeyed. Finding 1 -- assent. They wrote the falsifier into GH-DEC-2026-009: a scope genuinely unknown AND genuinely low-consequence, expected to be a §5.1 read-only diagnostic. We looked and do not have one. The stance map governs `warden sign` -- a credential-issuing side effect -- so §5.1 does not reach it and the argument stands. Being unclassifiable must not buy permissiveness. Finding 2 -- adopting it today would be a global fail-closed flag in all but name. Of four signing targets, zero resolve to a zone and three are `unknown`, so the cell would fail closed on essentially every certificate during a flex-auth outage -- including the SSH certificate needed to reach the host and repair flex-auth. That is exactly ADR-0006's rejected configuration reached by another route. Asked for a dated transition gated on coverage, or failing that for §13.1 to record coverage alongside stance: a row reading `unknown: fail_closed` while every target is unknown is conformant and misleading. Not flipping the cell. It is a proposed standard, 18 of our 18 unknown lanes are unknown because another repo has not declared, and ADR-0009 rule 3 forbids closing that with inference -- a stricter stance is not a licence to manufacture the membership that makes it survivable. WARDEN-WP-0040 records the order: classify the continuity path, raise coverage by asking owners, then supersede ADR-0009's unknown row. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C Assistant: claude-code Assistant-Model: opus Assistant-Process: 1276224@bnt-lap001 Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3 --- history/2026-09-09-layer-model-v08-review.md | 119 +++++++++++++++++ ...-0040-unknown-zone-fail-closed-adoption.md | 122 ++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 history/2026-09-09-layer-model-v08-review.md create mode 100644 workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md diff --git a/history/2026-09-09-layer-model-v08-review.md b/history/2026-09-09-layer-model-v08-review.md new file mode 100644 index 0000000..bc04aa6 --- /dev/null +++ b/history/2026-09-09-layer-model-v08-review.md @@ -0,0 +1,119 @@ +# security-layer-model v0.8 — ops-warden review + +**Date:** 2026-09-09 +**Reviewing:** `net-kingdom/canon/standards/security-layer-model_v0.8.md` (status +`proposed`, net-kingdom@66eeaba), circulated for assent by gate-house +**Prior reviews:** `2026-08-29-layer-model-v04-review.md`, `-v06-review.md`, +`-v07-scope-intent-assessment.md` + +## The cell in question + +v0.8 §6.4 obligation 3 adds: *unknown is not a zone and MUST resolve to +`fail_closed`.* `pep-stance.yaml` declares `unknown: fail_open` under `ADR-0009`. +§13.1 records the cell as non-conformant. + +## Finding 1 — assent. The rule is right and our falsifier check fails. + +gate-house wrote the falsifier into GH-DEC-2026-009's reversal: a scope that is +genuinely unknown **and** genuinely low-consequence, where failing closed costs +availability with no security gain. Their expectation is that any such path is a +§5.1 read-only diagnostic carrying no PEP obligation at all. + +We looked for one on our side and do not have it. The stance map governs exactly +one protected action — `warden sign`, SSH certificate issuance. That is a +credential-issuing side effect, not a diagnostic; §5.1 does not reach it. So the +predicted escape hatch is absent here, and the argument stands unrebutted on its +own terms: + +- §9.3 licenses trading availability for openness **per zone**, knowingly, for a + named scope. Where the scope is unknown that trade was never made for the + request in hand, so resolving permissively does not extend a considered + decision — it invents one. +- Unknown is the cheapest state to induce. Our own `unknown` reasons are + `workload_resolution_absent` and `catalog_applicability_absent` — an + unregistered workload or a missing declaration, neither of which requires a + credential to arrange. + +We accept that being unclassifiable must not buy permissiveness. The cell is +wrong as doctrine. + +## Finding 2 — the rule is right and adopting it today would be a global fail-closed flag in all but name + +This is the finding we would like recorded, and it is about adoption cost, not +about the rule. + +The stance map applies only when the engine is unreachable, so the cell's bite is +proportional to how much of the target population sits in `unknown`. Measured +today: + +| Population | Resolved to a zone | `unknown` | `not-applicable` | +| --- | --- | --- | --- | +| Signing targets (actor resources in the flex-auth snapshot) | **0** | **3** | 1 | +| Routing catalog lanes | 3 | 18 | 12 | + +Every signing target that resolves at all resolves to `unknown`. So +`unknown: fail_closed` adopted today does not fail closed on an edge case; it +fails closed on **essentially every certificate ops-warden issues** whenever +flex-auth is unreachable. + +That is the precise configuration `ADR-0006` rejected and `ADR-0009` replaced: one +value making the decision engine a uniform dependency of every signing path, +*including the continuity paths needed to repair that dependency*. If flex-auth is +unreachable and the operator needs an SSH certificate to reach the host and +restore it, `unknown: fail_closed` denies the certificate — and the target is +`unknown` precisely because nobody has classified the repair path. + +The zone model already answers this: classify continuity paths `z2-continuity`, +whose stance is `fail_open`, and the deadlock does not arise. We accept that as +the right answer. The point is that it is *work not yet done*, and the reason it +is not done is not ours to fix — 18 of our 18 unknown lanes are unknown because +another repo has not published an authoritative workload identity declaration. +`ADR-0009` rule 3 forbids us from closing that gap with inference, correctly. + +So as written, v0.8 §6.4 obligation 3 transfers an availability cost onto the +consumer for a classification gap the consumer cannot close alone, and it does so +at the moment of assent rather than at the moment the gap closes. + +**What we ask for**, in preference order: + +1. **§6.4 obligation 3 names a transition.** A consumer may declare + `unknown: fail_open` as a dated, published transitional state with a + classification-coverage figure attached, converting to `fail_closed` on + coverage rather than on calendar. This keeps the doctrine and prices the + adoption honestly. +2. Failing that, **§13.1 records classification coverage alongside stance.** A + register row reading `unknown: fail_closed` while 100% of that consumer's + targets are unknown is conformant and materially misleading; a reader cannot + tell a strict consumer from an unclassified one. This is the same defect + §11's *published map equals shipped behaviour* rule exists to prevent, one + level up: the map is now accurate about itself and inaccurate about its + effect. + +## Finding 3 — §12's derived-artifact rule, small and in agreement + +Six instances in one week matches our experience. `registry/generated/high-risk-data-paths.yaml` +carries `catalog_revision` and a `catalog_dirty` flag for exactly the reason §12 +now generalises: a derived artifact whose revision does not describe the file it +came from is worse than one with no revision, because the stale one is trusted. +No change requested; recording the agreement since the rule is being generalised +from other repos' incidents. + +## What ops-warden is doing about it + +Not flipping the cell on a `proposed` standard, and not flipping it before +coverage exists — that ordering is `ADR-0006`'s whole holding. `WARDEN-WP-0040` +records the adoption sequence: raise signing-target classification coverage +first, then convert the cell, with the deadlock case classified before rather +than after. If v0.8 is accepted with obligation 3 unchanged, ops-warden's cell +remains a **declared gap** under §11 — tracked non-conformance with a named +owner and a route, which is the mark §9.1 exists for and which we argued for in +the v0.6 round. + +## Axis declaration (second change touching us) + +`pep-stance.yaml` already carries `scope: security-zone`. No change needed. We +agree with rejecting a forced migration onto zones — secrets-engine scoping by +catalog stage is an accurate statement about their control, and making them +assert a zone they cannot know would trade a real fact for a conformant fiction. +The unavailability of cross-axis aggregation is better recorded than papered +over, and §13.1 now says so. diff --git a/workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md b/workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md new file mode 100644 index 0000000..c20c5e8 --- /dev/null +++ b/workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md @@ -0,0 +1,122 @@ +--- +id: WARDEN-WP-0040 +type: workplan +title: "Adopt unknown -> fail_closed behind signing-target classification coverage" +domain: infotech +repo: ops-warden +status: proposed +owner: ops-warden +topic_slug: netkingdom +planning_priority: P1 +depends_on_workplans: + - WARDEN-WP-0032 + - WARDEN-WP-0034 +created: "2026-09-09" +updated: "2026-09-09" +--- + +# WARDEN-WP-0040 — `unknown` → `fail_closed`, in the right order + +security-layer-model v0.8 §6.4 obligation 3 (proposed, 2026-09-06) rules that +`unknown` is not a zone and must resolve to `fail_closed`. ops-warden's +`pep-stance.yaml` declares `unknown: fail_open` under `ADR-0009`. + +**We agree with the rule.** `history/2026-09-09-layer-model-v08-review.md` records +the assent and why our falsifier check failed: the cell governs certificate +issuance, not a §5.1 read-only diagnostic, so nothing rescues it. + +**We disagree with adopting it first.** Measured 2026-09-09: of four signing +targets, zero resolve to a zone, three are `unknown`, one is `not-applicable`. +Flipping the cell today makes flex-auth a hard dependency of essentially every +certificate — `ADR-0006`'s rejected configuration, reached by a different route, +including the continuity path needed to repair flex-auth itself. + +So: coverage first, then the cell. That ordering is the whole holding of +`ADR-0006` and the reason `ADR-0009` replaced a global switch with a zone map. + +## Tasks + +```task +id: WARDEN-WP-0040-T01 +status: todo +priority: high +``` + +**Classify the continuity path before anything else changes.** + +The deadlock is specific and worth naming before it is designed around: flex-auth +unreachable → operator needs an SSH certificate to reach the host → target is +`unknown` because nobody classified the repair path → `fail_closed` denies it. + +`z2-continuity` exists for this and its stance is `fail_open`, so the fix is +classification, not an exception. Determine which actor(s) constitute the +repair path, establish whether the declaration is ops-warden's to make (our own +`tenancy.yaml` covers ops-warden as a workload; the actors' target workloads may +not be ours), and route what is not. + +Blocks T03. Converting the cell with the repair path unclassified is the one +outcome this workplan exists to prevent. + +```task +id: WARDEN-WP-0040-T02 +status: todo +priority: high +``` + +**Raise signing-target coverage, by asking owners — never by inferring.** + +Three actor resources report `workload_resolution_absent`: +`agt-codex-interhub-bootstrap`, `agt-state-hub-bridge`, `atm-backup-daily`. +Their owners (ops-bridge and the backup execution unit among them) have not +published an authoritative workload identity declaration. + +`ADR-0009` rule 3 forbids closing this with path or repository-name inference, +and that prohibition holds under pressure from this workplan specifically — +adopting a stricter stance is not a licence to manufacture the membership that +makes it survivable. + +Route to each owner with the concrete consequence: while the declaration is +absent their actor cannot be issued a certificate during a flex-auth outage once +the cell converts. That is a better ask than a generic request to publish a +declaration, and it is true. + +Report coverage with `scripts/report_workload_join.py`; this task is done when +coverage is stated, not when it reaches a threshold — the threshold is T03's +gate, and owners may legitimately decline. + +```task +id: WARDEN-WP-0040-T03 +status: wait +priority: high +``` + +**Convert the cell and supersede `ADR-0009`'s unknown row.** + +Gated on T01, and on v0.8 (or its successor) reaching `accepted`. Do not convert +against a `proposed` standard. + +`ADR-0009` is `owner: ops-warden`, so changing it means a superseding ADR, never +an in-place edit (`.claude/rules/architecture.md`). The superseding record should +carry the v0.8 argument rather than restate it: unknown is not a zone, so a §9.3 +per-zone trade was never made for that request. + +`pep-stance.yaml` is asserted equal to `PolicyConfig.failure_modes` by +`tests/test_layer_conformance.py`, so the map and the code convert in one commit +or the test fails — which is the property that makes the map worth publishing. + +```task +id: WARDEN-WP-0040-T04 +status: todo +priority: medium +``` + +**Return findings to gate-house and track the transition ask.** + +Sent 2026-09-09 with the review. Two asks, in preference order: obligation 3 +names a dated transitional state gated on coverage; or failing that, §13.1 +records classification coverage alongside stance, so a register row cannot read +`unknown: fail_closed` while every target is unknown. + +If both are declined, that is an answer and this workplan proceeds unchanged — +the cell stays a **declared gap** under §11 with this workplan as its route, +which is what the `declared-gap` mark (our own v0.6 finding) exists to express.