Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Preflight

Preflight is how Pretorin verifies that the host is connected to the sources a framework needs before evidence work begins. The platform recommends canonical source kinds per framework, but it cannot verify whether any of them are reachable from where you are working — only the CLI host can. Preflight is that CLI-local verification layer, and its verdict is the single source of truth for source availability (it replaces the platform connection registry).

The model

A recommended source kind (e.g. code_repository, cloud_control_plane) maps to a collection of resolvers, not a single one. Each resolver is a concrete, host-local way to reach part of the evidence story:

Resolver typeVerifiesExample params
workspace_patha path (and optional marker) exists{path: /infra, marker: "*.tf"}
cli_toola CLI is present/authenticated{name: gh, probe: "gh auth status"}
commanda generic probe exits 0{probe: "curl -fsS https://host/health"}
manual / attestednothing — user-asserted{identity: "SOC2-2026-Q1"}
mcp / connected_api / pretorin_featurea declared probe, else unverified{probe: "..."}

Resolver type and params are open — custom types work, and an unknown type with a declared probe is simply run (the registry fails open). A resolver may also declare capabilities, matched against a recipe’s requires.sources[].capabilities so the executor requires only the resolver(s) a recipe touches.

Status vocabulary

Each resolver verifies to one of: connected (machine-verified), degraded (reachable but stale/partial), missing (probe ran, not reachable), attested (user-asserted, never silently “connected”), or unverified (no probe yet).

These roll up per kind:

  • ready — every bound resolver is up; the whole evidence story is reachable.
  • degraded — some up, some not; partial story.
  • missing — resolvers bound and verified, none reachable.
  • unverified — resolvers bound but not probed yet.
  • unmapped — a recommended kind with no resolvers bound.

Two grains of availability

  • Control grain — the per-kind rollup answers “is the whole evidence story present?”
  • Executor grainstart_recipe only requires the specific resolver(s) a recipe touches (kind + optional capability), so a degraded kind never blocks a recipe that doesn’t need the down resolver.

How availability is decided

The verdict drives every availability decision:

  • list_recipes / the capture plan hide recipes whose required kinds are verified missing; unmapped/unverified kinds fail open (shown as unknown — a soft “verify before capture”, never a hard “not connected”).
  • start_recipe refuses to open a context when a required kind is verified missing, unless you pass force=true.

Commands

pretorin preflight init              # bind sensible local defaults, verify by default
pretorin preflight show              # read the verdict for the active scope
pretorin preflight verify            # probe every bound resolver, refresh status
pretorin preflight bind <kind> --type <type> [--param k=v ...] \
                       [--probe "<cmd>"] [--capability <cap> ...] [--recommended] \
                       [--constraint "<usage note>"] [--scope k=v ...]

pretorin preflight init is the low-friction setup path for a fresh machine: it detects the current git root, common local tools (gh, az, aws, kubectl), and local docs/policy folders, then binds those resolvers without calling the platform. It skips existing mappings unless you pass --replace, and it verifies by default (--no-verify just writes the mappings).

--system / --framework default to the active context (pretorin context set). The agent-facing MCP tools are get_preflight, verify_preflight, and update_preflight.

--constraint records a human/agent-readable usage note on the binding. --scope k=v (repeatable) pins a structured usage scope — for example --scope subscription=sub-prod --scope region=westus2. Scope entries become recipe param defaults: when a recipe declares a param with the same name, start_recipe and pretorin recipe run fill it from the matching binding unless the caller passes an explicit value. The applied defaults are reported back as source_params. Scope never crosses cloud providers — a binding identifiable as Azure (e.g. the az CLI, or an explicit --scope provider=azure) will not feed defaults into an AWS-kind recipe.

The guided workflow

For an interactive, recommendation-aware setup, run the preflight workflow: it pulls the framework’s recommended source kinds, diffs them against what you have mapped, walks you through binding a resolver collection for each gap, verifies them, and reports ready / degraded / missing. The artifact persists locally per (system, framework) under ~/.pretorin/preflight/, so later evidence work reads the verdict directly — re-run pretorin preflight verify if it has gone stale. Task and Campaign preparation, along with CLI and MCP updates for the same scope, share one transaction. Concurrent preparation therefore cannot discard another workspace binding or an explicitly activated recipe.

Over MCP, enter this workflow through the normal routing boundary: start_task with entities.intent_verb="preflight", the active system_id and framework_id, and the user’s verbatim prompt. Then load the returned preflight workflow with get_workflow before calling its preflight and recipe-discovery tools.

Do not put literal credentials in resolver probes. Secret-shaped strings in resolver params and probe results are redacted before the local artifact is persisted, but probes should rely on the host’s normal auth stores whenever possible.