provisioning-code/.ncl-cache/b108450474ac0bf5e812f2d07876a72d67683f8eb7ebfa3a0416abfae2e6c661.json

136 lines
3.9 KiB
JSON

{
"adr_refs": [
"adr-037",
"adr-038"
],
"description": "Rotates ops-controller key, keeper key, or operator key. For ops-controller: generates new key, proposes delegation patch on state-<workspace> signed by quorum, activates new key, verifies continuity. Keeper and operator key rotation follow the same quorum-sign pattern.",
"emit_audit": true,
"id": "rotate_keys",
"name": "Key Rotation",
"params": [
{
"default_val": "",
"description": "Target workspace (e.g. libre-wuji)",
"name": "workspace",
"required": true
},
{
"default_val": "",
"description": "Which key to rotate: ops-controller | keeper | operator",
"name": "key_type",
"required": true
},
{
"default_val": "",
"description": "Path to the new Ed25519 private key PEM",
"name": "new_key_path",
"required": true
},
{
"default_val": "",
"description": "Path to the new Ed25519 public key PEM",
"name": "new_pubkey_path",
"required": true
},
{
"default_val": "",
"description": "ops-vm SSH host (required for keeper rotation)",
"name": "ops_vm_host",
"required": false
}
],
"preconditions": [
"Identify which key type to rotate: ops-controller | keeper | operator",
"Ensure quorum of existing signers is available to sign the delegation patch",
"For ops-controller rotation: audit mirror must be paused or confirmed resilient to a 30-60s gap",
"Generate the new key offline before running this playbook"
],
"rollback_strategy": "manual",
"steps": [
{
"depends_on": [],
"dry_run_arg": "--dry-run",
"id": "validate_new_key",
"name": "Validate new key is a valid Ed25519 keypair",
"on_error": "Stop",
"params": {},
"script": "steps/validate_new_key.nu"
},
{
"depends_on": [
"validate_new_key"
],
"dry_run_arg": "--dry-run",
"id": "propose_delegation_patch",
"name": "Propose delegation patch on state-<workspace> repo",
"on_error": "Stop",
"params": {},
"script": "steps/propose_delegation_patch.nu"
},
{
"depends_on": [
"propose_delegation_patch"
],
"dry_run_arg": "--dry-run",
"id": "sign_delegation_patch",
"name": "Await quorum signatures on delegation patch",
"on_error": "Stop",
"params": {},
"script": "steps/sign_delegation_patch.nu"
},
{
"depends_on": [
"sign_delegation_patch"
],
"dry_run_arg": "--dry-run",
"id": "activate_new_key",
"name": "Activate new key (deploy to target service)",
"on_error": "Rollback",
"params": {},
"script": "steps/activate_new_key.nu"
},
{
"depends_on": [
"activate_new_key"
],
"dry_run_arg": "--dry-run",
"id": "verify_continuity",
"name": "Verify audit/signing continuity with new key",
"on_error": "Continue",
"params": {},
"script": "steps/verify_continuity.nu"
},
{
"depends_on": [
"verify_continuity"
],
"dry_run_arg": "--dry-run",
"id": "revoke_old_key",
"name": "Revoke old key from delegation set",
"on_error": "Continue",
"params": {},
"script": "steps/revoke_old_key.nu"
},
{
"depends_on": [
"revoke_old_key"
],
"dry_run_arg": "--dry-run",
"id": "emit_audit",
"name": "Emit key-rotation audit event",
"on_error": "Continue",
"params": {
"event_type": "key_rotation"
},
"script": "steps/emit_audit.nu"
}
],
"success_criteria": [
"New key is active and accepted by the target service",
"Delegation patch is merged in state-<workspace> Radicle repo",
"Old key is removed from delegation set",
"ops history shows key-rotation audit event",
"No interruption in audit trail during rotation"
],
"version": 1
}