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

@ -2,8 +2,10 @@
**Workplan task:** `INFD-WP-0001-T07`
**For:** `key-cape` (`KEY-WP-0013-T02`, `KEY-WP-0013-T05`)
**Status:** **draft — not yet submitted.** One input outstanding: the deployed
origin (§2). Everything else is fixed and stable.
**Status:** **submitted 2026-09-10** (`INFD-WP-0001-T07` done). The
origin is live. Registration rollout and a native human token accepted by
Approval Engine remain T08; the browser login implementation is described in
[browser-authentication.md](browser-authentication.md).
**Rulings:** `GH-DEC-2026-012`, `GH-DEC-2026-013`
**Contracts cited:** `key-cape/docs/approval-engine-auth-contract.md`,
`key-cape/docs/tenant-claim-contract.md`,
@ -47,11 +49,10 @@ than reconciled afterwards.
`hub.coulomb.social`, `kc.coulomb.social`), Traefik `ingressClassName`, TLS
secret per host.
- **DNS resolves** to the cluster address as of 2026-09-10.
- **Still requires, in `railiance-apps` rather than here:** an Ingress manifest
and an issued certificate. Manifest written 2026-09-10
(`manifests/informed-decision-ingress.yaml`); not yet applied.
- **Delivered by `railiance-apps`:** Ingress and issued certificate, applied
2026-09-10 (`manifests/informed-decision-ingress.yaml`).
**The host answers. This document is ready to submit.** 2026-09-10 14:32 UTC:
**The host answers. This document has been submitted.** 2026-09-10 14:32 UTC:
`railiance-apps` applied the Ingress and cert-manager issued a Let's Encrypt
certificate for `decisions.coulomb.social`;
`GET https://decisions.coulomb.social/auth/callback` returns `200` over a
@ -146,11 +147,12 @@ Consequences accepted here:
1. **This is transitional.** When the directory carries tenants, the same
`key-cape` code stops supplying and starts enforcing agreement, with no second
migration. This registration is expected to survive that unchanged.
2. **The claim is stored with its provenance.** `key-cape` emits `tenant` as a
bare string, so a consumer cannot distinguish a directory-asserted tenant from
a registration-supplied one. Until the claim carries its own provenance
(`GH-DEC-2026-013` §5, second field deliberately undesigned), this surface
records which route the value arrived by. See `PR-09`.
2. **The claim is stored with its provenance.** Current `key-cape` emits
`tenant_source`: `directory`, `registration`, or `default`. The browser
adapter preserves the first two as distinct routes and refuses missing,
unknown or default provenance for this platform approver flow. It does not
relabel registration-supplied tenancy as a fact asserted by the directory.
See `PR-09` and `key-cape/src/internal/server/oidc/token.go`.
3. **The tenant claim is never used as the act-scope.** `binding.target` is the
act-scope and is committed inside `view_hash`. Two different facts — which
scope this act enters, and which tenant this person belongs to — must not
@ -180,5 +182,17 @@ while it stands.
| # | Item | Owner |
| --- | --- | --- |
| 1 | ~~DNS A record + Ingress + TLS for `decisions.coulomb.social`~~**done 2026-09-10**, cert issued, host answers 200 | `railiance-apps` / deployment |
| 2 | Submit this document to `key-cape`, closing `KEY-WP-0013-T02` | this repo, once 1 lands |
| 3 | Prove a token issued against the registration is accepted by `approval-engine` | `T08` |
| 2 | ~~Submit the client contract to `key-cape`~~**done**, source T07 return | this repo |
| 3 | Deploy/admit the registration and prove a native human token is accepted by `approval-engine` | `T08`, `KEY-WP-0013-T05`, `APPROVAL-WP-0002-T01` |
## 8. Humanity provenance correction — 2026-09-10
The earlier assertion that `principal_type: human` came from registration was
incorrect for the current KeyCape implementation (`f9812ab`). Its code exchange
consumes a user-authenticated PKCE session, looks up that user and emits the
literal `human`; its client-credentials handler emits `service`.
`oidc.py` verifies the fixed issuer, signature, audiences, nonce, paired subject,
exact scopes, tenant provenance and MFA facts before assigning the
`authentication-derived` route. The generic provenance guard continues refusing
registration-only assertions. This is a checked source contract, not a claim
that the current deployed issuer or a native human login has been verified here.