Record the claim vs ActionAuthorization envelope divergence
secrets-engine reports its PIP join is implemented and blocked on
deployment rather than contract. Reviewing its
validate_action_authorization against what this engine actually serves
shows that is not the whole story: it expects a state-hub-authority
ActionAuthorization (id, status, superseded_by, request,
approvals.entries, policy pin) while GET /v1/approvals/{id}/claim serves
the governed approval-claim (approval_id, state/valid_now, binding,
freshness, reason_code, issuer approval-engine).
Both envelopes declare schema_version 0.1, so the version check passes
and the mismatch surfaces as a field or authority error that reads like
an approval-engine outage.
Document the field-by-field divergence and why the omissions are
deliberate: a claim is a fact about an approval object, not a decision,
so approver identities and policy pins are not republished. Reconciling
the envelopes is a GH-DEC-2026-003 cross-repo change, so the governed
claim schema is left unchanged here.
No code change; 84 tests still pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvyJPAaVCGsVheVhcCwNND
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 411227@bnt-lap001
Assistant-Session: d566f6d3-bcaf-43c3-bc5e-3ddd0f64b535
This commit is contained in:
parent
2370f69927
commit
115f309e0a
2 changed files with 46 additions and 1 deletions
|
|
@ -41,3 +41,36 @@ after consumption, the approval remains spent and a retry needs a new approval.
|
|||
|
||||
The response is mutation evidence, not a permission decision. It contains no
|
||||
`effect`, `allow`, `deny`, or decision result.
|
||||
|
||||
## The claim response is not an `ActionAuthorization`
|
||||
|
||||
`GET /v1/approvals/{id}/claim` serves the **approval-claim** envelope defined in
|
||||
[`approval-claim.md`](approval-claim.md). It is not the `ActionAuthorization`
|
||||
object that secrets-engine's `validate_action_authorization` currently expects,
|
||||
and a PEP that points that validator at this URL fails closed for the wrong
|
||||
reason.
|
||||
|
||||
Both envelopes carry `schema_version: "0.1"`, so the version check passes and
|
||||
the mismatch surfaces later as a missing-field or wrong-authority error. Do not
|
||||
read that failure as an approval-engine outage.
|
||||
|
||||
| Validator expectation | What the claim actually serves |
|
||||
| --- | --- |
|
||||
| `id` (canonical UUID) | `approval_id` — the object id, same value, different key |
|
||||
| `status == "approved"` | `state` (`approved`, `consumed`, `revoked`, `superseded`, `expired`, `requested`) plus the `valid_now` predicate |
|
||||
| `superseded_by` | absent; supersession appears as `state: "superseded"` |
|
||||
| `provenance.authority == "state-hub"` | `issuer: "approval-engine"` — this engine is the authority for the approval object; the State Hub is a read model and never issues one |
|
||||
| `request` (full CheckRequest) | `binding` (`action`, `actor`, `principal`, `purpose`, `target`) plus `binding.digest`, and `binding.pdp_digest` when recorded at issue |
|
||||
| `approvals.required_count` / `entries` | not exposed; the distinct-approver threshold is already folded into `valid_now`, with `reason_code: "insufficient_approvers"` when unmet |
|
||||
| policy package/version pin | not carried; the policy pin belongs to the access-engine decision, not to the approval fact |
|
||||
|
||||
The omissions are deliberate. A claim is a *fact about an approval object*, not
|
||||
a decision and not a permission; approver identities and policy pins are not
|
||||
republished to consumers. The consumer checks in
|
||||
[`approval-claim.md`](approval-claim.md) ("Required verification") are the
|
||||
supported validation path.
|
||||
|
||||
Reconciling the two envelopes is a cross-repo contract change under
|
||||
`GH-DEC-2026-003`, not a unilateral edit here. Until it is decided, this engine
|
||||
keeps serving the approval-claim shape and does not emit a `state-hub`
|
||||
authority it does not have.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ status: active
|
|||
owner: codex
|
||||
topic_slug: netkingdom
|
||||
created: "2026-09-01"
|
||||
updated: "2026-09-02"
|
||||
updated: "2026-09-06"
|
||||
reviewed_at: "2026-09-01"
|
||||
reviewed_against_commit: "ebce5abb276c01ab29ce2526f3b8abb332dc9e90"
|
||||
reviewed_note: >-
|
||||
|
|
@ -185,3 +185,15 @@ claim refusal, and unreachable-engine callback suppression. Waiting on live
|
|||
closure: this service deployed (T03) and a durable consume binding served
|
||||
(`SECRETS-WP-0007-T04` / `SECRETS-WP-0008-T02`). This repo does not claim the
|
||||
OpenBao side effect.
|
||||
|
||||
2026-09-06 follow-up: secrets-engine reports its PIP join is implemented and
|
||||
blocked on deployment, not contract (inbox `61ae1174`). Review of its
|
||||
`validate_action_authorization` shows a real envelope divergence: it expects a
|
||||
`state-hub`-authority `ActionAuthorization` (`id`, `status`, `superseded_by`,
|
||||
`request`, `approvals.entries`, policy pin) while this engine serves the
|
||||
governed approval-claim (`approval_id`, `state`/`valid_now`, `binding`,
|
||||
`freshness`, `reason_code`, `issuer: approval-engine`). Both declare
|
||||
`schema_version` `0.1`, so the mismatch surfaces as a field/authority error
|
||||
rather than a version error. Recorded in `docs/approval-consumption.md`;
|
||||
reconciling the envelopes is a `GH-DEC-2026-003` cross-repo change, not a
|
||||
unilateral edit here. T05 stays `wait`: still no deployed base URL (T03).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue