Assistant: codex Assistant-Model: gpt-5.6-luna Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
4.9 KiB
KeyCape approval-client rollout and recovery
Accepted 2026-09-09 under CCR-2026-0017 and CCR-2026-0018. Both service registrations are live on one ready KeyCape replica. The existing human OpenBao login passed after replacement. Live receipt. The attempt receipts retain failed checks and confirmed compatible rollback; no failed attempt is counted as activation. Both OpenBao values remain at their initial version 1.
The source image is the immutable manifest
forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611.
Deployment authority is sso-mfa/k8s/keycape/deployment.yaml; the live config
remains in sso/keycape-config. The contained helper appends only the two
reviewed client registrations and preserves the signing key and every unrelated
configuration byte. It uses UID/resourceVersion tests for config and deployment
mutations, and retains the previous compatible pair in protected owner storage.
The platform command scripts/keycape_approval_custody.py opens through
openbao-attended-exec.py and the governed Warden openbao-platform-admin-login
envelope. It owns approved policies/roles, CAS=0 first provision, ESO delivery,
native scope/auth/namespace denials and reader revocation. It invokes this
repository's sso-mfa/k8s/keycape/approval-clients-rollout.py for image/config
replacement and service acceptance. Do not run the platform child directly.
On this workstation the verified Railiance kubeconfig is
/home/worsch/.kube/config-railiance01; the default config targets another endpoint.
Use activate only for a first provision with absent custody and delivery.
resume-activate --prior-receipt <metadata receipt> requires a completed compatible
rollback, unchanged version-1 custody, unchanged policies and detached reader roles.
It reattaches the same readers without writing any value. Both actions require a
unique --receipt and --recovery path. Successful service acceptance is followed
by a fresh attended login running the owner helper's verify-after-login action.
Existing active custody can be rechecked with the platform helper's verify
action. Repeating first provision against active custody is deliberately refused.
The verifier binary comes from the pinned image, without starting its extraction
container. Install it in the owner-protected path
~/.local/share/key-cape/verified-bin/dcebd46/keycape with mode 0700. Its SHA-256
must be 4bf93bbe9afe0bf2e21d51c03373a7e2b4be6864586bcc2d472eeb9abc913d92;
the helper checks this before custody mutation and before each verifier run.
Extraction needs only docker create, docker cp <container>:/keycape <private path>,
and removal of that never-started container. No credential enters that container.
Run the native verifier in the existing attended owner process. It receives the
same verifier-side credential already read privately for independent JWT checks,
through a child environment that is never printed or written to a file. The
KeyCape pod's internal-only egress policy does not admit its public HTTPS issuer;
this rollout makes no network-policy change. Container readiness checks the
manifest digest in imageID, since containerd's image field can hold a different
runtime configuration digest.
Independent JWT checks match the existing native contract: at most 30 seconds
of future issued-at time, strict not-before and expiry, exact audience/subject/
tenant/role/scope and a 900-second lifetime. Global JWT leeway is not used.
Wrong secrets and excess scopes require the exact issuer HTTP status/error/feature.
The public human OpenBao client is also denied approval:consume.
Reproducible preparation checks:
python3 -B sso-mfa/k8s/keycape/test_approval_clients_rollout.py
python3 -B sso-mfa/k8s/keycape/exercise-approval-clients.py --receipt /tmp/<unique-scratch-receipt>.json
The second command requires Docker, the installed pinned verifier, PyYAML,
PyJWT and cryptography. It runs the pinned image behind loopback HTTPS with
synthetic signing keys and client credentials, including the native verifier.
It removes its container, TLS server and temporary credential files. It neither
reads production config nor opens an attended login. The platform's
tests/test_keycape_approval_custody.py separately exercises real ACLs, CAS=0,
revocation and version-preserving resume against disposable local OpenBao.
KEY-WP-0013-T02 is complete. KEY-WP-0013-T05 retains the approval UI's callback and MFA/PKCE acceptance. Separate client-side delivery remains RPF-WP-0035-T05; audit custody remains AUDIT-WP-0009-T09; claim/consume and native execution proof remain APPROVAL-WP-0002 and SECRETS-WP-0009-T03. Initial provisioning did not exercise natural JWT expiry or actual predecessor rotation. HFACT-WP-0001 retains factory execution/grant/spend admission and Railiance worker acceptance.