Replace Murmur API secret with ZITADEL OAuth
Replace Murmur's long-lived shared API bearer secret with OAuth 2.0 client-credentials access tokens issued by the production ZITADEL instance. Identity configuration: - Issuer: `https://login.kaukus.no` - Audience/project ID: `395049603763798020` - Allowed Kaukus production service-account subject: `395049767509426180` - Kaukus client ID: `kaukus-murmur-production` - Kaukus stores the client secret as `MURMUR_SECRET`; the secret must never enter Murmur configuration, source, logs, tests, or task metadata. Scope: - Murmur validates JWT access tokens locally using the issuer's discovery/JWKS metadata. - Pin supported access-token signing to RS256; require exact issuer, audience and subject plus expiry/not-before validation. - Cache JWKS, bound refreshes for unknown key IDs, and fail closed without leaking token details. - Remove the static Murmur API token configuration and secret requirement; keep worker authentication unchanged. - Add focused tests for valid tokens, malformed tokens, wrong issuer/audience/subject, expiry, unsupported algorithms, unknown keys and key rotation. - Add Kaukus client-credentials acquisition/caching as a separate repository slice after the Murmur resource-server contract is verified. Acceptance criteria: - Authenticated Murmur API calls accept only valid JWT access tokens for the configured Kaukus principal and Murmur audience. - Invalid or unverifiable tokens receive a standards-appropriate 401 without sensitive details. - Key rotation works without per-request ZITADEL calls or unbounded refreshes. - Murmur starts without `MURMUR_API_TOKEN` and no longer documents or deploys that secret. - Rust format, check, tests and relevant configuration/container validation pass. Verified Murmur milestone: - Strict RS256 JWT validation, exact issuer/audience/subject checks, bounded discovery/JWKS reads, cache rotation, stale-key policy, and refresh backoff semantics are implemented on `feature/add-zitadel-api-auth`. - The old static API token is removed from Murmur config, Compose, documentation, and workload harness; the harness now accepts `MURMUR_ACCESS_TOKEN`. - Production discovery advertises client credentials and client-secret Basic authentication; its current JWKS exposes RS256 signing keys. - `cargo fmt`, locked check/tests (15 tests), Clippy with the one pre-existing Scaleway lint allowed, Compose rendering, workload syntax/lint, release container build, live issuer/JWKS startup from the non-root container, and final focused feature review pass. - A live service-account token was acquired through Kaukus's existing Kamal/1Password adapter without placing the secret in source. Its RS256 key, issuer, subject, audience and client claims match the resource-server contract. The issuer currently grants roughly 31-day JWTs, so Murmur now enforces a one-hour maximum age and Kaukus refreshes after at most 55 minutes. - A containerized end-to-end test with PostgreSQL accepted the real token with HTTP 202 and rejected missing/malformed credentials with HTTP 401. - Kaukus now has a shared, redirect-safe client-credentials implementation, a Murmur wrapper using HTTP Basic and the project audience scope, bounded Redis caching, explicit invalidation, production `MURMUR_SECRET` wiring, 30 passing focused/Visma-regression specs, RuboCop and Zeitwerk validation, and a live Rails-client claim check. - The production Kamal secret file now quotes fetched JSON consistently; this fixes extraction when 1Password section names or values contain spaces. An accidental private-session disclosure during diagnosis is tracked separately for credential rotation and migration-sensitive key handling. - Ansible synchronization is implemented in an isolated worktree: the static API secret is removed, production auth metadata and the one-hour limit are rendered, API ingress is restricted to the Kaukus production host, and YAML/Ansible lint, syntax, inventory, TOML and Compose rendering pass. - The future Rust identity replacement still needs compatible client-credentials JWT issuance; that dependency is tracked separately.
Checklist
4 of 4 complete- Implement strict ZITADEL JWT validation and bounded JWKS caching in Murmur
- Remove static API-token configuration and update Murmur deployment documentation
- Verify Murmur tests, configuration, container build, and live ZITADEL metadata compatibility
- Implement and verify Kaukus client-credentials token acquisition and caching
- Area
- Kaukus
- Project
- Deploy Murmur to production
- Kind
- Feature
- Priority
- High
- Task ID
tsk_8qqcyknfdq- Updated