50 lines
1.9 KiB
Markdown
50 lines
1.9 KiB
Markdown
|
|
# Approval consumption (PEP)
|
||
|
|
|
||
|
|
Status: engine consumer implemented; live production remains fail-closed
|
||
|
|
until a durable consume binding is served.
|
||
|
|
|
||
|
|
Normative protocol: `gate-house/docs/contracts/approval-consumption.md`
|
||
|
|
(`GH-DEC-2026-003`). Implementation surface:
|
||
|
|
`approval-engine/docs/approval-consumption.md`. This document records how
|
||
|
|
secrets-engine, as the PEP for OpenBao writes, consumes that protocol. It
|
||
|
|
does not redefine it.
|
||
|
|
|
||
|
|
## Sequence
|
||
|
|
|
||
|
|
```text
|
||
|
|
1. PIP GET /v1/approvals/{id}/claim
|
||
|
|
2. PDP access-engine Check / decide → ALLOW
|
||
|
|
3. PEP POST /v1/approvals/{id}/consume → CAS
|
||
|
|
4. PEP OpenBao call → only after consume succeeds
|
||
|
|
```
|
||
|
|
|
||
|
|
Every live privileged production handler passes `_require_lane_approval`,
|
||
|
|
which calls `require_production_consume` before `OpenBaoClient.resolve`.
|
||
|
|
Dry-run and `plan` do not consume. Build/test remain fail-open relative to
|
||
|
|
approval-engine. The three-factor unsafe-demo exception is not a consume
|
||
|
|
path.
|
||
|
|
|
||
|
|
## Fail closed
|
||
|
|
|
||
|
|
| Condition | Result |
|
||
|
|
| --- | --- |
|
||
|
|
| No served consume binding | refuse; no OpenBao |
|
||
|
|
| Missing `SECRETS_ENGINE_APPROVAL_URL` or token file | refuse; no OpenBao |
|
||
|
|
| HTTP 409 / different digest | refuse; no OpenBao |
|
||
|
|
| Same digest after consume | idempotent success; OpenBao may proceed |
|
||
|
|
| 401/403/404/503/unreachable | refuse; no OpenBao |
|
||
|
|
| Side effect fails after consume | approval is spent; no unconsume |
|
||
|
|
|
||
|
|
The consume response is mutation evidence (`status=consumed` plus the
|
||
|
|
presented digest). It is not a permission. Evidence records approval id,
|
||
|
|
digest, idempotence, and consumed-at only. No token, secret, or accessor.
|
||
|
|
|
||
|
|
## What this does not do
|
||
|
|
|
||
|
|
- It does not enable live production. Unreachable-engine stance still
|
||
|
|
fail-closes production until an access-engine decision record is served
|
||
|
|
(`SECRETS-WP-0007-T04` / `SECRETS-WP-0008-T02`).
|
||
|
|
- It does not render or cache an authorization decision.
|
||
|
|
- It does not infer consumption from a decision record or from local
|
||
|
|
evidence.
|