Keyring

Rotate and revoke

Rotation mints a successor with an overlap window. Revocation is idempotent and can wait for your fleet to confirm.

Rotate with overlap

Rotate on a key's page, or POST /v1/keys/:id/rotate, mints a new key and gives the old one an overlap window during which both work. The default is 24 hours, the maximum 7 days, and the window only ever shortens an existing expiry; rotating a key that expires in an hour does not buy it a day.

curl -X POST "https://keyring-api.belghalem.fr/v1/keys/$KEY_ID/rotate" \
  -H "Authorization: Bearer $KEYRING_SECRET_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"overlap_hours": 48}'

The response carries the new key once, and the previous key's record with its new expiry. Idempotency records are scoped per tenant rather than per key, so a retry that lands on the new key during the overlap still finds what the old key wrote.

Revoke

Revoke on the key's page, or POST /v1/keys/:id/revoke, with an optional reason. It is idempotent on purpose: revocation is what you reach for during an incident, and a second call must not fail.

Propagation is the SDK's ordinary poll. Every node fetches the project's delta at most 5 seconds after the revoke, and a revoked key is refused from that node's next request. Measured on a rehearsal stack over five trials, revoke-to-401 landed between 4.4 and 4.9 seconds; read it as a bound of one poll interval, not a fixed number.

Revoke and wait

curl -X POST "https://keyring-api.belghalem.fr/v1/keys/$KEY_ID/revoke?wait=true" \
  -H "Authorization: Bearer $KEYRING_SECRET_KEY"

With wait=true the control plane holds the response until every node that has polled this project acknowledges the revoking policy version on its own next poll, bounded by KEYRING_REVOKE_WAIT_TIMEOUT_MS, 10 seconds by default. The body's propagation field is the receipt:

{
  "propagation": {
    "complete": true,
    "waited_ms": 7555,
    "acked_nodes": 3,
    "total_nodes": 3
  }
}

Check propagation.complete rather than the status alone: a fleet with a node whose poll is slow can return complete: false at the timeout. The difference between the two calls is the difference between "we told your fleet" and "your fleet told us", and it is the question every security reviewer asks.

What a node that is not polling does

A node whose poller is down keeps its cached policy and keeps admitting the key until it polls again; that is the stale-then-open trade stated plainly. wait=true only counts nodes that have polled, which is exactly why its receipt is worth more than the promise.

On this page