2026-09-05 01:08:58 +02:00
|
|
|
# Proposed non-secret admission packet. This is not executable authorization.
|
Align approval registrations to the tenant:platform decision
Operator decision 5ed3fb35-eca9-413a-82b9-95171ba85bf6 accepts tenant:platform
as the platform management tenant for the Glas approval chain, requiring exact
spelling across the approval store, the service-client JWT claim and the
lifecycle CheckRequest.
Changes the tenant field on secrets-engine-approval and approval-engine-operator
only, in the registration fixture and the provisioning packet. Unrelated clients
and the human directory default keep tenant:coulomb, and no audience, scope,
subject, role, lifetime or MFA grant changes.
Adds issuance evidence that the approval shape emits tenant:platform exactly and
never an alias the caller requests, that the OpenBao client gains no
cross-tenant reach, and a fixture guard pinning every reviewed client's tenant.
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
2026-09-06 22:30:32 +02:00
|
|
|
# Tenant for both requests is tenant:platform per decision
|
|
|
|
|
# 5ed3fb35-eca9-413a-82b9-95171ba85bf6 (landlord zone). Exact spelling required
|
|
|
|
|
# across the approval store, these JWT claims and the lifecycle CheckRequest;
|
|
|
|
|
# no alias to platform or tenant:coulomb.
|
2026-09-05 01:08:58 +02:00
|
|
|
status: awaiting-custody-admission
|
|
|
|
|
owner: key-cape
|
|
|
|
|
resource_audience: approval-engine
|
|
|
|
|
issuer: https://kc.coulomb.social
|
|
|
|
|
registration_source: config/service-clients.example.yaml
|
|
|
|
|
requests:
|
|
|
|
|
- client_id: secrets-engine-approval
|
|
|
|
|
subject: service:secrets-engine
|
Align approval registrations to the tenant:platform decision
Operator decision 5ed3fb35-eca9-413a-82b9-95171ba85bf6 accepts tenant:platform
as the platform management tenant for the Glas approval chain, requiring exact
spelling across the approval store, the service-client JWT claim and the
lifecycle CheckRequest.
Changes the tenant field on secrets-engine-approval and approval-engine-operator
only, in the registration fixture and the provisioning packet. Unrelated clients
and the human directory default keep tenant:coulomb, and no audience, scope,
subject, role, lifetime or MFA grant changes.
Adds issuance evidence that the approval shape emits tenant:platform exactly and
never an alias the caller requests, that the OpenBao client gains no
cross-tenant reach, and a fixture guard pinning every reviewed client's tenant.
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
2026-09-06 22:30:32 +02:00
|
|
|
tenant: tenant:platform
|
2026-09-05 01:08:58 +02:00
|
|
|
scopes: [approval:read, approval:consume]
|
|
|
|
|
lifetime: 15m
|
|
|
|
|
proposed_openbao_path: platform/workloads/secrets-engine/approval-client
|
|
|
|
|
field: client_secret
|
|
|
|
|
proposed_kubernetes_secret: sso/keycape-secrets-engine-approval-client
|
|
|
|
|
kubernetes_key: client-secret
|
|
|
|
|
keycape_environment: KEYCAPE_SECRETS_ENGINE_APPROVAL_CLIENT_SECRET
|
|
|
|
|
custody_owner: railiance-platform
|
|
|
|
|
consumer: secrets-engine
|
|
|
|
|
- client_id: approval-engine-operator
|
|
|
|
|
subject: service:approval-engine-operator
|
Align approval registrations to the tenant:platform decision
Operator decision 5ed3fb35-eca9-413a-82b9-95171ba85bf6 accepts tenant:platform
as the platform management tenant for the Glas approval chain, requiring exact
spelling across the approval store, the service-client JWT claim and the
lifecycle CheckRequest.
Changes the tenant field on secrets-engine-approval and approval-engine-operator
only, in the registration fixture and the provisioning packet. Unrelated clients
and the human directory default keep tenant:coulomb, and no audience, scope,
subject, role, lifetime or MFA grant changes.
Adds issuance evidence that the approval shape emits tenant:platform exactly and
never an alias the caller requests, that the OpenBao client gains no
cross-tenant reach, and a fixture guard pinning every reviewed client's tenant.
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
2026-09-06 22:30:32 +02:00
|
|
|
tenant: tenant:platform
|
2026-09-05 01:08:58 +02:00
|
|
|
scopes: [approval:create, approval:read, approval:approve, approval:revoke, approval:supersede, approval:observe, approval:emit]
|
|
|
|
|
lifetime: 15m
|
|
|
|
|
proposed_openbao_path: platform/workloads/approval-engine/operator-client
|
|
|
|
|
field: client_secret
|
|
|
|
|
proposed_kubernetes_secret: sso/keycape-approval-engine-operator-client
|
|
|
|
|
kubernetes_key: client-secret
|
|
|
|
|
keycape_environment: KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET
|
|
|
|
|
custody_owner: railiance-platform
|
|
|
|
|
consumer: approval-engine-operator
|
|
|
|
|
human_registration:
|
|
|
|
|
status: awaiting-exact-callback
|
|
|
|
|
scopes: [openid, approval:approve]
|
|
|
|
|
mfa_required: true
|
|
|
|
|
client_type: public
|
|
|
|
|
verification:
|
Ship the live-registration check both blocked tasks depend on
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
2026-09-08 14:30:43 +02:00
|
|
|
# The first two lines are now one runnable command per client; see
|
|
|
|
|
# docs/native-authentication.md, "Verifying a live registration". It writes
|
|
|
|
|
# nothing and prints no value, so it is safe to run against production.
|
|
|
|
|
- command: |
|
|
|
|
|
keycape verify-client -issuer https://kc.coulomb.social
|
|
|
|
|
-client-id secrets-engine-approval -audience approval-engine
|
|
|
|
|
-scope "approval:read approval:consume"
|
|
|
|
|
-secret-env KEYCAPE_SECRETS_ENGINE_APPROVAL_CLIENT_SECRET
|
|
|
|
|
-expect-subject service:secrets-engine -expect-tenant tenant:platform
|
|
|
|
|
-expect-roles secrets-engine
|
|
|
|
|
-deny-scope "approval:approve approval:revoke approval:supersede"
|
|
|
|
|
- command: |
|
|
|
|
|
keycape verify-client -issuer https://kc.coulomb.social
|
|
|
|
|
-client-id approval-engine-operator -audience approval-engine
|
|
|
|
|
-scope "approval:create approval:read approval:approve approval:revoke approval:supersede approval:observe approval:emit"
|
|
|
|
|
-secret-env KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET
|
|
|
|
|
-expect-subject service:approval-engine-operator -expect-tenant tenant:platform
|
|
|
|
|
-expect-roles approval-operator
|
|
|
|
|
-deny-scope "approval:consume"
|
2026-09-05 01:08:58 +02:00
|
|
|
- Check KeyCape and consumer readiness without emitting secrets or tokens.
|
|
|
|
|
- Preserve existing registrations and signing key; record versions and image digest.
|
Ship the live-registration check both blocked tasks depend on
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
2026-09-08 14:30:43 +02:00
|
|
|
- Human consume denial is approval-engine's to verify at its resource; KeyCape
|
|
|
|
|
proves only that the human client is never issued a consume grant.
|
2026-09-05 01:08:58 +02:00
|
|
|
blockers:
|
|
|
|
|
- Admit exact custody paths, field delivery, consumer identities and lifecycle authority.
|
|
|
|
|
- Resolve attended first-provision authority through the custody owner.
|
|
|
|
|
- Supply exact human client ID and callback URI.
|