# ops-warden — PEP unreachable-engine stance map # # Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md §6.4, §9.3, §9.7 # Rule of record: docs/adr/ADR-0009 # Validate: pytest tests/test_layer_conformance.py -k stance # # §6.4 obligation 3 requires a declared unreachable-engine stance that is total, # scoped per zone, carries no implicit default and no per-call discretion, and is # "published rather than held in code comments". §6.4 further requires every # PEP-shaped consumer to PUBLISH its map so the maps can be inventoried. This # file is ops-warden's, published because a map that lives only in a dataclass # default is not published — it is merely written down. # # The property that makes this worth reading: it is asserted equal to the shipped # default in src/warden/config.py (PolicyConfig.failure_modes) by # tests/test_layer_conformance.py. A published map that may drift from the code # is worse than none, because it invites reliance it cannot support. schema_version: "0.1" framework: netkingdom-security-layer-model # v0.7 is the accepted standard and the one in force. v0.8 is `proposed`: its # assent round closed 2026-09-09 (GH-DEC-2026-011) with nine corrections applied, # but the version is not yet accepted, so this declaration stays pinned to what # binds. The one cell v0.8 would change is marked inline below rather than # silently pre-adopted. standard_version: "0.7" standard_version_reviewed: "0.8" # reviewed and assented; see history/2026-09-09-layer-model-v08-review.md repository: ops-warden pep_shape: true declared_by: docs/adr/ADR-0009 protected_action: "SSH certificate issuance (warden sign / cert_command)" decision_engine: access-engine # flex-auth until the governed rename scope: security-zone # security-zones_v0.1 membership of the TARGET workload # Total by construction: every zone in security-zones_v0.1, plus the two # non-zone outcomes. No implicit default — an unlisted value is a config error, # not a permissive fallback. stance: z0-experimental: fail_open z1-operational: fail_open z2-protected: fail_open z2-continuity: fail_open z3-critical: fail_closed # DECLARED GAP under security-layer-model v0.8 §6.4 obligation 3 (GH-DEC-2026-011, # net-kingdom@64394e9): unknown is not a zone and MUST resolve to fail_closed. # ops-warden ASSENTED to that rule — we went looking for the §5.1 read-only # diagnostic its reversal clause predicts and do not have one, because this map # governs `warden sign`, a credential-issuing side effect. # # The cell has not been flipped, and the reason is measured rather than argued: # 0 of 3 signing targets resolve to a zone, so converting today would fail closed # on essentially every certificate whenever the engine is unreachable — including # the certificate an operator needs to reach the host and repair it. That is # ADR-0006's rejected configuration reached from another direction. # # We asked for a coverage-gated transitional fail_open and were DECLINED: a # sanctioned transitional fail_open is indistinguishable at runtime from the # stance the rule forbids. Our second preference was adopted instead — §13.1 now # carries a Coverage column, and this repo's figures are its first entries. # # So this is tracked non-conformance with a route, not an exemption. # Route: WARDEN-WP-0040. Register row: §13.1, marked. unknown: fail_open # non-conformant at v0.8; see above not-applicable: fail_closed # What happens when the stance is applied. §6.4 obligation 1 requires a decision # record for a protected side effect; where the engine is unreachable there is no # decision to hold, so ops-warden records the APPLICATION OF THE STANCE instead. # See the assessment note: obligation 1 as written admits no such case. on_apply: recorded_fields: - policy_zone - policy_failure_mode - policy_decision_id # present only where a decision was actually rendered - outcome written_to: - "signatures log (src/warden/ca.py)" - "audit.jsonl (src/warden/audit.py)" never_recorded: "any secret material, any certificate private key" # §6.4 obligation 2 — the verdict is never cached. Input claims (zone membership, # compiled from the flex-auth registry snapshot) are cached under their own # freshness rules; the answer is not. # Classification coverage, published beside the stance because v0.8 §6.4 # obligation 3 now requires it and because ops-warden asked for the column. # Coverage is DISCLOSURE, never a transitional licence: it does not soften this # map's stance, does not gate it, and never makes the marked cell conformant. # Self-measured; regenerate with `python scripts/report_coverage.py`. classification_coverage: measured: "2026-09-09" attribution: self-measured signing_targets: resolved: 0 unknown: 3 not_applicable: 1 routing_lanes: resolved: 3 unknown: 18 not_applicable: 12 verdict_caching: none input_claim_caching: "registry/flex-auth/production_registry_snapshot.json, rebuilt by scripts/build_flex_auth_registry.py" # §6.4 obligation 4 — reconstructability, bounded by §9.6. ops-warden's audit # emission on this lane is deliberately non-atomic and therefore ATTRIBUTIVE, not # load-bearing: no control branches on the presence of a signing record # (`warden activity` displays it; nothing gates on it). Registered in §13. reconstructability: bound: "§9.6 attributive — completeness is not claimed" declared_at: wiki/AuditTrail.md # §9.7.2 — the certificate-verification PEP has no active revocation channel. # A previously allowed certificate remains usable until its enforced TTL expires, # so the visibility deadline is exactly the maximum issued lifetime per actor type. revocation_visibility: boundary: "SSH certificate verification at the target host" mechanism: ttl_expiry revocation_channel: none deadline_hours: adm: 48 agt: 24 atm: 8 note: >- No CRL or KRL distribution exists. Host-side authorization belongs to railiance-infra; shortening or actively recalling this window is a joint design question, not an implied capability of ops-warden. # §9.6 — signing evidence is attributive, not load-bearing. Measurement as of # 2026-09-04 found three signature records across 79 calendar days, concentrated # on only two active days (1 event on 2026-06-17; 2 within 40 minutes on # 2026-08-22). That bursty operator-driven sample cannot support a useful rate # threshold, so cadence is explicitly deferred instead of fabricated. emission_cadence: classification: attributive status: deferred measured_as_of: "2026-09-04" observed_window: first: "2026-06-17T23:18:33Z" last: "2026-09-04T21:21:30Z" signature_records: 3 active_signature_days: 2 daily_counts: "2026-06-17": 1 "2026-08-22": 2 reason: "operator-driven issuance is too sparse and bursty for a meaningful rate threshold"