Require declared human control in factory credential delivery
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-10 20:16:55 +02:00
parent d1c13b5dd6
commit 2b0d04e8e1
11 changed files with 451 additions and 27 deletions

View file

@ -86,9 +86,50 @@ authority is approval-engine (checked as `issuer`); the decision's is flex-auth.
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.
Dry-run and `plan` do not consume. For undeclared lanes, build/test and the
three-factor unsafe-demo exception retain their existing behavior. An explicitly
declared human control requires observation, PDP ALLOW and CAS consumption at
every stage; no demo or lane-review fallback discharges it.
## Declared human-control workflow
The factory lane explicitly declares `approval.human_control: true`. This
implements its existing human action-review requirement and GH-DEC-2026-016;
it does not infer human control from a CCR model, stage, actor, or approver entry,
and does not make a local authorization decision. Other catalog entries default
to undeclared. The catalog value must be a boolean, and `bootstrap-only` cannot
be combined with a declared human control.
The generated CheckRequest includes `context.human_control: true`. This changes
its evaluator-bound identity. The separate request-creation caller must issue an
unapproved Approval Engine object with **top-level `human_control: true`** and
`pdp_path: true`, using the actual evaluator-origin digest of that exact claim-free
request. A human subsequently supplies `/entries` through the admitted approver
surface. Do not copy an old request digest or retrofit an existing approval.
Approval Engine retains its unchanged five-field native act digest; the consumer
joins through the distinct evaluator-origin PDP digest as before.
At observation, this engine requires **`claim.binding.human_control is true`**
in addition to current validity, freshness and the PDP path. Missing, false,
string or numeric declarations refuse before the PDP call. The declaration is
checked again after PDP validation and carried in the internal consume binding
and non-secret `approval_human_control` evidence. A declared lane cannot skip
consumption through a build/test or unsafe-demo fallback. The consumer does not
reconstruct approver identities or counts: Approval Engine owns that evidence.
The repeatable `tools/exercise_approval_identity.py --exec-owner --human-control`
exercise creates a declared request through the actual engine API, proves a real
KeyCape service JWT cannot bind it, proves an undeclared claim cannot reach the
PDP/consume/backend path, and proves the real evaluator preserves the requirement.
The positive human entry is **seeded in the disposable store**, while requester,
claim and consume use real local service authentication. The backend and child
payload are synthetic; this is not human JWT/PKCE or live custody evidence.
See [the component receipt](evidence/2026-09-10-human-control-consumer-exercise.json).
Native narrow requester identity, browser human approval, admitted custody and
current deployed services remain APPROVAL-WP-0002-T01/T03/T05,
INFD-WP-0001-T07/T08 and SECRETS-WP-0009-T03. The factory catalog's exec owner
remains pending; adding this requirement grants no runtime or credential access.
## Fail closed
@ -110,8 +151,9 @@ digest, idempotence, and consumed-at only. No token, secret, or accessor.
## Required configuration
The join is absent by default, so an unconfigured engine behaves exactly as it
did before. Production additionally needs:
The join is absent by default. Undeclared lanes retain their existing behavior;
a lane declaring `approval.human_control: true` refuses an absent join.
Production and declared human-control paths need:
| Variable | Meaning |
| --- | --- |