feat: implement the PIP claim + validate authorization join
resolve_consume_binding was a `return None` stub, so protocol step 1 of
docs/approval-consumption.md (GET /v1/approvals/{id}/claim) and the
validation join never existed. validate_action_authorization had no caller
in src/ at all - it was reachable only from tests. Production fail-closed
was correct, but for an undocumented second reason, and WP-0007-T04's
"what remains is not local engine work" was wrong.
The join now reproduces the exact CheckRequest via build_action_request,
fetches the durable ActionAuthorization, and validates request binding,
digest, validity, authority, policy pin, and distinct-approver threshold
before offering a consume binding. _require_lane_approval threads the exact
field set for provision/rotate/verify/exec so the digest covers the real
proposed action.
Deliberate choices:
- The approval-engine object id is never inferred from a State Hub decision
UUID; flex-auth stated GET /decisions/{uuid} is not the durable object.
- No default policy pin. flex-auth stated secrets-engine.lifecycle/v1 is
example vocabulary, not a published package.
- A half-configured join raises rather than returning None, so a partial
deployment cannot be mistaken for an unconfigured one.
Behavior is unchanged today: every new input is absent by default, so
production still fails closed and plan/--dry-run still work. 234 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M65ovP3eiiPHubibvWs9mD
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 393550@bnt-lap001
Assistant-Session: 4bb359f9-1f12-4410-9e76-079cf23c82e4
This commit is contained in:
parent
ebcc36ecab
commit
627810b478
10 changed files with 456 additions and 25 deletions
|
|
@ -8,7 +8,7 @@ status: active
|
|||
owner: codex
|
||||
topic_slug: custodian
|
||||
created: "2026-08-23"
|
||||
updated: "2026-09-02"
|
||||
updated: "2026-09-06"
|
||||
state_hub_workstream_id: "68a39be1-bd9c-5133-ad64-e7bca892aaf3"
|
||||
---
|
||||
|
||||
|
|
@ -243,6 +243,36 @@ exception. Live destroy remains disabled independently. State Hub endpoint and
|
|||
authenticated approval storage are still outstanding. flex-auth corrected its
|
||||
example digest and added a complete binding regression assertion in `d402408`.
|
||||
|
||||
Correction 2026-09-06. The 2026-08-29 note above ("What remains is not local
|
||||
engine work") was wrong. `resolve_consume_binding` was a `return None` stub, so
|
||||
protocol step 1 (PIP `GET /v1/approvals/{id}/claim`) and the validation join
|
||||
were never implemented, and `validate_action_authorization` — the validator this
|
||||
plan called "shipped" — had no caller in `src/` at all. Only step 3 (CAS
|
||||
consume) and the OpenBao gate were real. Production fail-closed was therefore
|
||||
correct but for a second, undocumented reason.
|
||||
|
||||
The join is now implemented. `resolve_consume_binding` reproduces the exact
|
||||
CheckRequest via `build_action_request`, fetches the durable
|
||||
ActionAuthorization, and validates request binding, digest, validity, authority,
|
||||
policy pin, and distinct-approver threshold before returning a binding.
|
||||
`_require_lane_approval` threads the exact field set for provision, rotate,
|
||||
verify, and exec so the digest covers the real proposed action. Eight tests in
|
||||
`tests/test_consume_binding_join.py` cover unconfigured, half-configured, digest
|
||||
mismatch, action mismatch, unreachable, and superseded paths.
|
||||
|
||||
Two deliberate choices, both recorded in `docs/approval-consumption.md`:
|
||||
the approval-engine object id is never inferred from a State Hub decision UUID
|
||||
(flex-auth: `GET /decisions/{uuid}` is not the durable object); and there is no
|
||||
default policy pin, because flex-auth stated `secrets-engine.lifecycle`/`v1` is
|
||||
example vocabulary rather than a published package.
|
||||
|
||||
Behavior today is bit-for-bit unchanged: every new input is absent by default,
|
||||
so an unconfigured engine still fails production closed, and `plan`/`--dry-run`
|
||||
still work. This task stays `wait`, but the remaining constraint is now purely
|
||||
deployment: approval-engine must serve the claim endpoint and access-engine must
|
||||
serve Check. Probed 2026-09-06 — neither is reachable, and State Hub exposes
|
||||
only `/decisions/`.
|
||||
|
||||
Define and enforce the decision contract needed by production commands. A
|
||||
resolved approval must bind at least:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ status: active
|
|||
owner: grok
|
||||
topic_slug: custodian
|
||||
created: "2026-08-29"
|
||||
updated: "2026-09-02"
|
||||
updated: "2026-09-06"
|
||||
state_hub_workstream_id: "9c9e5164-b2f5-5ea2-a557-5368d65e9fe0"
|
||||
---
|
||||
|
||||
|
|
@ -103,6 +103,14 @@ binding fail closed with no OpenBao call. Production still also fail-closes
|
|||
on the unpublished durable ActionAuthorization / consume-binding serving
|
||||
path, so this task remains `wait`.
|
||||
|
||||
Correction 2026-09-06. See `SECRETS-WP-0007-T04` for the full note. Summary: the
|
||||
consume-before-OpenBao gate was real, but the PIP claim + validate join was a
|
||||
`return None` stub and `validate_action_authorization` had no production caller,
|
||||
so this task's "blocked on the durable serving path" framing hid an unimplemented
|
||||
local seam. The join is now implemented and tested; the remaining blocker is
|
||||
genuinely external (approval-engine claim endpoint and access-engine Check, both
|
||||
unreachable as of 2026-09-06).
|
||||
|
||||
Blocked on the durable ActionAuthorization serving path owned with
|
||||
`SECRETS-WP-0007-T04` / State Hub / `access-engine`.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue