Add verified browser login and human approval HTTP client

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-10 22:05:17 +02:00
parent 4e103f62a0
commit 0e48355b9f
16 changed files with 1365 additions and 39 deletions

View file

@ -436,7 +436,7 @@ state_hub_task_id: "b5c1d329-9580-5672-9640-2930cbbb729a"
```
Prove the specs against reality with the thinnest possible L3 path: sign in via
`key-cape`, list approvals awaiting this principal from `approval-engine`,
`key-cape`, retrieve one named approval by id from `approval-engine`,
render one as a Decision Memo with brief, packet and highlights, acknowledge the
required highlights, and submit an approval entry with a stored presentation
record carrying `view_hash`.
@ -492,6 +492,40 @@ requires the evidence copy to reach `audit-core` independently of this
component, and the payload question is open. Design and decision request in
`docs/evidence-path-design.md`. This task must not ship before it is answered.
2026-09-10 — **browser authentication and real HTTP adapter implemented.**
`oidc.py` verifies KeyCape authorization-code/S256 PKCE, browser-bound single-use
state, ID-token nonce and client audience, access-token resource audience,
paired subject/tenant/provenance, exact scopes and MFA facts. Tokens stay in
bounded ephemeral server sessions. `web.py` supplies the sign-in shell with
secure cookies, CSRF sign-out, no token output and no memo/entry route.
`approval_http.py` reads by id and submits human entries, requires the declared
control and native digest format, and recovers duplicate correlation from the
actual stored entry. No consume API, validity cache or automatic POST retry.
206 tests pass, including three checks against Approval Engine's actual JWT
verifier/API and 100 existing domain/contract tests. Six installed-entrypoint
HTTP smoke checks pass. These use signed synthetic identity fixtures: **no
native human login, audit admission or factory execution is claimed.**
The component test caught an unprefixed-digest assumption; the adapter now
carries the native `sha256:<64 hex>` value unchanged. The package's dev extras
now include PyYAML so layer conformance cannot silently disappear in a clean
installation. Evidence: `docs/evidence/2026-09-10-browser-authentication.json`.
The earlier principal-type provenance assumption is corrected against KeyCape
`f9812ab`: its user-authenticated code flow emits `human`, while client credentials
emit `service`; `tenant_source` distinguishes directory and registration.
Unknown tenant provenance fails closed. This adopts the current issuer contract
without assuming that it has been proven on the deployed login path.
**Next within this task:** durable presentations/dispositions plus transactional
outbox; entitlement before render; connect one named memo with required
acknowledgments, accept/return/discuss and correct actor/presentation binding;
independent audit delivery; then native registered login and deployed-engine
proof. Ambiguous engine POSTs must reconcile against stored entry correlation
before a UI retry. `/readyz` deliberately remains 503 and browser entry routes
are absent until this protected path is wired. The task remains `progress`.
See `docs/browser-authentication.md`.
## Known risks
- **T02 is a hard gate.** Writing the blueprint before the layer ruling risks