From a4e2751ab5fa3de44b95f8389e8ecfdafbeec7d3 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 9 Sep 2026 23:23:41 +0200 Subject: [PATCH] Make the registration-bound tenant caveat a condition, not a paragraph informed-decision replied on KEY-WP-0013-T05 asking for one thing that is ours: the caveat under which a registration-bound human tenant is safe should be a condition of the capability, so a future change to registration policy has to confront it, rather than reasoning left in a message. They will hold the approver registration, so they are the party that inherits the risk. The contract now states it as a condition rather than a caveat, in a form that says removing the paragraph is not the decision, and points at the test that enforces it. I also wrote a guard test for this and then deleted it: tests/profile has asserted registration_endpoint's absence all along, and a peer session was concurrently writing a better guard that asserts both halves together -- the capability still issuing, and the endpoint still absent -- so whichever is removed first the failure points at the other. That connection is the whole value, and a third assertion of the same fact would have been the duplication this repository keeps correcting. The contract cites theirs. Co-Authored-By: Claude Opus 5 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 --- docs/tenant-claim-contract.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/docs/tenant-claim-contract.md b/docs/tenant-claim-contract.md index 27c9705..965952b 100644 --- a/docs/tenant-claim-contract.md +++ b/docs/tenant-claim-contract.md @@ -116,10 +116,32 @@ carries tenants, the same code stops supplying the zone and starts enforcing agreement with it — no second migration, and no window in which a stale registration silently wins. -It is safe only because client registrations are static and deployment-owned. -KeyCape excludes dynamic client registration by design; a self-service client -able to name its users' tenant would be a straightforward escalation, and this -rule must be revisited if that exclusion is ever lifted. +### Condition of the capability + +This is not a caveat on the reasoning; it is a condition of the capability, and +it is stated here so a future change to registration policy has to confront it. + +> **A client-declared tenant is safe only while client registrations are static +> and deployment-owned.** If KeyCape ever admits dynamic client registration, +> anyone able to register a client can name its users' tenant and relabel +> unplaced users into a zone. The deliberate binding becomes an escalation. That +> change may not be made without first deciding what happens to client-declared +> tenants — and removing this paragraph is not that decision. + +Recorded at the request of informed-decision, who will hold the approver +registration and asked for it in the contract rather than in a message. + +A document can be missed, so the condition is also enforced. +`TestRegistrationBoundTenantRequiresStaticRegistration` +(`src/internal/server/oidc/tenant_precondition_test.go`, KEY-WP-0030) asserts +both halves together: that a client-declared tenant still issues, and that +discovery advertises no registration endpoint. Whichever is removed first, the +failure points at the other — which is the part that matters, since +`tests/profile` has long asserted the endpoint's absence on its own and that +assertion reads as discovery metadata rather than as a warning about relabelling +users. Dynamic client registration is a deliberate exclusion in +[SCOPE](../SCOPE.md); this ties the tenant capability to that exclusion so the +two cannot drift apart silently. Covered by `src/internal/server/oidc/human_tenant_test.go`, including the relabel refusal.