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>The command invokes the OpenRotation RPC and prints the resulting RotationTransition — the (old_key_id, new_key_id, opened_at, closes_at) tuple. The signer now advertises both public keys; closes_at = opened_at + overlap_window (configured at signer bring-up through --overlap-window).
Exit codes follow the shared exitCodeFor catalogue in ../../../cmd/plexctl/app.go:
0on success.1when the signer returnsFailedPrecondition— most commonly the stable detail stringsigning: rotation in progress, meaning a rotation is already open for this scope.2when the signer returnsInvalidArgument— the stable detail stringsigning: invariant violation, meaning the request violates a domain invariant (malformed scope, malformed key ID, or a scope the deployment profile refuses).
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. Optionally restart the signer mid-overlap to prove the window is persisted — RotationService.Resume reconciles the open transition row at boot without republishing the signing_key_rotated event.
Close the rotation
shell
plexctl signing close --scope domain:<uuid> --old <old-key-id> --new <new-key-id>The 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 exitCodeFor mapping as rotate above.
Verification
- Confirm the JWKS no longer lists the retired key ID and that 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 wire-level payload shape.
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.