All three v0.4 findings were acted on — §9.1 split into pending/declared-gap and §5's scope rule adopted as recommended and credited, and §9.6 ruled via the load-bearing/attributive distinction with ops-warden's `# audit must not block signing` named as the estate's live example. Checked the favourable ruling rather than accepting it. §9.6's test is "no control branches on its presence": the only consumer of audit.jsonl is `warden activity`, which displays. Nothing gates on a signing record, so the lane is genuinely attributive. AuditTrail.md now records the ruling instead of the open question, and states that the trade must be revisited if a control ever gates on the trail. CONFORMANCE ACTION. §6.4 obligation 3 requires a stance map "published rather than held in code", and requires every PEP-shaped consumer to publish one so the maps can be inventoried — naming ADR-0009 as the reference shape. ops-warden was not doing it: the map lived in PolicyConfig.failure_modes, a dataclass default. Not a code comment, but not published either. pep-stance.yaml publishes it, and the test asserts the published map EQUALS the shipped default. A published map that may drift from the code is worse than no map, because it invites reliance it cannot support. Two findings sent to gate-house, in history/2026-08-29-layer-model-v06-review.md: §6.4 obligation 1 (no side effect without a decision record) contradicts obligation 3 and §9.3, with ops-warden's blessed fail-open stance as the instance; and §6.4 mandates a stance-map inventory in §13 that §13 does not implement — where ops-warden is currently the only PEP to have published one. 402 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c
69 lines
3.2 KiB
YAML
69 lines
3.2 KiB
YAML
# ops-warden — PEP unreachable-engine stance map
|
|
#
|
|
# Framework: net-kingdom/canon/standards/security-layer-model_v0.6.md §6.4, §9.3
|
|
# 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
|
|
standard_version: "0.6"
|
|
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
|
|
unknown: fail_open # versioned build profile (ADR-0009); explicit, never inferred
|
|
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.
|
|
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
|