informed-decision/pep-stance.yaml

111 lines
5.1 KiB
YAML
Raw Normal View History

Declare the layer per GH-DEC-2026-012; close T02 Gate House ruled all three questions within a day, attributing the speed to the request being filed before the architecture with candidate answers and their costs. R1 PEP-shaped, confirmed as proposed. The ruling settles the shape; the layer stays ours to declare, so layer.yaml is written in this repository's voice rather than transcribed from the reply. R2 yes to a presentation claim, no second catalog row, under three limits now declared in layer.yaml and tested. Limit 2 — the claim must never be an input to the decision it presents for — is load-bearing: our self-dealing argument was accepted because it holds, not despite it. Limit 3 drives architecture, since here the actor being audited and the evidence source are the same component. R3 (b) with the authority rule: binding digest authoritative for what the request is, view_hash only for what was shown, neither substitutable, and a disagreement between them is a finding against the presenting surface rather than a fact about the request. Linkage is co-reference; nesting was refused because it reproduces the GH-DEC-2026-008 hash cycle. Built to v0.8 obligation 3 rather than migrating later: axis enumerated, unknown resolves to fail_closed, absent distinguishable from unknown in the record, and published-equals-shipped asserted by test rather than claimed. Every stance is fail_closed, which is a conclusion not a shortcut — ops-warden can justify fail_open on a continuity argument that does not exist here. GH-DEC-2026-010 inherited as a declared gap in four documents: a decision cannot today be proven to have come from access-engine. The decision path must not be described as validated while FLEX-WP-0024 is open. 46 tests pass. T05 and T07 unblocked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR Assistant: claude-code Assistant-Model: opus Assistant-Process: 1565372@bnt-lap001 Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
2026-09-09 22:25:35 +02:00
# informed-decision — PEP unreachable-engine stance map
#
# Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md §6.4, §9.3, §9.7
# Built to: v0.8 obligation 3 (GH-DEC-2026-011), not v0.7 — per GH-DEC-2026-012,
# so this is built to rather than migrated to.
# Ruling: GH-DEC-2026-012
# Validate: pytest tests/test_layer_conformance.py
#
# §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. A map that lives only in a module
# default is not published — it is merely written down.
#
# The property that makes this worth reading: it is asserted equal to the shipped
# map in informed_decision/stance.py 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.7"
built_to_obligation_3_of: "0.8"
repository: informed-decision
pep_shape: true
declared_by: layer.yaml
ruling: GH-DEC-2026-012
protected_action: "Approver entry recorded against an approval object"
decision_engine: access-engine
# v0.8 obligation 3: the map MUST enumerate its axis rather than lean on a
# catch-all. The axis here is the memo's binding_level — this repository's own
# graded property, and the one that determines how costly a wrong bind is.
axis: binding_level
axis_source: decision-memo.schema.json#/properties/binding_level
# Total by enumeration, not by catch-all. Every value of the axis appears
# explicitly, plus the two non-value outcomes required to be distinguishable.
#
# Every stance is fail_closed, and that is a conclusion rather than a shortcut.
# ops-warden can justify fail_open on some zones because refusing removes
# production host access to close a documentation gap — a continuity argument.
# No such argument exists here. Refusing to render or to bind delays a decision;
# it does not remove a capability anyone depends on to keep a system running.
# Binding a human's identity to an act without an authorization decision is the
# precise failure this repository exists to prevent, so there is no level at
# which proceeding-without-a-decision is the safer error.
stance:
acknowledgment: fail_closed
organizational: fail_closed
aes: fail_closed
qes: fail_closed
unknown: fail_closed # v0.8 obligation 3: unknown MUST resolve to fail_closed
absent: fail_closed # distinct from unknown in the record — see below
# v0.8 obligation 3 requires an absent scope to be DISTINGUISHABLE in the record
# from an unknown one. They resolve to the same stance here but must never be
# recorded as the same fact:
# absent — the memo carried no binding_level at all (a defect in the memo)
# unknown — a binding_level was present but is not a value this map enumerates
# (a version skew between memo and this map)
# Collapsing them would hide a schema-drift incident inside a malformed-input
# statistic.
scope_absence:
distinguishable: true
recorded_as:
absent: "binding_level.absent"
unknown: "binding_level.unknown"
# §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 this surface
# records the APPLICATION OF THE STANCE instead.
on_apply:
recorded_fields:
- memo_id
- memo_version
- binding_level
- binding_level_state # present | absent | unknown
- stance_applied
- decision_id # only where a decision was actually rendered
- decision_attributable # see inherited gap below
- presentation_id
user_visible: >-
The approver is told the act could not be authorized and that nothing was
bound. The surface never presents a fail_closed outcome as a decline by the
approver: no disposition is recorded, because the human did not make one.
# GH-DEC-2026-010, inherited. Obligation 1 requires a decision be ATTRIBUTABLE to
# access-engine, and no consumer can satisfy that today — flex-auth's envelope is
# unsigned (declared §13 gap, FLEX-WP-0024). `decision_attributable` is therefore
# recorded as false and MUST NOT be reported as satisfied while that is open.
inherited_gap:
id: GH-DEC-2026-010-attributability
decision_attributable_today: false
tracked_by: FLEX-WP-0024
# §13.1 / GH-DEC-2026-011 — a dated classification-coverage figure beside the
# stance. Honest figure for a repository at spec stage: the axis is fully
# enumerated against the schema, and no protected action has shipped yet.
classification_coverage:
as_of: "2026-09-09"
axis_values_enumerated: 4
axis_values_in_schema: 4
coverage: "4/4 (100%) of binding_level values enumerated"
protected_actions_shipped: 0
note: >-
Coverage is complete against the schema, not against production behaviour:
nothing is deployed. Re-date this figure when the walking skeleton
(INFD-WP-0001-T08) ships, and treat a coverage figure that predates a schema
change as stale.