# Runbook pack specification v0.2 - proposal Status: **proposed** (review with Bernd; RBT-WP-0002-T04). Derived from `docs/ux-review-2026-09-29.md`. v0.1 stays valid; v0.2 is a superset. ## Principle The spec describes *what the procedure is*: structure, data, actors, gates and order. It carries no presentation. Rendering (layout, theme, dark mode, the questionnaire and the dimension view) is the renderer's job and must follow from the semantics alone. If a UI feature needs a new spec field, that field has to be justified as meaning, not appearance. ## The model ```text pack |- framing what to keep in mind (shown first) |- actors who does or approves what, with privileges |- datapoints the non-secret facts collected and applied -> state nil/set/err/ok |- stages hierarchy of the procedure | |- steps the work -> state todo/running/done/failed | |- gates QA checks tied to the stage and to goals -> state open/passed/failed/waived |- artefacts what a run produces and where it lives (non-secret references) ``` ### Two states, two things | Thing | States | Meaning | | --- | --- | --- | | **Datapoint** (parameter, role assignment, artefact location, custody reference) | `nil` no value, `set` value given, `err` invalid or rejected, `ok` confirmed in the real system | Is the data known and right? | | **Step** | `todo`, `running`, `done`, `failed` (`skipped` for read-only) | Has it been applied? | | **Gate** | `open`, `passed`, `failed`, `waived` | Is the quality condition met? | A v0.1 `parameter` is a datapoint that has a value type and is asked as a question. Steps `uses:` datapoints; steps may `produces:` datapoints (for example an artefact location). ### Hierarchy and order - `stages` nest to at most three levels. A stage has `title`, `goal`, `steps`, and optional child `stages`. - Every step and stage may declare `requires:` (ids of steps, stages, gates, or datapoints in state `ok`). This forms a dependency graph, so alternatives and parallel work are expressible. `one_of:` groups declare alternatives: any one satisfies the group. - **Canonical serialization.** The order in which the pack lists things is the recommended order. The engine computes: *ready* = every requirement met; *recommended next* = the first ready item in canonical order. Operators may take any other ready item. A pack that lists no `requires` behaves as a linear sequence, which is exactly a v0.1 pack. ### Gates A gate is a QA condition, not a step. ```yaml gates: - id: custody-approved title: Custody strategy approved stage: custody # exit gate of this stage goal: platform-root-custody # quality objective; canon standard id where one exists blocking: true # blocks dependents and the stage exit checks: # same check shape as step verify - {done_when: "signed roster verifies", command: "...", expect: exit-0} - {datapoints_ok: [custody_mode, roster_location]} waivable: {by: king, needs_reason: true} # omit if never waivable ``` - A gate is tied to exactly one stage (its exit or entry) and names the quality goal it protects, so gates are traceable to standards instead of floating. - `requires: [gate:custody-approved]` makes a step wait for a gate. - A waiver records who, when and why, and appears in the overview. ### Actors, roles and privileges ```yaml actors: - id: king role: Platform-root custodian description: Holds platform-root recovery authority. privileges: [approve-custody, revoke-root-token] ``` Steps and gates name an `actor` (who acts or approves). `owner` stays the repository or tool that does the work. The pack thereby explains what is relevant and who is responsible; the overview can group by actor. ### Datapoints and dimensions ```yaml datapoints: - id: custody_mode label: Custody mode type: enum values: [temporary-single-king, two-of-three-ready] dimensions: {actor: king, subsystem: openbao, kind: decision} ask_in: custody # stage in which the questionnaire asks for it ``` `dimensions` are free key/value tags, using canon vocabulary where it exists (actor, role, privilege, subsystem, kind, assurance goal). They drive the **dimension view**: a random-access table of all datapoints grouped or filtered by any dimension, editable independently of the flow. Secrets are never datapoints; only references ("stored in the platform-root safe entry") are. ### Artefacts `artefacts:` lists what a run yields, each with a `location` datapoint (a reference, never a value) and the `produced_by` step. The artefacts view is what makes a run more than a script. ### Confirmation Each step declares `reversible: true|false` (default `true`). - reversible: a confirm button; - not reversible: the operator types the pack's `confirm_phrase` (default `I understand this cannot be undone`; a step may set its own). This replaces v0.1's `risk` for the purpose of confirmation. v0.1 `risk` values map as: `destructive` gives `reversible: false`, all others `true`. ### Framing `threat_checks` becomes `framing:` (list of statements, optionally per stage): things to keep in mind, shown before the work starts. They are not gates. v0.1 `threat_checks` load as pack-level framing. ## Compatibility - The engine loads `runbook-pack/v0.1` and `v0.2`. A v0.1 pack is interpreted as one stage, a linear `requires` chain, no gates, no actors, its parameters as datapoints. - `engine: legacy-command` is unchanged. - The run record gains `datapoints`, `gates` and `waivers` sections (`runbook-run/v0.2`); v0.1 records still load. ## What this is not - No layout, color, icon or copy-text fields. - No embedded scripting, and no execution mode (still RBT-WP-0006). - No secret values anywhere. ## Recommendation Keep `runbook-pack/v0.1` as shipped (three NetKingdom packs use it). Adopt this proposal as v0.2 and port the four in-repo packs, then use the console's seven runbooks and 14 gates as the first real v0.2 test: if the model can express them without special cases, it is expressive enough. ## Open questions 1. **Waivers:** allowed at all, and by whom? Proposal: only where the pack declares `waivable`, always with a recorded reason. 2. **Gate checks against live systems:** may a gate run a command (as steps' verify do, operator-confirmed), or only read datapoint states and step results? Proposal: both, with the same confirmation rule. 3. **Dimension vocabulary:** free tags first, or start from a canon list? Proposal: free tags, with a `dimensions` registry file that packs may reference, promoted to canon later. 4. **Nesting depth:** three levels enough? 5. **Datapoint `ok`:** who confirms it, the operator or a check? Proposal: either; a check makes it `ok`, a manual confirmation is recorded as such.