gate-house ruled the v0.8 assent round (GH-DEC-2026-011, net-kingdom@64394e9): ask 1 declined, ask 2 adopted. Ask 1's refusal is accepted without reservation and the reason is better than the ask -- a sanctioned transitional fail_open is indistinguishable at runtime from the stance the rule forbids, and would make the rule optional at the only moment it costs anything. Ask 2 gave §13.1 a Coverage column with this repo's figures as its first entries. Since we asked for the column, we owe it accuracy: scripts/report_coverage.py measures both populations from the artifacts the runtime uses (reusing the workload-join build rather than re-deriving it), and a test asserts pep-stance.yaml's published block equals what it measures. A hand-counted number in a register that explicitly does not recompute it decays silently, and a stale figure beside a marked cell is worse than the blank the other four rows carry. pep-stance.yaml marks the unknown cell inline as a declared gap -- assent, the measured reason for not flipping, the declined ask, WARDEN-WP-0040 as route -- and a second test keeps it marked while it is fail_open, failing when it is flipped. standard_version stays 0.7 because that is what binds; v0.8 is proposed, so it gains standard_version_reviewed rather than pre-adopting. Separately, gate-house corrected GH-DEC-2026-008: the claim/decision digest comparison it originally required is unimplementable and a fail-closed consumer obeying it would have denied permanently. We had never copied the wording, so nothing to unwind -- but everything they have sent about this lane was living in an inbox thread, a bad home for a correction that only matters when someone finally wires the consume. Now wiki/ApprovalConsumption.md, leading with "nothing is wired", carrying the corrected target and the attribution gap that digest matching does not discharge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013EPuTc18FjU5WFqoSEKH3C Assistant: claude-code Assistant-Model: opus Assistant-Process: 1276224@bnt-lap001 Assistant-Session: 426ec497-e1c4-4dd3-b417-dfce1ca1dbc3
77 lines
3.8 KiB
Markdown
77 lines
3.8 KiB
Markdown
# Approval consumption — notes for the signing lane's future consume
|
|
|
|
**Status:** notes only. **Nothing is wired.** ops-warden's pre-sign gate consults
|
|
flex-auth (`wiki/PolicyGatedSigning.md`); it does not yet consume an approval
|
|
artifact. This page exists so the corrections we have already been given survive
|
|
until it does, rather than sitting in an inbox thread.
|
|
|
|
Owner of the contract: `gate-house`, `docs/contracts/approval-consumption.md`.
|
|
ops-warden is one of two PEP-shaped consumers named there (the SSH signing lane).
|
|
|
|
## Validate across two artifacts, never one
|
|
|
|
`GH-DEC-2026-005` settles the step-1 artifact: `GET /v1/approvals/{id}/claim`
|
|
serves the **approval-claim**. flex-auth's proposed `ActionAuthorization` is not
|
|
required there and will not be served from that endpoint.
|
|
|
|
| Artifact | Carries |
|
|
| --- | --- |
|
|
| approval-claim (step 1) | the approval fact — binding digest, validity window, consumption state, freshness, issuer |
|
|
| `DecisionEnvelope` (step 2) | exact `CheckRequest` match, policy pin |
|
|
|
|
v0.8 §6.4 obligation 5 hardened this: each artifact **must** be validated against
|
|
the layer that owns its data, and a PIP **must not** republish the PDP's decision.
|
|
Neither artifact may be taken from the other.
|
|
|
|
## Three things that are easy to get wrong
|
|
|
|
**1. Do not require `provenance.authority == 'state-hub'`.**
|
|
|
|
State Hub is a read model with no runtime approval authority. This is easy to get
|
|
wrong precisely *because* the hub is where everything else about a workplan lives,
|
|
so a consumer reaches for it as the authority on approval too.
|
|
|
|
Worth holding as a shape rather than an instance: a PEP requiring the hub to have
|
|
asserted an approval is the same boundary violated from the **consuming** side
|
|
that "never register workplans or tasks by hand" forbids from the **writing**
|
|
side. Same rule, two directions.
|
|
|
|
**2. The digest comparison target was corrected. Use `binding.approval_binding_digest`.**
|
|
|
|
`GH-DEC-2026-008` as originally issued required the claim's `pdp_digest` to equal
|
|
the decision's `request_digest`. That is unimplementable — a claim travelling
|
|
inside a hashed request cannot name the digest of the request containing it — and
|
|
a fail-closed consumer obeying it would have denied permanently. Corrected by
|
|
`FLEX-DEC-2026-007` to the PDP's published **exclusion-scoped** digest,
|
|
`binding.approval_binding_digest`.
|
|
|
|
ops-warden never copied the superseded wording anywhere (checked 2026-09-09), so
|
|
there was nothing to unwind. Recorded here so it cannot be reintroduced from an
|
|
older reading of the contract.
|
|
|
|
**3. Digest comparison does not discharge attribution, and attribution is not
|
|
available today.**
|
|
|
|
`GH-DEC-2026-010` rules that a PEP must be able to **attribute** a decision to
|
|
access-engine, and that matching digests does not achieve that. flex-auth's
|
|
envelope is unsigned and its pins serve plain HTTP, so that half is a declared
|
|
§13 gap owned by access-engine until `FLEX-WP-0024` lands.
|
|
|
|
Nothing for ops-warden to build. But when this lane is wired, its validation is
|
|
**complete-minus-attribution** and must be described that way: fail-closed
|
|
protects against a decision point that is absent, not against one that lies.
|
|
|
|
## Open dependency
|
|
|
|
`WARDEN-WP-0039-T03` — whether an admitted flex-auth contract exists for a
|
|
delegated credential read where caller and resource owner differ. If the answer
|
|
changes the caller shape it may reach how this lane's consume is built, and
|
|
`gate-house` has asked to hear that before rather than after: a contract admitted
|
|
for that shape would reach §6.4 obligation 5, and whether such a delegation
|
|
attenuates or widens is doctrine they own.
|
|
|
|
## See also
|
|
|
|
- `wiki/PolicyGatedSigning.md` — the pre-sign gate as it actually is today
|
|
- `pep-stance.yaml` — unreachable-engine stance, and the marked `unknown` cell
|
|
- `history/2026-09-09-layer-model-v08-review.md` — the v0.8 assent round
|