key-cape/docs
tegwick 329e48f64a
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 46s
Let a human token carry the zone it is issued into, without relabelling anyone
KEY-WP-0013-T05's tenant blocker did not need the decision it was waiting on. The
two proposed resolutions differ in where a human's tenant comes from -- the
directory record, or the client registration -- and an implementation exists that
is correct under either, so the choice can be made later without another
migration.

A client registration may now declare a tenant. humanTenant() resolves it by four
rules: no declaration keeps the directory answer unchanged; a declared zone
applies where the directory has placed the user nowhere; agreement passes; and a
declared zone conflicting with a directory assignment refuses issuance rather
than relabelling the user.

The refusal is the design, not an edge case. A registration can bind a zone for
unplaced users and can never move a placed one, so this gets the approval chain
its tenant:platform without writing a general cross-tenant override into the
issuer. It fails closed rather than picking a winner, because either answer would
be a silent cross-tenant assertion, and it reports 403 with
error_type: tenant_binding so an operator can tell a misconfigured registration
from a rejected login. If the owners later populate directory tenants, the same
code stops supplying the zone and starts enforcing agreement with it.

Safe only because client registrations are static and deployment-owned. The
tenant contract records that this rule must be revisited if dynamic client
registration is ever admitted.

Tests cover all four rules; neutering the conflict check fails the relabel test
rather than passing silently.

T05 now waits on one thing only: the client_id and callback URI from
informed-decision once it has a deployed origin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uV8zoCKpA1WRAxsKRYbdH

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1182213@bnt-lap001
Assistant-Session: 966597b9-ae61-46a4-8b9e-1594ab3ec4ad
2026-09-09 14:40:36 +02:00
..
adr feat: implement T01-T04 — Go module, canonical model, LDAP validator, error taxonomy 2026-03-13 01:27:54 +01:00
evidence docs: close live approval service registration gate 2026-09-09 02:18:12 +02:00
approval-clients-deployment.patch.yaml docs(keycape): prepare pinned approval-client rollout and recovery 2026-09-08 17:03:59 +02:00
approval-clients-rollout.md docs: close live approval service registration gate 2026-09-09 02:18:12 +02:00
approval-engine-auth-contract.md Let a human token carry the zone it is issued into, without relabelling anyone 2026-09-09 14:40:36 +02:00
approval-engine-provisioning-request.yaml Let a human token carry the zone it is issued into, without relabelling anyone 2026-09-09 14:40:36 +02:00
authorization-code-bindings.md Document the authorization-code bindings for relying parties 2026-09-07 00:17:56 +02:00
native-authentication.md Ship the live-registration check both blocked tasks depend on 2026-09-08 14:30:43 +02:00
openbao-service-auth-contract.md Implement KeyCape provider and service identity contracts 2026-08-23 13:10:13 +02:00
operations.md Establish the live state and find a rollout precondition for G10 2026-09-08 11:41:42 +02:00
qonto-runtime-identity-contract.md Define Qonto runtime identity contract 2026-07-26 13:34:56 +02:00
tenant-claim-contract.md Let a human token carry the zone it is issued into, without relabelling anyone 2026-09-09 14:40:36 +02:00
upstream-issuer-proof.md docs(identity): record verified live upstream issuer and completed cleanup 2026-09-08 23:50:54 +02:00