KEY-WP-0013-T02 and KEY-WP-0014-T04 stay blocked on custody and on ops-warden, but each contains a KeyCape-owned piece that had been left as prose. T02 requires proving "live JWKS verification and denied excess scopes without logging values"; T04 step 4 requires verifying a rotated secret, refusing its predecessor and refusing excess scope. Both were describable and neither was runnable, so the proof would have been improvised by hand against production at the moment custody lands -- the worst possible time for it. keycape verify-client does it in one command. Per registration it checks discovery origin, the client_credentials exchange and its RS256 signature against the deployed JWKS, exact sub/tenant/roles/principal_type, that every -deny-scope is refused, and that the token carries no scope that was not requested. That last check is a real gap: the caller commands prove every requested scope was granted, never that nothing extra came back. -previous-secret-env additionally requires the predecessor to be refused, and treats an unchanged secret as a rotation that did not happen. Nothing is written to disk and no value is printed. Failures name the claim, not the observed value, so running this against production cannot turn a verification into a disclosure. Every check runs before it reports, so one failure does not hide the rest. The exact invocation for each approval client is recorded in the verification block of the provisioning packet, so custody admission hands back a command rather than a description. Tests cover the passing case, an over-broad registration, a live predecessor, an identical rotation and output non-disclosure; neutering mustFail makes the suite fail, so the checks have teeth. Also recorded in KEY-WP-0014: read from ops-warden's catalog rather than waiting for a reply, key-cape-oidc-login is asked-and-waiting on us since 2026-08-28 and is a pointer lane with no programmatic consumers, and the rapp-qonto-keycape-client blocker citing an absent native exchange command went stale when service-token shipped on 2026-09-05. 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
6.2 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| KEY-WP-0014 | workplan | Review native login and client credential lane handoffs | infotech | key-cape | blocked | codex | native-credential-lane-handoff | 2026-09-05 | 2026-09-08 | 0d003df3-f7d3-5063-8ca0-e1e33f7df74a |
Source: ops-warden inbox message 0dd9c7bd-0ecd-42d1-806f-7cc4ba9730ed. The native service exchange and public PKCE login commands are now implemented. Cross-owner rotation and consumer-specific route cutover remain outstanding.
Design owner command and custody boundaries
id: KEY-WP-0014-T01
status: done
priority: medium
state_hub_task_id: "0c0a0b61-c19e-5631-9cda-8b2dc0f47d8f"
Review ops-warden's existing key-cape-oidc-login proxy and rapp-qonto-keycape-client route contracts. Specify the native interactive login and bounded exchange commands, token delivery, renewal and custody-mediated rotation before implementation. Keep secret custody with OpenBao and avoid retiring the proxy until replacement commands have equivalent verification.
Verify handoff delivery evidence
id: KEY-WP-0014-T02
status: done
priority: low
state_hub_task_id: "d9a5de97-b7d5-5599-98c2-eaab32f51495"
Ops-warden reports KEY-WP-0009-T04's claimed reply did not arrive. Verify prior receipts for all four named recipients before claiming successful notification. No outbound coordination messages were sent during the 2026-09-05 repo review.
Implement and verify native caller commands
id: KEY-WP-0014-T03
status: done
priority: high
state_hub_task_id: "4e46f474-a15e-594f-ae07-ad37a9667d89"
Implemented keycape service-token and login with HTTPS discovery, RS256/JWKS verification, exact audience bindings, PKCE/state/nonce, private out-of-Git file delivery and redacted errors. Service Basic authentication now form-decodes credentials. Integration tests exercise the real token/JWKS handlers and browser callback, including forged state, tampering, excess scope and unsafe output. See docs/native-authentication.md for invocation and ownership boundaries.
Admit rotation and verify consumer handoff
id: KEY-WP-0014-T04
status: wait
priority: high
state_hub_task_id: "e7632c71-9676-5837-a925-7f905e3015c5"
Qonto rotation requires admitted custody/provider transaction and rollback semantics; see the exact review sequence in docs/native-authentication.md. The current login proxy yields an OpenBao token, so it cannot be replaced by a JWT-writing command without adapting its consumer contract. Verify that split with the platform owner and ops-warden before route changes. No route was changed.
2026-09-05 receipt audit: GET /messages/?from_agent=key-cape returned one 2026-03 image-publication message and no KEY-WP-0009 handoff receipts for NetKingdom, secrets-engine, ops-warden or railiance-platform. Corrected the unsupported statement in KEY-WP-0009-T04. This proves only that no receipts are present in the current Hub response, not that no message ever existed. The 2026-09-05 audit's finding stands as recorded; the replacement outbound messages were sent on 2026-09-08 (below).
2026-09-08: 0a6c9d88-cf50-45d8-acdc-99a40747683e -> ops-warden, readable back
via GET /messages/?from_agent=key-cape. It puts both open questions to the
route and custody owner in one place:
- The
key-cape-oidc-loginproxy yields an OpenBao token andkeycape loginyields an issuer JWT — different credential types, different verifiers, different enforcement owners, so not interchangeable. Two admissible options are offered: keep the proxy and runkeycape loginalongside it for JWT consumers, or adapt the route's consumer contract to a JWT and then cut over. Option (a) is recommended until every consumer of the route is enumerated. - Qonto rotation for
rapp-qonto-keycape-client, quoting the five-step reviewed sequence fromdocs/native-authentication.mdand asking who executes the successor generation and CAS update, in which transport, under what authority. It records thatwarden route/warden planreturned no exact admitted lane and that a generic match is not being treated as authorization.
The KEY-WP-0009 handoff ops-warden reported missing has also now been delivered
(5bc58847-eed5-4164-bb0f-a0d8455e75b8), closing the KEY-WP-0014-T02 correction.
Task remains wait — no route was changed and no rotation command ships until
ops-warden answers (1) and an execution/rollback authority is admitted for (2).
2026-09-08, second pass — read ops-warden's own catalog rather than waiting for a reply, and it changes the shape of both questions.
registry/routing/catalog.yaml, lane key-cape-oidc-login: intended_owner was
already corrected to key-cape, and verified: asked-and-waiting since
2026-08-28. ops-warden is waiting on us, not the other way round. The lane is
also warden_executes: false with a wiki_ref into CredentialRouting.md — a
pointer, per their ADR-0001, not a code path with programmatic consumers. So the
consumer-contract risk behind question (1) is smaller than assumed: adding
keycape login alongside retires nothing, and the acceptance we owe them is a
statement of ownership, not a cutover.
Lane rapp-qonto-keycape-client: rotation.owner: key-cape,
automatable: true, and blocked_on reads "still no key-cape-native
exchange/rotation command", verified: source-read 2026-08-28. That blocker is
stale. keycape service-token (T03) shipped 2026-09-05 and is exactly the
native client_secret_basic exchange they record as absent. It does not clear
the lane, and should be narrowed rather than closed.
Shipped here: keycape verify-client, which is rotation step 4 and the denial
checks step 5 rests on — new exchange verified against deployed JWKS, predecessor
refused, excess scope refused, no value printed or written. See
docs/native-authentication.md, "Verifying a live registration". The identical
predecessor case is treated as a failure, because an unchanged secret is a
rotation that did not happen.
Steps 1-3 remain custody's and are deliberately not automated. Task stays wait
on exactly two answers: which option ops-warden takes for the login proxy, and
who executes the successor generation and CAS update under what authority. No
route changed.