Architecture Decision Record

0036. Key-compromise emergency response

Context

ADR-0023 specifies planned key rotation — overlap, then retire, so no in-flight token is orphaned. But a leaked signing key is the opposite situation: every token under that kid must die immediately, not after the overlap window. The §12.8 review flagged that the emergency path (distinct from planned rotation) was undecided. A signing-key leak is the most severe identity incident, so the mechanism is fixed here.

Decision

  1. Emergency kid revocation. A compromised signing key is revoked wholesale: its kid is removed from the published JWKS (ADR-0023) at once, and every token signed by it is invalidated via a kid-scoped revocation on the status list (ADR-0005) — not waiting for the rotation overlap. The wire form is the status list's dedicated key-revocation section (ADR-0043): a per-token bitstring cannot express "every token under this kid", so the list carries a revoked-kid set alongside it.

  2. Forced re-issue. Active sessions (ADR-0016) re-mint tokens under a fresh key; tokens bearing the compromised kid fail verification at the edge once the JWKS no longer carries it (and the status list reflects the revocation). This is the publish-before-sign discipline (ADR-0023) run in reverse — unpublish-then-the-kid-is-dead.

  3. Fail closed for the dropped kid (ADR-0010): a token whose kid is no longer in the JWKS cannot verify — the absence of the key is itself the kill switch, independent of the status list.

  4. Mechanism + runbook. The mechanism (kid-scoped revocation + JWKS removal + forced re-issue) is specified here; the operational runbook (detect → revoke → re-issue → post-incident review feeding ADR-0027) accompanies it.

Consequences

  • A key leak is contained in minutes (the edge JWKS-cache refresh bound) — a bound that is registered and gate-validated in the budget system (ADR-0039), not merely hoped for — rather than the rotation-overlap window: the blast-radius reduction a leaked signing key demands.
  • Two independent kill mechanisms (JWKS removal and status-list revocation) mean a token under a compromised kid dies even if one path lags. Both kill paths are themselves replay-protected: the JWKS and the status list carry the counter + max-age freshness discipline and are signed by the distribution key, not a token-signing key (ADR-0043) — otherwise a stale-JWKS replay would re-animate the removed kid, and the compromised key could forge a "clean" list defeating its own revocation.
  • Per-tenant/realm key separation (ADR-0023) bounds the scope: only the affected tenant's tokens are forced to re-issue.
  • Distinct from, and composes with, planned rotation (ADR-0023), the status list (ADR-0005), and the incident loop (ADR-0027). Closes the §12.8 key-compromise gap.