railiance-platform replied on all three open threads. Recording what they add rather than what we already knew. T02: they reached the same reading of the verifier receipt independently and add human_client_consume_denied: true for both clients, confirm the verifier ran twice (activation and post-rollout) at generation 38 with the signing key unchanged, and state T02 can close against that receipt. They also correct our framing, rightly: the packet says client-side retrieval is unadmitted, which stays true, but the attended operator path is not a client-side read and never required one. This task had been treating those as the same constraint. T04: the live approval clients mean this repo now holds a committed receipt that looks like rotation evidence and is not. Both owners independently state the same two gaps -- no real predecessor rotation, no observed wall-clock expiry. Recorded in T04 rather than only in T02, because verify-client's predecessor rejection is now implemented and unproven, which is a different state from missing or done, and T04 is where that distinction belongs. Answered their open question on CCR-2026-0020, which has no named presenting actor. As issuer: the registration carries both approval:create and approval:approve, so one presenter can create an entry and approve it. That is a separation-of-duties property of the holder, not a defect in the token -- KeyCape issues the grants approval-engine asked for. Recorded both shapes KeyCape can support, and that who holds it is approval-engine's decision and the doctrine question gate-house's, not ours. Also narrowed the operations note: the deployed config has not been written since the activation, so the inspected state is the state that will boot. 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
124 lines
6.9 KiB
YAML
124 lines
6.9 KiB
YAML
# Proposed non-secret admission packet. This is not executable authorization.
|
|
# 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.
|
|
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
|
|
tenant: tenant:platform
|
|
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
|
|
tenant: tenant:platform
|
|
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
|
|
blocks_service_client_rollout: false
|
|
# Owner identified 2026-09-09: informed-decision (hub repo cf4c7da8). It
|
|
# supplies client_id and callback URI from INFD-WP-0001-T07 once it has a
|
|
# deployed origin. approval-engine is a bearer-only resource server and never
|
|
# owned those strings.
|
|
owner: informed-decision
|
|
# approval:read added 2026-09-09 on approval-engine's finding: the surface
|
|
# cannot render a decision without GET /v1/approvals/{id} and /claim, so the
|
|
# earlier scope set let an approver submit what they could not display.
|
|
scopes: [openid, approval:read, approval:approve]
|
|
mfa_required: true
|
|
client_type: public
|
|
grant: authorization_code + S256 PKCE
|
|
never: [approval:consume]
|
|
# Required. Without it the token carries tenant:coulomb from the directory
|
|
# default and approval-engine refuses it. See docs/tenant-claim-contract.md.
|
|
tenant: tenant:platform
|
|
keycape_side_resolved: |
|
|
2026-09-09: a human token can now carry tenant:platform. A client
|
|
registration may declare a tenant; humanTenant() supplies it when the
|
|
directory has not placed the user, requires agreement when it has, and
|
|
refuses issuance on conflict rather than relabelling. Safe only because
|
|
registrations are static and deployment-owned. Still outstanding from
|
|
elsewhere: the exact client_id and callback URI from informed-decision
|
|
(INFD-WP-0001-T07), and whether the owners prefer the directory-sourced
|
|
resolution instead, which this implementation degrades into cleanly.
|
|
verification:
|
|
# 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"
|
|
- Check KeyCape and consumer readiness without emitting secrets or tokens.
|
|
- Preserve existing registrations and signing key; record versions and image digest.
|
|
- 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.
|
|
# Asked by railiance-platform 2026-09-09 (CCR-2026-0020 has no named presenting
|
|
# actor in any owner source, and they declined to guess one). This is KeyCape's
|
|
# view as the issuer of the identity, not a decision: who may hold the
|
|
# credential is approval-engine's call and the doctrine question is
|
|
# gate-house's.
|
|
presenting_actor_note:
|
|
client_id: approval-engine-operator
|
|
observation: |
|
|
The registration as issued carries both approval:create and approval:approve,
|
|
so a single presenter can create an entry and then approve it. That is a
|
|
separation-of-duties property of the credential holder, not a defect in the
|
|
token -- KeyCape issues exactly the grants approval-engine requested, and
|
|
splitting them would be a change to that request rather than to issuance.
|
|
options_keycape_can_support:
|
|
- Two registrations with disjoint grants, one creating and one approving, if
|
|
approval-engine wants the split enforced at issuance. KeyCape can do this
|
|
today; it needs approval-engine to say so, since it changes their contract.
|
|
- Keep one registration and constrain the holder by custody instead, which is
|
|
where it sits now.
|
|
keycape_does_not_decide: |
|
|
Who presents this credential, and whether self-approval is acceptable for the
|
|
lifecycle operator, are not KeyCape's to settle. Recorded here so the question
|
|
is answered from the registration rather than reconstructed from it.
|
|
|
|
blockers:
|
|
- Admit exact custody paths, field delivery, consumer identities and lifecycle authority.
|
|
- Resolve attended first-provision authority through the custody owner.
|
|
- Verify the actual upstream ID-token issuer before production image rollout.
|
|
custody_return:
|
|
owner_record: railiance-platform/workplans/RPF-WP-0035-credential-lane-implementation.md#Admit-KeyCape-approval-engine-client-custody-and-delivery
|
|
requests: [CCR-2026-0017, CCR-2026-0018]
|
|
status: proposed-awaiting-owner-approval
|
|
field_correction: CLIENT_SECRET
|
|
scope: KeyCape verifier-side copies only; client-side retrieval is not admitted.
|
|
human_registration_gate:
|
|
- The approver UI owner must supply its real client ID and exact callback.
|
|
- This gate blocks human approval entry; it does not block the two independent client_credentials registrations or service startup.
|