Appearance
Rotate the signing key
Signing-key rotation opens an overlap window during which both the retiring and the incoming key verify, then retires the old key. Rotation is driven through the plexctl signing rotate and plexctl signing close subcommands implemented in ../../../cmd/plexctl/commands/signing.go, which delegate to the signer's OpenRotation and CloseRotation gRPC RPCs per Domain scope.
Prerequisites
- Operator access to the signer deployment.
- The target scope (
platformordomain:<uuid>) and the new key ID. - Access to a
plexctlbinary configured to reach the signer (--signer-endpointor thePLEXSPHERE_SIGNER_ENDPOINTenv var).
Steps
Open the rotation
shell
plexctl signing rotate --scope domain:<uuid> --new-key-id <key-id>
# SCOPE OLD_KEY_ID NEW_KEY_ID OPENED_AT CLOSES_AT
# domain:… domain-2026-04 domain-2026-05 2026-05-01T12:00:00Z 2026-05-01T13:00:00ZThe command invokes the OpenRotation RPC and prints the resulting transition. The signer now advertises both public keys, and CLOSES_AT = OPENED_AT + overlap_window (configured at signer bring-up through --overlap-window).
rotate exits 0 on success, 1 when a rotation is already open for the scope, and 2 when a flag value is rejected (malformed scope or key ID, or a scope the deployment profile refuses). The full gRPC-status to exit-code table is in the plexctl signing reference.
Sign through the new key
During the overlap every fresh Sign resolves to the new key while existing signatures still verify against the old one. The overlap window is persisted, so restarting the signer mid-overlap resumes the open rotation without re-emitting the rotation event.
Close the rotation
shell
plexctl signing close --scope domain:<uuid> --old <old-key-id> --new <new-key-id>
# SCOPE OLD_KEY_ID NEW_KEY_ID
# domain:… domain-2026-04 domain-2026-05The command invokes the CloseRotation RPC after the overlap. The old key is retired and no longer advertised. Rotation is per-Domain independent — one scope's rotation never touches another's. Exit codes follow the same table as rotate.
Verification
The rotate and close commands print the transition they applied, so the immediate success signal is in-band: a rotate whose CLOSES_AT sits in the future opened the overlap window, and a close that echoes the (SCOPE, OLD_KEY_ID, NEW_KEY_ID) tuple retired the old key.
Confirm the durable effects:
- The JWKS no longer lists the retired key ID, and signatures minted during the overlap still verify against the new active key.
- A successful
rotateemits asigning_key_rotatedevent on the signed event bus — one outbox row per Node in the scope. See the event-taxonomy row in../../contexts/mesh/sse.mdfor the payload shape and Inspect the signed event bus for how to tail it.
See also
../../contexts/signing-rotation.md— explanation of the end-to-end rotation workflow and the fan-out contract.../../contexts/signing/deployment.md— deployment-scoping matrix, the three-state rotation lifecycle, and the--overlap-windowflag.