ADR 0008: Key Lifecycle for Receipt Verifiability (K1–K6, Forward Specification)
Status: Proposed — forward specification. K1–K6 have been listed in spec/receipt-v1.md §10 since 2026-06-24; this record states the decisions as the standard's own. The v1 verifier is unchanged. Date: 2026-10-17
Related: ADR 0005 (the standard is the source of truth), ADR 0007 (receipt envelope; D3 transparency-log proof, D4 error registry), spec/v0.1.md §2 (key_custody) and §3 (JWKS), spec/transparency-log-v0.1.md, docs/security/KEY_ROTATION.md.
Context
A receipt is meant to remain verifiable long after it is issued — across routine key rotation — and a compromised key must not make forged receipts look authentic. A node may sign several layers (offer, transport, payment) with one key, so one compromise reaches all of them. The v1 receipt verifier checks signature and freshness only: it matches the JWS kid against the JWKS fetched at verification time, with no notion of retired or revoked keys.
The decisions for that lifecycle were recorded in the reference implementation's repository and cited here twice as "ADR 0011". Following ADR 0005, this record states them in the standard's own terms.
Decision
These rules are forward specification: a lifecycle-aware verifier implements them; the v1 verifier does not change.
- K1 — Every signature is key-identified. Each attestation signature carries a JWS
kid, and a receipt records the verifyingkidper attestation. Akididentifies one key; reusing it for another key would make historical receipts ambiguous. - K2 — The JWKS keeps retired public keys. After a key stops signing, the host domain's JWKS keeps serving its public half for the receipt-retention horizon (the longest period a receipt must remain independently verifiable). Each key entry carries
vrp_key_status(active,retiredorrevoked) andvrp_not_before/vrp_not_after, the window in which it was a legitimate signer. Historical verification resolves thekidagainst this retained set and does not treat "no longer active" as a failure for a signature made inside the window. - K3 — Rotation is additive and overlapping. A new key is published as
activeand begins signing under a newkid; the previous key becomesretired. Both stay resolvable during an overlap window. Rotation alone never invalidates a receipt. - K4 — Revocation is distinct from rotation and is time-anchored.
revokedmeans the private key is believed compromised, and the revocation publishesvrp_compromised_at. A receipt proven to predate that instant can still be treated as authentic; one that cannot be proven to predate it fails closed and is invalid for that layer. The proof needs an independent time anchor — the transparency-log inclusion proof (ADR 0007 D3, transparency-log-v0.1) — never the times asserted inside the possibly forged signature. A receipt intended to survive a future revocation, for example one kept as dispute or insurance evidence, therefore MUST carry atlogproof. - K5 — Per-layer keys are permitted. A node MAY sign one layer (for example
payment) with a different key orkidthan another. Each attestation resolves its own key through itssourceandkid, so nothing in the envelope presumes one key per receipt. - K6 — Lifecycle error codes. A lifecycle-aware verifier adds
key_retired_out_of_window,key_revokedandtlog_requiredto the ADR 0007 D4 registry. The v1 codes are unchanged.
K1–K6 apply to a node's key whoever holds it. Where key_custody is platform (v0.1 §2), the operator holding the key performs rotation and revocation, and the same metadata is published in the host domain's JWKS; a verifier applies the same rules either way.
Consequences
- A receipt can outlive routine rotation (K2, K3), and a leaked key cannot silently validate forgeries (K4) or, with separate keys, reach other layers (K5).
- The transparency-log proof gains a concrete role: it is what makes a receipt survive revocation.
- Until a lifecycle-aware verifier exists, public descriptions of VRP receipts do not claim long-term or post-revocation verifiability (
spec/receipt-v1.md§10). - Nodes that keep receipts as evidence take on JWKS retention, lifecycle metadata and
tloganchoring.
Not carried over from the implementation's record: its delivery phases, its acceptance checklist, its internal code paths and its own retention commitments. This ADR adds no runtime behavior and no new tools.