Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
9.9 KiB
Runbook pack specification v0.2
Status: adopted 2026-09-29 (Bernd's review answers are in the Decisions section).
Derived from docs/ux-review-2026-09-29.md. v0.1 stays valid; v0.2 is a superset.
Machine-checkable form: schema/runbook-pack-v0.2.schema.json plus the semantic
checks in rtut/v2.py. The engine and UI do not run v0.2 packs yet (RBT-WP-0007).
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
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 datapoint becomes ok when the step or gate named in its confirmed_by passes. A gate must not
require a datapoint (datapoints_ok) that it is itself confirmed_by: that is circular and the validator
rejects it.
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
stagesnest to at most three levels. A stage hastitle,goal,steps, and optional childstages.- Every step and stage may declare
requires:(ids of steps, stages, gates, or datapoints in stateok). 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
requiresbehaves as a linear sequence, which is exactly a v0.1 pack.
Gates
A gate is a QA condition, not a step.
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
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
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(defaultI 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.1andv0.2. A v0.1 pack is interpreted as one stage, a linearrequireschain, no gates, no actors, its parameters as datapoints. engine: legacy-commandis unchanged.- The run record gains
datapoints,gatesandwaiverssections (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.
Operating modes, overrides and deviations
A run has a mode. The mode belongs to the run, not to the pack.
| Mode | Who confirms | Checks, gates, preconditions |
|---|---|---|
| manual | the operator | shown with their state; the operator confirms each |
| auto-confirm | the engine, when every precondition is met | evaluated by the engine; confirmation is applied automatically |
Manual mode: override
If preconditions are not met the operator may override and continue anyway.
Doing so must (1) show a dialog that names the unmet preconditions and the
downstream risk (downstream_risk text declared on the step or gate, else a
generic warning), (2) require an explicit confirmation, and (3) record a
deviation in the run.
Auto-confirm mode: timeout and push-through
- A step or gate may declare
timeout: {seconds: N, on_timeout: stop|push-through}; a run may set a default. Without a timeout, auto-confirm waits. stop(default): on timeout the run stops and reports.push-through: on timeout the engine confirms the item, records a deviation, and moves on, ignoring the problem. This gathers the most information about problems in one run and reduces refinement runs.- Irreversible steps are never confirmed automatically unless the run was started
with an explicit, recorded pre-authorization naming those steps (and the pack's
confirm_phrase). Push-through does not bypass that rule. This is a safety default, open to review. - A step may declare
auto_confirm: manual-onlyto forbid automation entirely. - Auto-confirm applies confirmation only. It does not run a step's own command; execution is a later, separate level (RBT-WP-0006).
Deviations
An item passed over by push-through gets the distinct state pushed (steps, gates and datapoints): not done, not set, not an error.
Every override, waiver, push-through and change of a value that steps already used (changed-after-use) is a deviation in the run record:
kind (override|waiver|push-through), item (step or gate id), mode,
unmet (what was not satisfied), risk_acknowledged, reason (required for
overrides and waivers; automatic text for push-through), who, at. A run with
deviations is marked so in the overview and never counts towards maturity. A waiver is
declared in advance (waivable on a gate); an override is not.
Decisions (2026-09-29, Bernd)
- Waivers: allowed only where a gate declares
waivable, always with a reason. Undeclared departures are overrides (above), also recorded. - Gate checks: a gate may run a command (operator-confirmed in manual mode) or read datapoint states and step results.
- Dimension vocabulary: free tags first; a shared registry may be promoted to canon.
- Nesting: at most three levels. If procedures grow beyond that, dependencies between runbooks are needed (see below), not deeper nesting.
- Datapoint
ok: reached by a check, or by a recorded manual confirmation. Handling of missing preconditions is defined by the operating modes above.
Later: dependencies between runbooks
Idempotency is a declared characteristic of a step: idempotent: idempotent | non-idempotent | conditional
(conditional needs an idempotent_note). Undeclared means unknown. The runbook's overall value is derived.
See docs/maturity-and-projects.md.
Not in v0.2. When a procedure needs another runbook (for example "OpenBao operating
path requires the SSH access pack"), packs will declare requires_packs with a
required result (a maturity level, or a named gate passed). Tracked in RBT-WP-0006.
Recommendation (carried out)
Keep runbook-pack/v0.1 as shipped (three NetKingdom packs use it). Use the old
console's seven runbooks and 14 gates as the first real v0.2 test.