approval-engine/docs/pep-integration.md
tegwick 2370f69927 Harden the PEP harness and KeyCape registration request
Close remaining in-repo APPROVAL-WP-0002 gaps: drive GH-DEC-2026-003 against
the real HTTP surface, fail closed on JWT/human-consume/static-token paths,
treat audit 200 duplicates as drained, and ask KeyCape for the production
audience and client grants.

Assistant: grok
Assistant-Session: 01a06253-e557-7971-93d9-4f4c2cfbf455
2026-09-02 15:46:06 +02:00

1.5 KiB

PEP integration sequence

approval_engine.pep implements the fail-closed ordering from GH-DEC-2026-003 without becoming a PDP:

  1. fetch a fresh approval claim;
  2. pass that claim to the consumer's authorization decision function;
  3. require ALLOW, decision id, and the exact canonical request digest;
  4. CAS-consume the approval;
  5. only after confirmed consumption invoke the protected callback.

Claim or consume unavailability, invalid/consumed claims, DENY, digest mismatch, and consume conflicts all prevent the callback. A same-digest retry receives the engine's idempotent success. If the callback fails after consume, the approval stays spent; there is no unconsume.

The module rereads the mounted bearer-token file on each HTTP request. Conflict, unavailability, unauthorized, missing, DENY, and digest-mismatch paths all prevent the callback. Same-digest consume retries are idempotent; a later full sequence against a spent approval fails at the claim. The consume response is rejected if it carries decision-shaped keys (effect / allow / deny).

The live HTTP harness in tests/test_pep.py drives this sequence against the real WSGI surface without performing a protected action. secrets-engine owns the production OpenBao PEP (src/secrets_engine/approval_consume.py); that handler is implemented and proven in-repo for 409 / unreachable / missing binding. Live closure still needs this service deployed and a durable consume binding served (SECRETS-WP-0007-T04 / SECRETS-WP-0008-T02).