ADR 0008: The startupos-services client replaces the shared service client
- Status: accepted, in progress
- Date: 2026-11-07
- Decision makers: the project owner, as recorded in the Keycloak fix plan
Context and problem statement
All eight services used one Keycloak client, startupos-backend, for client-credentials calls. Its secret needed to be replaced with a generated one that exists only in the cluster. How should that happen without a window in which a service cannot get a token?
Decision drivers
- No downtime at any step.
- Evidence of retirement without printing a secret.
- Avoid enabling a preview feature on the identity provider of a live system.
Considered options
- Rotate the secret in place.
- Enable the preview client-secret rotation executor.
- A blue/green swap: create a new client with a generated secret, move services over, then retire the old client.
Decision outcome
A blue/green swap. A new confidential client, startupos-services, has a generated secret stored in the Secret startupos-oidc-client and read by every service through secretKeyRef. The realm script refuses to use the repository default on a non-local URL, and a flagless re-run cannot re-enable the retired client. Services move over one at a time. The old client stays enabled until the last service has moved, and is then disabled and its secret regenerated or the client deleted.
Consequences
- Good: the rehearsal showed zero failures on old and new credentials during cutover, and the retired client refused even its own secret.
- Bad: until the old client is retired, both clients are enabled.
Confirmation
When complete: each Deployment's QUARKUS_OIDC_CLIENT_ID is startupos-services, and a client-credentials request for the old client is refused.
Sources
docs/runbooks/keycloak-client-secret-rotation.md, docs/runbooks/keycloak-fix-final-report.md, .agents/tasks/keycloak-fix/plan.md, live read on 2026-11-07.