2026-09-29 10:49:10 +02:00
{
"$schema" : "https://json-schema.org/draft/2020-12/schema" ,
"$id" : "https://runbook-tutorials.invalid/schema/runbook-pack/v0.2" ,
"title" : "Runbook pack manifest v0.2" ,
"type" : "object" ,
"required" : [
"spec" ,
"id" ,
"title" ,
"owner" ,
"exercise_status" ,
"engine"
] ,
"additionalProperties" : false ,
"properties" : {
"spec" : {
"const" : "runbook-pack/v0.2"
} ,
"id" : {
"type" : "string" ,
"pattern" : "^[a-z0-9]+([.-][a-z0-9]+)*$"
} ,
"title" : {
"type" : "string" ,
"minLength" : 3
} ,
"owner" : {
"type" : "string" ,
"minLength" : 1
} ,
"outcome" : {
"type" : "string"
} ,
"exercise_status" : {
"type" : "string" ,
"pattern" : "^(unexercised|exercised [0-9]{4}-[0-9]{2}-[0-9]{2} by \\S+)$"
} ,
"engine" : {
"enum" : [
"native" ,
"legacy-command"
]
} ,
"confirm_phrase" : {
"type" : "string" ,
"minLength" : 8 ,
"description" : "Typed by the operator to confirm an irreversible step."
} ,
"timeout" : {
"$ref" : "#/$defs/timeout" ,
2026-09-29 12:19:58 +02:00
"description" : "Default for auto-confirm runs."
2026-09-29 10:49:10 +02:00
} ,
"legacy" : {
"type" : "object" ,
"required" : [
"command"
] ,
"additionalProperties" : false ,
"properties" : {
"command" : {
"type" : "array" ,
"items" : {
"type" : "string"
} ,
"minItems" : 1
} ,
"cwd" : {
"type" : "string"
} ,
"url" : {
"type" : "string"
} ,
"note" : {
"type" : "string"
}
}
} ,
"framing" : {
"type" : "array" ,
"items" : {
"type" : "string"
} ,
"description" : "Things to keep in mind; shown first; not gates."
} ,
"actors" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/actor"
}
} ,
"datapoints" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/datapoint"
}
} ,
"stages" : {
"type" : "array" ,
"minItems" : 1 ,
"items" : {
"$ref" : "#/$defs/stage"
}
} ,
"artefacts" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/artefact"
}
} ,
"ownership" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/ownership"
}
}
} ,
"allOf" : [
{
"if" : {
"properties" : {
"engine" : {
"const" : "native"
}
}
} ,
"then" : {
"required" : [
"stages" ,
"framing"
]
}
} ,
{
"if" : {
"properties" : {
"engine" : {
"const" : "legacy-command"
}
}
} ,
"then" : {
"required" : [
"legacy"
]
}
}
] ,
"$defs" : {
"id" : {
"type" : "string" ,
"pattern" : "^[a-z][a-z0-9-]*$"
} ,
"dpid" : {
"type" : "string" ,
"pattern" : "^[a-z][a-z0-9_]*$"
} ,
"timeout" : {
"type" : "object" ,
"required" : [
"seconds"
] ,
"additionalProperties" : false ,
"properties" : {
"seconds" : {
"type" : "integer" ,
"minimum" : 1
} ,
"on_timeout" : {
"enum" : [
"stop" ,
"push-through"
] ,
"default" : "stop"
}
}
} ,
"actor" : {
"type" : "object" ,
"required" : [
"id" ,
"role" ,
"description"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"role" : {
"type" : "string"
} ,
"description" : {
"type" : "string"
} ,
"privileges" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
}
}
} ,
"datapoint" : {
"type" : "object" ,
"required" : [
"id" ,
"label" ,
"type"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/dpid"
} ,
"label" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"string" ,
"text" ,
"enum" ,
"path" ,
"bool" ,
"int"
]
} ,
"values" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"default" : {
"type" : [
"string" ,
"integer" ,
"boolean"
]
} ,
"pattern" : {
"type" : "string"
} ,
"help" : {
"type" : "string"
} ,
"dimensions" : {
"type" : "object" ,
"additionalProperties" : {
"type" : "string"
}
} ,
"ask_in" : {
"$ref" : "#/$defs/id"
} ,
"produced_by" : {
"$ref" : "#/$defs/id"
} ,
"confirmed_by" : {
"$ref" : "#/$defs/id"
} ,
"secret" : {
"const" : false
}
}
} ,
"check" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"done_when" : {
"type" : "string" ,
"minLength" : 3
} ,
"command" : {
"type" : "string"
} ,
"expect" : {
"enum" : [
"manual" ,
"exit-0" ,
"output-contains"
]
} ,
"contains" : {
"type" : "string"
} ,
"datapoints_ok" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/dpid"
} ,
"minItems" : 1
}
} ,
"anyOf" : [
{
"required" : [
"done_when"
]
} ,
{
"required" : [
"datapoints_ok"
]
}
]
} ,
"alternative" : {
"type" : "object" ,
"required" : [
"id" ,
"title" ,
"verify"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"title" : {
"type" : "string"
} ,
"command" : {
"type" : "string"
} ,
"reversible" : {
"type" : "boolean"
} ,
"rollback" : {
"type" : "string"
} ,
"verify" : {
"$ref" : "#/$defs/check"
} ,
"recommended_when" : {
"type" : "object" ,
"additionalProperties" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
}
2026-09-29 12:19:58 +02:00
} ,
"idempotent" : {
"enum" : [
"idempotent" ,
"non-idempotent" ,
"conditional"
]
} ,
"idempotent_note" : {
"type" : "string"
2026-09-29 10:49:10 +02:00
}
}
} ,
"step" : {
"type" : "object" ,
"required" : [
"id" ,
"title" ,
"actor" ,
"owner"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"title" : {
"type" : "string"
} ,
"actor" : {
"$ref" : "#/$defs/id"
} ,
"owner" : {
"type" : "string"
} ,
"description" : {
"type" : "string"
} ,
"command" : {
"type" : "string"
} ,
"reversible" : {
"type" : "boolean" ,
"default" : true
} ,
"rollback" : {
"type" : "string"
} ,
"confirm_phrase" : {
"type" : "string" ,
"minLength" : 8
} ,
"verify" : {
"$ref" : "#/$defs/check"
} ,
"requires" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"uses" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/dpid"
}
} ,
"produces" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"evidence" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"one_of" : {
"type" : "array" ,
"minItems" : 2 ,
"items" : {
"$ref" : "#/$defs/alternative"
}
} ,
2026-09-29 12:19:58 +02:00
"timeout" : {
"$ref" : "#/$defs/timeout"
} ,
"downstream_risk" : {
"type" : "string"
} ,
"auto_confirm" : {
2026-09-29 10:49:10 +02:00
"enum" : [
"allowed" ,
"manual-only"
] ,
"default" : "allowed"
} ,
2026-09-29 12:19:58 +02:00
"idempotent" : {
"enum" : [
"idempotent" ,
"non-idempotent" ,
"conditional"
] ,
"description" : "Is re-running this step after a partial or complete earlier attempt safe? Omit if unknown. Values are words, never yes/no: YAML reads unquoted yes/no as booleans."
2026-09-29 10:49:10 +02:00
} ,
2026-09-29 12:19:58 +02:00
"idempotent_note" : {
"type" : "string" ,
"description" : "Required when idempotent is conditional: under what condition."
2026-09-29 10:49:10 +02:00
}
} ,
"anyOf" : [
{
"required" : [
"verify"
]
} ,
{
"required" : [
"one_of"
]
}
]
} ,
"gate" : {
"type" : "object" ,
"required" : [
"id" ,
"title" ,
"goal" ,
"checks"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"title" : {
"type" : "string"
} ,
"goal" : {
"type" : "string" ,
"minLength" : 3
} ,
"blocking" : {
"type" : "boolean" ,
"default" : true
} ,
"checks" : {
"type" : "array" ,
"minItems" : 1 ,
"items" : {
"$ref" : "#/$defs/check"
}
} ,
"waivable" : {
"type" : "object" ,
"required" : [
"by" ,
"needs_reason"
] ,
"additionalProperties" : false ,
"properties" : {
"by" : {
"$ref" : "#/$defs/id"
} ,
"needs_reason" : {
"const" : true
}
}
} ,
"timeout" : {
"$ref" : "#/$defs/timeout"
} ,
"downstream_risk" : {
"type" : "string"
}
}
} ,
"stage" : {
"type" : "object" ,
"required" : [
"id" ,
"title" ,
"goal"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"title" : {
"type" : "string"
} ,
"goal" : {
"type" : "string" ,
"minLength" : 3
} ,
"framing" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"requires" : {
"type" : "array" ,
"items" : {
"type" : "string"
}
} ,
"steps" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/step"
}
} ,
"gates" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/gate"
}
} ,
"stages" : {
"type" : "array" ,
"items" : {
"$ref" : "#/$defs/stage"
}
}
} ,
"anyOf" : [
{
"required" : [
"steps"
]
} ,
{
"required" : [
"stages"
]
}
]
} ,
"artefact" : {
"type" : "object" ,
"required" : [
"id" ,
"title" ,
"location" ,
"produced_by"
] ,
"additionalProperties" : false ,
"properties" : {
"id" : {
"$ref" : "#/$defs/id"
} ,
"title" : {
"type" : "string"
} ,
"location" : {
"type" : "object" ,
"required" : [
"datapoint"
] ,
"additionalProperties" : false ,
"properties" : {
"datapoint" : {
"$ref" : "#/$defs/dpid"
} ,
"path" : {
"type" : "string"
}
}
} ,
"produced_by" : {
"$ref" : "#/$defs/id"
} ,
"lives_until" : {
"$ref" : "#/$defs/id"
}
}
} ,
"ownership" : {
"type" : "object" ,
"required" : [
"concern" ,
"owner"
] ,
"additionalProperties" : false ,
"properties" : {
"concern" : {
"type" : "string"
} ,
"owner" : {
"type" : "string"
}
}
}
}
}