| KeyCape config/JWT/JWKS behavior | key-cape | Pin the complete non-secret client configuration and the signing-key strategy; verify discovery, new JWTs, JWKS, and old-token invalidation. |
| LLDAP provider and Authelia consumer | net-kingdom | Replace the LLDAP credential at its issuer, update Authelia's consumer binding, and prove predecessor denial. |
| Authelia client provider | net-kingdom | Install the replacement client-secret hash and prove old-secret rejection. |
| privacyIDEA token provider | net-kingdom | Issue a replacement token with overlap, verify it, then revoke the predecessor. |
| Downstream JWT consumers | service owners coordinated by key-cape | Refresh JWKS caches or restart as declared and prove new-token acceptance plus old-token rejection. |
`warden route show openbao-api-key` confirms railiance-platform owns the
non-automatable rotation mechanics; ops-warden routes but does not execute.
## Required decisions and receipts
Before any value exists, record one revision-pinned receipt containing:
- this incident id and exact Secret UID/resource version;
- KeyCape, NetKingdom, and railiance-platform Git revisions;
- a named start/end window of at most 30 minutes;
- the attended driver and independent abort operator;
- owner acknowledgements for all four credential classes;
- the exact non-secret KeyCape client-config source;
- the chosen signing strategy and downstream cache behavior;
- explicit permission for provider writes, the one Secret apply, rollouts,
predecessor revocation, and protected negative verification.
KeyCape currently signs and publishes only hard-coded `kid=key-1`. Its
`KEY-WP-0011` records operator acceptance of deliberate session/token
invalidation, but that is not a live GO for this platform plan. Before the
window, KeyCape must pin one of these concrete implementations:
1. a reviewed unique-kid/multi-key overlap revision; or
2. deliberate immediate invalidation, including explicit downstream JWKS-cache
refresh/restart steps and proof that the old controlled token is rejected.
Do not rotate a key behind the same cached `kid=key-1` without the declared
cache invalidation procedure.
## Attended sequence
### 1. Preflight and hold
1. Recheck the metadata anchor without reading Secret data.
2. Verify all pinned repositories are clean and at the approved revisions.
3. Verify KeyCape, Authelia, LLDAP, and privacyIDEA are healthy.
4. Create one controlled pre-cutover OIDC token and keep it only in the private
workspace for the post-cutover negative test.
5. Verify the cleanup trap and abort operator, then stop at an exact human GO.
### 2. Prepare one replacement bundle
1. Generate the new signing key and selected unique kid/rollover metadata.
2. Generate the replacement LLDAP and Authelia credentials.
3. Ask privacyIDEA to issue the replacement admin token while the predecessor
remains valid.
4. Build the complete KeyCape `config.yaml` once from the pinned non-secret
client configuration plus the three replacement provider credentials.
5. Build the Authelia replacement configuration/hash from the same LLDAP and
Authelia values.
6. Validate syntax and derive only safe fingerprints. Do not print either file.
### 3. Provider and consumer cutover
1. Install the replacement Authelia client hash and replacement Authelia LLDAP
binding without using a stale full-bundle generator.
2. Replace the LLDAP provider credential. From this point the prior LLDAP
credential must fail and the bounded SSO interruption clock starts.
3. Apply exactly one reconstructed `sso/keycape-config` bundle guarded by the
anchored Secret UID/resource version. The apply consumes `config.yaml` and
`key.pem` from files and must not emit a Secret manifest.
4. Roll Authelia and KeyCape, wait for observed generations and readiness, and
abort forward if either fails. Never restore the exposed bundle.
5. Keep the predecessor privacyIDEA token only until positive KeyCape MFA proof
completes, then revoke it.
### 4. Positive and negative proof
Record only pass/fail and safe identifiers:
- discovery and JWKS are reachable; JWKS digest/kid match the approved result;
- a newly issued controlled JWT validates at a downstream consumer;
- the pre-cutover controlled JWT is rejected after the declared invalidation
or overlap expiry;
- KeyCape can perform an LLDAP lookup with the replacement and the predecessor
bind credential is rejected;
- Authelia accepts the replacement KeyCape client credential and rejects the
predecessor;
- KeyCape completes privacyIDEA MFA with the replacement token and the
predecessor token is rejected after revocation;
- KeyCape, Authelia, LLDAP, privacyIDEA, and affected downstreams are Ready.
Any ambiguous result is a fail-closed abort. Do not extend the window by
restoring or re-enabling an exposed predecessor.
### 5. Cleanup and evidence
1. Revoke every predecessor not intrinsically invalidated by its provider.
2. Securely remove the private workspace and verify all files are absent.
3. Record the new Secret resource version, public JWKS digest/kid, provider