Compare commits

...

3 commits

Author SHA1 Message Date
1a920a5490 Confirm the approval-claim as the step-1 PEP artifact
approval-engine raised APPROVAL-IN-0002: secrets-engine's PEP validator
expects a flex-auth ActionAuthorization but fetches the approval-claim
endpoint that GH-DEC-2026-003 names as step 1. Two objects on one path.

GH-IN-0002 records the intake; GH-DEC-2026-005 resolves it. The claim is
the step-1 artifact and always was — ActionAuthorization is unratified,
has no valid_now field, and cannot be served from a step-1 call. The
addition beyond confirmation is doctrine: a PEP validates each artifact
against the layer that owns its data, and no PIP republishes the PDP's
decision. The provenance.authority == "state-hub" requirement is struck;
State Hub is a read model and holds no runtime approval authority.

docs/contracts/approval-consumption.md carries the amendment at the
sequence itself so implementers find it there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WtJBr77gMFLrN93iEevqQJ

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 425128@bnt-lap001
Assistant-Session: f5944d8b-dac4-4e1a-87eb-8b3d8f314a63
2026-09-06 01:29:28 +02:00
repo-manager
60e2e7de65 repo.work.create_decision GH-DEC-2026-005
correlation_id: a62fcaea-d7f9-4b8a-9d68-d3e0e9a2fe14
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 425128@bnt-lap001
Assistant-Session: f5944d8b-dac4-4e1a-87eb-8b3d8f314a63
2026-09-06 01:28:23 +02:00
repo-manager
be18542cc6 repo.work.create_intake GH-IN-0002
correlation_id: d2369d5a-ffae-4dc5-9f6a-ee4011d50b4c
reason: rmgr CLI
source: repo-manager

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 425128@bnt-lap001
Assistant-Session: f5944d8b-dac4-4e1a-87eb-8b3d8f314a63
2026-09-06 01:28:12 +02:00
3 changed files with 187 additions and 2 deletions

View file

@ -453,3 +453,120 @@ 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.

View file

@ -3,8 +3,9 @@
**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`
**Date:** 2026-08-29
**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
**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`
@ -30,6 +31,35 @@ 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

View file

@ -124,3 +124,41 @@ 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'
```