0023. Key rotation, JWKS publication, and multi-key lifecycle
Context
ADR-0003 made signing-key custody a trait (KeyCustody) but deliberately left
most of its surface to be filled in later. The operational lifecycle of those
keys is that surface, and it is constitution-critical, because the public half of
every signing key is what Vör reads to verify (ADR-0010). Two latencies are in
tension: keys should rotate often (security), but the edge caches public material,
so a token signed with a key the edge has not yet seen would fail verification. The
JWKS is also the clearest case of a read that must be a cached projection, never a
core read on the hot path (rule 1). This ADR fixes the rotation and publication
model.
Decision
-
Multiple concurrent keys,
kid-addressed. At any time Vord holds a current signing key, a next key, and one or more retiring keys, each identified by itskid. Tokens carry theirkid(ADR-0003); a verifier selects the matching public key from the JWKS. Per-tenant/realm key separation (ADR-0012) is the cryptographic isolation boundary. -
JWKS is a derived, edge-cached projection — never a hot-path core read. The published JWKS is a projection of the key set (ADR-0022), cached at the edge and refreshed on a short interval, exactly like the status list (ADR-0005). Vör reads the cache, not the core (ADR-0010, rule 1). Private keys are core/HSM-resident and never hot-path-read (rule 2); only public material is ever distributed.
-
Rotation overlaps, then retires — no orphaned token. A new key is published to the JWKS before it is first used to sign (publish-before-sign), so the edge has learned the new
kidbefore any token bearing it arrives. The retiring key stays published until every token it signed has expired (the overlap window ≥ the max token TTL), so no in-flight token is left unverifiable. Retirement removes the public key only after that window. -
Key-distribution latency is the named dual of revocation latency. Just as revocation has a propagation budget (ADR-0005), key introduction has one: the interval between publishing a new
kidand signing with it must exceed the edge JWKS-cache staleness bound. It is a stated budget and a security/freshness-plane signal, not an afterthought.
Consequences
- Aggressive rotation and edge caching coexist: publish-before-sign plus the overlap window mean rotation never produces a verification failure, so keys can rotate on a security-driven schedule without operational fear.
- The JWKS, the status list (ADR-0005), and the future SAML signing certificate (ADR-0017) are sibling edge-cached projections of core-resident authoritative material — one pattern, three artifacts, all keeping the verification path core-independent.
- KMS/HSM unavailability affects issuance only (new signatures), never
verification (which reads cached public keys) — the constitution working as
intended (ADR-0010 §3), and the failure-domain note ADR-0008 flags for
KeyCustody. - Production keys are a milestone of the implementation arc (M1); M0 uses a single
embedded-keystore key with rotation reserved, so the walking skeleton stays small
while the seam and the
kiddiscipline exist from the first token.