diff --git a/decisions/decisions.md b/decisions/decisions.md index 799f9c0..aa2f9c0 100644 --- a/decisions/decisions.md +++ b/decisions/decisions.md @@ -453,120 +453,3 @@ NetKingdom security profile, or if Info Tech Canon cannot provide a stable cross-domain contract boundary. Reversal must still name one owner for every artifact; returning to undifferentiated "Taxonomy ownership" is not an acceptable outcome. - -## GH-DEC-2026-005 — The approval-claim is the step-1 artifact on the PEP consumption path - -```yaml -id: GH-DEC-2026-005 -kind: decision -title: The approval-claim is the step-1 artifact on the PEP consumption path -status: resolved -owner: Bernd Worsch -repo: gate-house -standard: net-kingdom/canon/standards/security-layer-model_v0.7.md -source_note: docs/contracts/approval-consumption.md -origin: GH-IN-0002 -requested_dispositions: -- approved -- revised -- rejected -affects: -- gate-house -- approval-engine -- flex-auth -- secrets-engine -- ops-warden -rationale: 'Confirmed, with one addition. GH-DEC-2026-003 already named step 1 by - endpoint and by field; the approval-claim is what that endpoint serves and valid_now - is its field. ActionAuthorization is a proposed, unratified shape carrying no doctrine - standing here. The addition is that the split validation is stated as doctrine rather - than left implicit: each artifact is checked by the consumer against the layer that - owns its data, and no PIP republishes a PDP decision. The state-hub authority requirement - in the secrets-engine validator is struck because State Hub is a read model and - holds no runtime approval authority.' -decided_by: Bernd Worsch -created: '2026-09-05T23:28:23.931441Z' -updated: '2026-09-05T23:28:23.931441Z' -``` - -## Context - -`GH-DEC-2026-003` settled the consumption sequence and named step 1 by endpoint and -by field: `GET /v1/approvals/{id}/claim` → `valid_now` (a fact, not permission). -`approval-engine` serves the approval-claim at that endpoint -(`approval-engine/docs/approval-claim.md`). `secrets-engine`'s PEP validator -(`validate_action_authorization`, `src/secrets_engine/authorization.py`) calls the -same endpoint but expects a flex-auth `ActionAuthorization`. Two different objects -were being assumed on one path, and the divergence would have surfaced at first live -consume rather than at deployment. - -`ActionAuthorization` originates in `flex-auth/docs/action-bound-authorization-contract.md` -as a proposed shape for durable approval storage that the same document assigns to -`approval-engine`. It was never ratified, appears nowhere in this repository's -doctrine, and has no `valid_now` field. `GH-DEC-2026-003` was issued after it without -reference to it. There is therefore nothing to reconcile: the claim was the step-1 -artifact all along, and this record says so where implementers will find it. - -`approval-engine` raised the question rather than guessing, which is the behaviour -§12 asks for. The three substantive assertions in the request were checked here -independently before confirmation. - -## Decision - -**1. The approval-claim is the step-1 artifact on the `GH-DEC-2026-003` path.** -It carries the approval fact: binding digest, validity window, consumption state, -observation freshness, and issuer. Holding one with `valid_now: true` remains not -authority to act. - -**2. `ActionAuthorization` is not required on that path.** `approval-engine` is not -expected to serve it and MUST NOT serve it from the claim endpoint. A step-1 response -cannot contain a step-2 decision; any composed post-decision artifact would be a new -artifact at a new endpoint. The proposal is shelved on this path, not withdrawn. - -**3. A PEP validates across the two artifacts it already fetches.** The claim is -checked for the approval fact; the flex-auth `DecisionEnvelope` from step 2 is checked -for exact `CheckRequest` match and policy package/version pin. This is doctrine, not -merely an implementation convenience: **each artifact is validated against the layer -that owns its data.** A PIP republishing the PDP's decision would put a copy of the -authority decision in a repository that did not render it — the same shape of error -the re-cut removed from Gate House itself. No safety property is lost, because -`ActionAuthorization` is a bundle of exactly these two checks. - -**4. The `provenance.authority == "state-hub"` requirement is struck.** State Hub is -a read model. It is not the runtime approval authority and never was; flex-auth's own -contract says so. A validator that requires it would fail closed against every -correctly issued claim. `secrets-engine` removes the constant with the validator split. - -Consequent changes: `approval-engine` none — the claim schema stands as published; -`secrets-engine` splits its validator and drops the authority constant; `flex-auth` -records that the proposal is shelved on this path. Nothing here gates -`APPROVAL-WP-0002-T03` — `secrets-engine` is fail-closed until its own gates land, -and this record governs first live consume, not deployment. - -## Deferred - -A ratified post-decision `ActionAuthorization` — one composed, signed, forwardable -object — remains coherent and is recorded here so it is not rediscovered as new. It -is not adopted now because it has no named issuer or lifecycle owner and the sequence -is already settled without one. Revisit on any of: a third or fourth PEP-shaped -consumer; a requirement for a single signed forwardable artifact (offline -verification, or an audit that must replay one object rather than a join); resolution -of flex-auth's open G3 finding by composition rather than by adding a lifetime to the -envelope; or assent of the statute §17 Taxonomy request-claim schema -(`APPROVAL-IN-0001`) — in which case converge there and do **not** revive this -separately. - -Also rejected, so they are not re-proposed: serving `ActionAuthorization` at the claim -endpoint (structurally impossible for step 1, and it would assert an authority -`approval-engine` does not hold); and extending the claim with `approvals.required_count` -or `entries` (publishing approver identities is a deliberate least-disclosure non-goal, -and it would still not satisfy the validator). - -## Reversal - -Revert this record and the amendment to `docs/contracts/approval-consumption.md`. The -falsifier is a demonstrated check that two-artifact validation cannot perform and a -single composed artifact can — most plausibly offline or forwarded verification with -no access to the PDP. That is a trigger for the deferred option above, not for -returning `ActionAuthorization` to the claim endpoint, which stays forbidden on -structural grounds regardless. diff --git a/docs/contracts/approval-consumption.md b/docs/contracts/approval-consumption.md index 5837e4d..1860eb8 100644 --- a/docs/contracts/approval-consumption.md +++ b/docs/contracts/approval-consumption.md @@ -3,9 +3,8 @@ **Owner:** gate-house **PIP:** approval-engine **PDP:** access-engine (currently flex-auth) -**Status:** normative for GH-WP-0002-T06; recorded as `GH-DEC-2026-003`, -amended by `GH-DEC-2026-005` (step-1 artifact and split validation) -**Date:** 2026-09-06 +**Status:** normative for GH-WP-0002-T06; recorded as `GH-DEC-2026-003` +**Date:** 2026-08-29 **Statute:** `net-kingdom/canon/standards/security-layer-model_v0.7.md` §9.4, §9.7.3–4, §16 **Blocks:** `APPROVAL-WP-0001-T05`, `FLEX-WP-0017-T05` @@ -31,35 +30,6 @@ companion §5 already treats as PEP-shaped. Holding a claim with `valid_now: true`, or an ALLOW against that claim, is not authority to act. The consume is. -## What each step's artifact is - -Amended by `GH-DEC-2026-005`. - -**Step 1 serves the approval-claim** (`approval-engine/docs/approval-claim.md`). -That is the artifact `valid_now` belongs to, and it is the only object the claim -endpoint serves. flex-auth's proposed `ActionAuthorization` is **not** required -here, is not served here, and MUST NOT be served from this endpoint: a step-1 -response cannot contain a step-2 decision. - -**A PEP validates across both artifacts it already fetches**, and each against -the layer that owns its data: - -| Artifact | Source | What the PEP checks | -| --- | --- | --- | -| approval-claim | step 1, `approval-engine` (PIP) | binding digest, validity window, consumption state, observation freshness, issuer | -| `DecisionEnvelope` | step 2, `access-engine` (PDP) | exact `CheckRequest` match, policy package and version pin | - -A PIP MUST NOT republish the PDP's decision, and a PEP MUST NOT accept the -approval fact from the decision artifact or the decision from the approval -artifact. Composing the two into one served object is a separate, post-decision -artifact at a separate endpoint if it is ever ratified — not a change to the -claim. - -**Claim provenance is not State Hub.** A PEP MUST NOT require -`provenance.authority == "state-hub"` on the claim. State Hub is a read model and -holds no runtime approval authority; the issuer to check is the engine that -served the claim. - ## Why consume is before the side effect §9.7.3 says consumption MUST NOT be inferred from a decision record. That diff --git a/intakes/intakes.md b/intakes/intakes.md index 971fd14..591039d 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -124,41 +124,3 @@ closed_at: '2026-08-29T00:55:21.377495Z' outcome: promoted state_hub_intake_id: "01a04b04-dd82-73a4-a8bf-9aeba5ef575f" ``` - -## GH-IN-0002 — Claim envelope on the PEP consumption path — which artifact is step 1 of GH-DEC-2026-003 - -```yaml -id: GH-IN-0002 -kind: intake -title: Claim envelope on the PEP consumption path — which artifact is step 1 of GH-DEC-2026-003 -status: closed -origin: cross-repo -origin_ref: approval-engine APPROVAL-IN-0002 (decision request) -priority: high -owner: gate-house -requested_by: approval-engine -lane: red -description: 'approval-engine asks gate-house to confirm which artifact satisfies - step 1 of the GH-DEC-2026-003 consumption sequence. secrets-engine''s PEP validator - (validate_action_authorization) expects a flex-auth ActionAuthorization envelope - but fetches GET /v1/approvals/{id}/claim, which serves approval-engine''s approval-claim. - Two different objects on one path. - - - GH-DEC-2026-003 already names step 1 by endpoint and by field — ''GET /v1/approvals/{id}/claim - -> valid_now (a fact, not permission)''. valid_now is an approval-claim field; ActionAuthorization - has no such field and appears nowhere in gate-house doctrine. It originates in flex-auth - docs/action-bound-authorization-contract.md as a proposed shape for durable approval - storage that the same document assigns to approval-engine; it was never ratified. - - - Secondary finding: the secrets-engine validator hard-requires provenance.authority - == ''state-hub'' (AUTHORITY constant, src/secrets_engine/authorization.py), while - flex-auth''s own contract holds that State Hub decision records are not the runtime - approval authority. - - - Requested disposition is a confirmation, not a redesign. Resolved as GH-DEC-2026-005.' -created: '2026-09-05T23:28:11.977565Z' -updated: '2026-09-05T23:28:11.977565Z' -```