Split the gate-house ruling work into its own workplan

fix-consistency skipped C-11 for two tasks I had appended to KEY-WP-0030 after
marking it finished, so they were never registered in the hub. The skip was
right: appending tasks to a finished workplan is the wrong shape, and the fix is
structural rather than flipping a status to get them registered.

The provenance implementation and the condition (b) correction are responses to
GH-DEC-2026-013, not to informed-decision's request for an enforced precondition.
They are now KEY-WP-0031, which also records that conditions (a) and (c) needed
nothing from this repository and why.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
This commit is contained in:
tegwick 2026-09-10 08:05:49 +02:00
parent 7f6fdd00e6
commit f2c9aa45a8
2 changed files with 78 additions and 52 deletions

View file

@ -51,58 +51,6 @@ This is deliberately not a vote on the tenant question. It makes the preconditio
of one option checkable; it does not choose between them, and if option 1 lands
the capability and this guard are removed together.
## Carry the tenant claim's provenance
```task
id: KEY-WP-0030-T03
status: done
priority: high
```
gate-house ruled on GH-DEC-2026-013 while this was in flight. Section 5 is a
finding nobody asked for and is ours to implement: `tenant` is a bare string, so
a consumer cannot tell a zone the directory asserted about the person from one a
registration supplied about the client they came through. approval-engine
exact-matches that string while its contract reads as though it relies on the
first — the check is sound and the property a reader infers from it is absent.
Every token now carries `tenant_source` beside `tenant`: `directory`,
`registration`, or `default`. It is advertised in `claims_supported` and asserted
on both grants at the token level, not only in the resolution function, because
the claim a consumer reads is the thing under obligation.
Three values where the ruling names two, and that is the substantive judgement
here. Labelling an unasserted profile default as `directory` would reproduce the
same defect one level down — a consumer reading an assertion the identity layer
never made. The ruling cites GH-DEC-2026-011 §3 on unknown versus absent for the
case it examined; the same rule applies to our own fallback, so the fallback is
named rather than folded into the strongest neighbouring value.
The agreement case resolves to `directory` deliberately: if a registration
declares the zone the directory also assigned, the directory did assert it, and
reporting the weaker source would understate what is known.
## Condition (b) corrected a message I had just shipped
```task
id: KEY-WP-0030-T04
status: done
priority: high
```
The guard committed in `5f516a0` told a future reader that adding dynamic
registration could be resolved by dropping the capability **or gating it to
statically configured registrations**. Condition (b) voids the second: admitting
dynamic registration voids the registration-bound shape that day, and the
directory becomes the only source whatever state the adapter is in. gate-house
strengthened our own "must be revisited" on the grounds that *revisited* implies
the answer might survive review, and it would not.
So the message offered a way out the ruling forbids, in the exact place someone
would read it while making that change. Corrected the same day. Worth recording
rather than quietly editing: the guard was written to force a confrontation, and
a guard that suggests an inadmissible resolution is worse than none.
## What stays with the owners
```task

View file

@ -0,0 +1,78 @@
---
id: KEY-WP-0031
type: workplan
title: "Implement the gate-house tenant ruling"
domain: infotech
repo: key-cape
status: finished
owner: claude
topic_slug: gate-house-tenant-ruling
created: "2026-09-10"
updated: "2026-09-10"
---
gate-house ruled GH-DEC-2026-013 (`gate-house@16c1d46`) on the human-tenant
question KeyCape declined to settle for itself. Directory-sourced is the terminal
state; the registration-bound shape is granted as a declared bounded gap under
three conditions, on the general property that *a transitional shape is
admissible where it fails closed on exactly the case distinguishing it from the
correct resolution*. Ours refuses issuance where registration and directory
disagree, which is that case.
Conditions (a) and (c) needed nothing from this repository — (a) is already the
implemented behaviour, and its strengthening, that a future change preferring the
**directory** is equally void because picking any winner is a silent
cross-tenant assertion, is recorded in the contract. This workplan covers the two
items that were implementation.
## Carry the tenant claim's provenance
```task
id: KEY-WP-0031-T01
status: done
priority: high
```
gate-house ruled on GH-DEC-2026-013 while this was in flight. Section 5 is a
finding nobody asked for and is ours to implement: `tenant` is a bare string, so
a consumer cannot tell a zone the directory asserted about the person from one a
registration supplied about the client they came through. approval-engine
exact-matches that string while its contract reads as though it relies on the
first — the check is sound and the property a reader infers from it is absent.
Every token now carries `tenant_source` beside `tenant`: `directory`,
`registration`, or `default`. It is advertised in `claims_supported` and asserted
on both grants at the token level, not only in the resolution function, because
the claim a consumer reads is the thing under obligation.
Three values where the ruling names two, and that is the substantive judgement
here. Labelling an unasserted profile default as `directory` would reproduce the
same defect one level down — a consumer reading an assertion the identity layer
never made. The ruling cites GH-DEC-2026-011 §3 on unknown versus absent for the
case it examined; the same rule applies to our own fallback, so the fallback is
named rather than folded into the strongest neighbouring value.
The agreement case resolves to `directory` deliberately: if a registration
declares the zone the directory also assigned, the directory did assert it, and
reporting the weaker source would understate what is known.
## Condition (b) corrected a message I had just shipped
```task
id: KEY-WP-0031-T02
status: done
priority: high
```
The guard committed in `5f516a0` told a future reader that adding dynamic
registration could be resolved by dropping the capability **or gating it to
statically configured registrations**. Condition (b) voids the second: admitting
dynamic registration voids the registration-bound shape that day, and the
directory becomes the only source whatever state the adapter is in. gate-house
strengthened our own "must be revisited" on the grounds that *revisited* implies
the answer might survive review, and it would not.
So the message offered a way out the ruling forbids, in the exact place someone
would read it while making that change. Corrected the same day. Worth recording
rather than quietly editing: the guard was written to force a confrontation, and
a guard that suggests an inadmissible resolution is worse than none.