Signing
Key rotation
Every Permit names the key that signed it. Rotation is a phased overlap with no downtime and no weakening: publish the new key in the JWKS before it signs anything; switch signing so new Permits carry the new key while Permits signed by the old key stay valid until they expire; retire the old key from the JWKS only after every Permit it could have signed has expired. Retiring a key never revives anything — revoked, expired and consumed Permits stay refused, because status is authoritative — and retiring it too early cannot make a Permit usable either: such a Permit is refused at consume with nothing spent, and the next delivery re-issues it under the new key.Single use and replay
Consumption is an atomic transition of the Permit row fromissued to consumed, with the attempt id recorded, in the same transaction that moves the change to applying. Unique indexes allow one live and one consumed Permit per change and one consumption per attempt. A second attempt is refused as a replay; the same attempt re-delivering its claim is idempotent; concurrent consumes yield exactly one winner. Executors additionally keep a local replay cache.
Binding and tamper resistance
The Permit’s claims bind the tenant, the environment (including the EKS cluster, account, region, endpoint and certificate authority), the target workload, the exact action and its hash, the executor location and identity, the authority (approver or policy id and version) and the judgment result. The canonical action form refuses duplicate keys (including keys that differ only by escapes) and invalid UTF-8; verifiers refuse any header or claim set with a duplicated member, so a Permit has one meaning for every implementation. At consume the Executor must present the SHA-256 of the exact token it verified: a token with a valid ChangeGuard signature but different bytes is refused.Revocation
Immediate, up to the commit point. A revocation, a withdrawn approval, a material proposal change, a policy edit or an execution-path change that lands before consume makes the consume fail. Revocation and consume race on the same row lock; exactly one wins. Reasons are a closed set, signed into history:human_revocation, policy_changed, environment_retired, target_identity_changed, proposal_changed, approval_withdrawn, security_event, execution_disabled. An admin can revoke every live Permit as a security event.
Immutability
A database trigger forbids changing any signed field. Status only moves out ofissued. The outcome is written once. Permit events are append-only (the application role can insert and select, never update or delete).