One key forever is not a plan
The simplest design is a single key pair. The server signs with the private half; everyone verifies with the public half. It works until the first rotation, and rotation is not optional. Keys leak, people leave, and some keys should simply have a shelf life. Parmana has its own reason to care. A default signing key used before 2026-07-05 was publicly exposed. It was rotated that day, and it must still be treated as permanently compromised, whichever repository exposed it. That is written at the top of the claims register, and it is why rotation had to work without breaking everything else.The idea: every signature names its key
Put a key id on every signature. A verifier then does not ask “does this verify against our key?” but “does this verify against the key it names, and is that key acceptable right now?” That splits the problem in two. Old records keep verifying, because they name the old key and the old public key is kept. New signing moves to a new key id. And a separate list says which key ids have expired or been revoked, so the old key can be refused for anything that must be current.How Parmana does it
Execution authorizations. The signed authorization that lets the gateway release an action carries its own key id. The gateway resolves the public key by that id, through the same signer that made the signature, whether the key lives in a local file or in AWS KMS. Signing and verification have to use the same source for a key, or a key that signs can fail to verify. The design resolves both through one signer, so that mismatch cannot be configured. Expiry and revocation. Before reading any key material, the gateway can check the key id against a small list kept beside the keys. An entry can say the key is revoked, or give a time after which it expires. A revoked key, an expired key, or a key that cannot be found makes key resolution fail, and the authorization fails verification. There is no quiet fallback to some other key. A key id with no entry is treated as always valid, so a deployment that never writes the list behaves exactly as before. A list that is malformed is an error, not “no expiry”. This is claim 2.28. Durable records. Trust Records, Refusal Records and audit events used to be signed under a fixed key id, so they could not be rotated without breaking every earlier signature. Now the key id for new signatures is a setting, a script creates a new key under a fresh id, and verification always uses the id stored on the record. The rule in the production runbook is blunt: never delete the old key files, because old records name them. Public keys by id. Anyone can fetch a public key by its id, or the list of keys the server publishes, without an API key. The offline verifiers take a map from key id to public key, so an auditor checks each record against the key it names. Other keys follow the same pattern. A transaction for a tenant can be signed with that tenant’s own key, and a caller may only name tenants its API key allows. Keys trusted to sign human approvals are added and revoked through maker checker, with no deploy, and the gateway re-checks that the approver’s key is still trusted just before release.What it does not do
- Expiry and revocation are checked for execution authorizations only. The list is consulted at the gateway. The offline verifiers for Trust Records and other durable records check a signature against the key it names; they do not consult a revocation list. A record signed by a key that was later compromised still verifies mathematically. Knowing the key is compromised, as with the 2026 notice, is up to the reader.
- A revoked key’s past signatures are not undone. Revocation stops a key being accepted from now on. It cannot tell you which of its earlier signatures were made by the rightful holder.
- Rotation is manual. It is a script an operator runs, not a schedule. Rotation under AWS KMS is not covered by a live test.
- Per tenant keys have soft edges. A tenant with no key provisioned falls back to the shared default key (
default) rather than failing. Under KMS, the mapping of tenant key ids to KMS names is unit tested only, not run against real AWS. - It is one algorithm at a time. Rotation means a new key under the same algorithm. Switching a live deployment from Ed25519 to ML-DSA-65 while old records stay verifiable is not built.