81 lines
3.3 KiB
Text
81 lines
3.3 KiB
Text
|
|
let pb = import "schemas/lib/playbook.ncl" in
|
||
|
|
|
||
|
|
pb.make_playbook {
|
||
|
|
id = "onboard_operator",
|
||
|
|
name = "Onboard Operator",
|
||
|
|
description = "Generates Radicle identity, issues NATS JWT credential with scopes, proposes delegation patch on policy-<workspace> repo signed by existing quorum. After completion the new operator can sign ops commands and participate in quorum.",
|
||
|
|
version = 1,
|
||
|
|
|
||
|
|
preconditions = [
|
||
|
|
"New operator has generated their Radicle identity (rad auth)",
|
||
|
|
"New operator's Ed25519 public key is available",
|
||
|
|
"Existing quorum of current operators is available to sign the delegation patch",
|
||
|
|
"Agreed scope for new operator (which op_type patterns they may sign)",
|
||
|
|
],
|
||
|
|
|
||
|
|
params = [
|
||
|
|
{ name = "workspace", description = "Target workspace", required = true, default_val = "" },
|
||
|
|
{ name = "operator_name", description = "Human-readable name for the new operator", required = true, default_val = "" },
|
||
|
|
{ name = "operator_pubkey", description = "Path to operator Ed25519 public key PEM", required = true, default_val = "" },
|
||
|
|
{ name = "operator_did", description = "Radicle DID of the new operator", required = true, default_val = "" },
|
||
|
|
{ name = "allowed_op_types", description = "Comma-separated op_type patterns (e.g. deploy,rollback)", required = true, default_val = "" },
|
||
|
|
{ name = "nats_account_url", description = "NATS account server URL for JWT issuance", required = false, default_val = "" },
|
||
|
|
],
|
||
|
|
|
||
|
|
steps = [
|
||
|
|
{
|
||
|
|
id = "issue_nats_credential",
|
||
|
|
name = "Issue NATS JWT with scoped publish permissions",
|
||
|
|
script = "steps/issue_nats_credential.nu",
|
||
|
|
dry_run_arg = "--dry-run",
|
||
|
|
on_error = 'Stop,
|
||
|
|
depends_on = [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id = "propose_policy_patch",
|
||
|
|
name = "Propose delegation addition on policy-<workspace> repo",
|
||
|
|
script = "steps/propose_policy_patch.nu",
|
||
|
|
dry_run_arg = "--dry-run",
|
||
|
|
on_error = 'Stop,
|
||
|
|
depends_on = ["issue_nats_credential"],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id = "sign_policy_patch",
|
||
|
|
name = "Await quorum signatures on delegation patch",
|
||
|
|
script = "steps/sign_policy_patch.nu",
|
||
|
|
dry_run_arg = "--dry-run",
|
||
|
|
on_error = 'Stop,
|
||
|
|
depends_on = ["propose_policy_patch"],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id = "verify_operator_can_sign",
|
||
|
|
name = "Verify new operator credential can sign a test op",
|
||
|
|
script = "steps/verify_operator_sign.nu",
|
||
|
|
dry_run_arg = "--dry-run",
|
||
|
|
on_error = 'Continue,
|
||
|
|
depends_on = ["sign_policy_patch"],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id = "emit_audit",
|
||
|
|
name = "Emit operator-onboard audit event",
|
||
|
|
script = "steps/emit_audit.nu",
|
||
|
|
params = { event_type = "operator_onboard" },
|
||
|
|
dry_run_arg = "--dry-run",
|
||
|
|
on_error = 'Continue,
|
||
|
|
depends_on = ["sign_policy_patch"],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
rollback_strategy = 'manual,
|
||
|
|
|
||
|
|
success_criteria = [
|
||
|
|
"New operator NATS JWT credential file generated and encrypted with SOPS",
|
||
|
|
"Delegation patch merged in policy-<workspace> Radicle repo",
|
||
|
|
"New operator can sign a test op with keeper-cli",
|
||
|
|
"ops history shows operator-onboard audit event",
|
||
|
|
],
|
||
|
|
|
||
|
|
emit_audit = true,
|
||
|
|
adr_refs = ["adr-037", "adr-038"],
|
||
|
|
}
|