let pb = import "schemas/lib/playbook.ncl" in pb.make_playbook { id = "offboard_operator", name = "Offboard Operator", description = "Revokes NATS JWT credential, proposes delegation removal patch on policy- repo signed by remaining quorum. After completion the operator cannot sign ops commands.", version = 1, preconditions = [ "Identify operator by name and Radicle DID", "Remaining quorum (after removal) still meets the threshold for the workspace", "Any pending ops signed by this operator should be reviewed before offboarding", ], params = [ { name = "workspace", description = "Target workspace", required = true, default_val = "" }, { name = "operator_name", description = "Name matching onboard record", required = true, default_val = "" }, { name = "operator_did", description = "Radicle DID of the operator to remove", required = true, default_val = "" }, { name = "reason", description = "Offboarding reason (recorded in audit)", required = false, default_val = "voluntary" }, ], steps = [ { id = "revoke_nats_credential", name = "Revoke operator NATS JWT credential", script = "steps/revoke_nats_credential.nu", dry_run_arg = "--dry-run", on_error = 'Stop, depends_on = [], }, { id = "propose_delegation_removal", name = "Propose delegation removal from policy- repo", script = "steps/propose_delegation_removal.nu", dry_run_arg = "--dry-run", on_error = 'Stop, depends_on = ["revoke_nats_credential"], }, { id = "sign_removal_patch", name = "Await remaining quorum signatures on removal patch", script = "steps/sign_removal_patch.nu", dry_run_arg = "--dry-run", on_error = 'Stop, depends_on = ["propose_delegation_removal"], }, { id = "verify_operator_cannot_sign", name = "Verify revoked operator credential is rejected", script = "steps/verify_operator_blocked.nu", dry_run_arg = "--dry-run", on_error = 'Continue, depends_on = ["sign_removal_patch"], }, { id = "emit_audit", name = "Emit operator-offboard audit event", script = "steps/emit_audit.nu", params = { event_type = "operator_offboard" }, dry_run_arg = "--dry-run", on_error = 'Continue, depends_on = ["sign_removal_patch"], }, ], rollback_strategy = 'manual, success_criteria = [ "Operator NATS JWT credential is revoked (NATS rejects connection attempts)", "Operator DID removed from policy- delegation set", "Test sign attempt with revoked credential returns 403", "ops history shows operator-offboard audit event", ], emit_audit = true, adr_refs = ["adr-037", "adr-038"], }