Repository navigation
Certify JWK rotation, stale-cache, and emergency revocation for edge capabilities #88
Description
Goal
Turn key rotation for authenticated Cloudflare fallback and edge/origin proofs into an executable outage contract rather than an assumed operational property.
Coordinates:
- Edge auth v1: signed fallback capabilities and provider-specific credential broker #74 / DEN-2859: add signed edge capability verification for authenticated fallback #80 — signed edge fallback capabilities;
zed-pkg/zed-interfaces#147— EdgeFallbackCapabilityV1 authority;- Authenticate Cloudflare-to-origin requests independently of end-user auth #87 — Cloudflare-to-origin service authentication.
This issue owns key lifecycle and outage semantics, not the capability grant model itself.
Rotation model
Define a bounded key lifecycle with explicit states such as introduced/active/retiring/revoked and prove:
- new signing key can be published before first use;
- old + new verification keys overlap for a bounded interval;
- issuers stop minting with the retiring key before verifiers remove it;
- unknown
kidfails closed and does not trigger unbounded refetch loops; - stale verifier caches have a maximum accepted age;
- cache refresh respects HTTP/JWK freshness metadata within a repository-owned upper bound;
- a normal issuer/JWK endpoint outage does not cause indefinite trust of stale keys;
- emergency revocation has a documented faster path than ordinary TTL expiry.
Separation of key sets
If authenticated fallback capabilities and edge→origin service proofs use distinct issuers/audiences or key sets, keep them cryptographically and operationally distinct. Do not create one universal high-authority key merely for convenience.
Failure semantics
Exercise at least:
- old key only;
- old + new overlap;
- issuer signs with new key after verifiers have learned it;
- verifier has stale old-only cache when new token arrives;
- JWK endpoint unavailable while cached keys are still inside freshness bound;
- JWK endpoint unavailable after maximum stale bound;
- unknown kid flood;
- malformed JWK / duplicate kid / unsupported algorithm;
- key removed too early;
- emergency revocation of a compromised active key;
- clock skew near
nbf/exp; - rollback to an older JWK document/version.
Cache / anti-amplification requirements
- one unknown kid must not cause every request/isolate to create unbounded JWK traffic;
- use bounded negative/single-flight refresh semantics where practical;
- key cache cardinality and document size are bounded;
- refresh failures are typed/redacted;
- no JWT/capability body, provider secret, or signing private key enters logs/artifacts.
Evidence
Add deterministic fake-clock unit tests plus Worker-runtime integration coverage. Retain a compact rotation timeline/receipt proving which key ids were accepted/rejected at each phase without retaining bearer tokens.
Done when
The edge can survive routine overlapping rotation, fails closed after bounded stale-key tolerance, can reject a compromised key promptly, and every transition is covered without depending on Shared Auth or the primary Zed API being continuously reachable during verification.
Activity