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
Updated by fix-consistency on 2026-09-10:
- update .custodian-brief.md for key-cape
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
Every closure criterion now has evidence, taken one at a time rather than as an
impression. Custody admitted and provisioned (CCR-2026-0017/0018, both secrets
wired, receipt committed). The real callback registered, verified live by its
owner, pinned by test. The new contracts deployed and verified at the 2026-09-09
attended rollout: acceptance passed at generation 38, per-client live JWKS
verification, exact claims, excess-scope and wrong-secret denial, human consume
denied, no credential values emitted. Token types reconciled at the consumer
boundary -- ops-warden took option (a) because the proxy's OpenBao token and an
issuer JWT were never one thing to cut over between; both lanes owner-confirmed
and no route changed. Four handoff receipts retained.
The condition that named the gap -- source capability running ahead of live
custody and consumer adoption -- no longer holds.
What closing it does not claim, stated in both documents: the approver
registration is published, not deployed, so the human approval path is registered
rather than proved; the deployed image predates most of this revision; the
verifier receipt declines real predecessor rotation and observed wall-clock
expiry and so do we; and the Qonto rotation is deferred by owner decision on
evidence. Those are open items with owners and triggers, which is a different
thing from a gap between what this repository claims and what is true.
SCOPE's header lineage is consolidated so a reader can ask what changed since a
given revision and get an answer, and the test count is refreshed rather than
carried.
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
KEY-WP-0014-T04 sat `wait` with nothing outstanding, which is a contradiction.
Its title is admit rotation and verify consumer handoff, and both are delivered:
the semantics are published, the executor, authority and transport are named, the
CCR will be prepared on request, and step 4 shipped as keycape verify-client;
ops-warden took option (a) for the reason given, with both lanes owner-confirmed
and no route changed. Executing a rotation was never its deliverable, so treating
the owner's deferral as an open item would have kept the task open against work
it was not scoped to do. The deferral stands separately, revisited on evidence.
GH-DEC-2026-016 §5 applies A-16 to what makes a principal human. Verified against
source that `human` has exactly one route here -- a literal on the
authorization-code path after an upstream login resolved to a directory user,
with no configuration able to assert it -- so A-16 does not yet bite and no
provenance claim is warranted. Adding one would encode a distinction that does
not exist.
Asserting the behaviour would not protect that: a test checking a human token
says human passes just as happily when the value starts coming from a
registration. The guard parses the package and requires every principal_type
assignment to be a string literal, the set being exactly human and service. It
covers both shapes -- the browser path assigns into a map, the service path uses
a key-value pair in a map literal -- and checking only assignments found one of
two routes and passed, which the pinned literal set caught. Verified by mutation.
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
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
Updated by fix-consistency on 2026-09-10:
- update .custodian-brief.md for key-cape
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
informed-decision submitted client_id informed-decision-approver and redirect
https://decisions.coulomb.social/auth/callback, with the origin already live and
verified by them rather than reported: both / and /auth/callback return 200 on a
Let's Encrypt certificate valid to 2026-12-09. The host is decisions, not the
decide of an earlier draft. Its path serves a placeholder for now, which does not
matter -- the redirect is matched as an exact string and never fetched.
Published as a public authorization_code client with S256 PKCE, audience
approval-engine, scopes openid/approval:read/approval:approve, mfaRequired true
and a declared tenant:platform. No secretRef, since PKCE is the whole proof.
TestApproverRegistrationShapeIsExact pins every field, so widening a scope or
relaxing MFA fails the build rather than reading as an edit, and asserts the
registration passes startup validation -- proving the KEY-WP-0028 tenant
exemption holds for the registration that actually depends on it.
Two existing guards fired on the way in and neither was loosened. The tenant pin
refused an unreviewed client carrying a tenant, which is its purpose, so the
approver was added to its reviewed set deliberately. And the audience test
panicked slicing secretRef[4:], an assumption that held while the fixture had
only confidential clients; the approver is the first public one, so the loop now
guards on the env: prefix.
The declared tenant reaches the token by the GH-DEC-2026-013 gap route by
construction, and tenant_source says so: registration, never directory.
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
approval-engine chose the registration-bound shape for the consuming side and
asked that the limit making it admissible be carried into the contract rather
than left in a message.
Their check is store isolation -- does this caller belong to the store this
engine serves -- not membership. A registration-supplied tenant is admissible for
that question. It is not admissible for any doctrine turning on the approver's own
membership, which is a fact about the person that this claim cannot carry, and an
exact-match check does not become that claim merely by matching.
That is GH-DEC-2026-013 section 1 reached independently from the consuming side,
and it is the practical reason tenant_source exists: a consumer whose check means
store isolation can accept registration, one whose check means membership must
require directory. Recorded next to the provenance table so the two are read
together.
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
The repository owner declined to schedule the rotation now. Recorded with the
reasoning rather than as a bare status so it is revisited on evidence instead of
re-litigated: nothing indicates compromise, the offer stands open, and one
founder-attended window is already pending for the fail-closed startup changes.
Names what should reopen it -- an actual or suspected exposure, the secret's age
becoming a stated concern, a consumer requiring proof of rotation, or a decision
to prove rotation step 4 before relying on it -- and says plainly that a calendar
date is not one of them.
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