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.

A Pretorin Physical Security Policy is a policy and applicability record. It does not supply badge logs, visitor records, door events, or facility operating records. If an older local artifact bound that policy under physical_access_system, Pretorin moves the binding to document_repository with only policy_applicability capability when the mutable artifact is loaded or saved. The former generic API-authentication verdict is cleared; a fresh probe must read that policy’s mappings. physical_access_system remains unmapped unless a separate operating-record source is bound and verified. Previously frozen Campaign snapshots retain their historical bytes and are never silently rewritten.

Two grains of availability

  • Control grain — the per-kind rollup answers “is the whole evidence story present?”
  • Executor grain — start_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 prune             # preview stale/duplicate resolver cleanup
pretorin preflight prune --apply     # persist safe removals
pretorin preflight bind <kind> --type <type> [--param k=v ...] \
                       [--probe "<cmd>"] [--capability <cap> ...] [--recommended] \
                       [--constraint "<usage note>"] [--scope k=v ...] [--env-key NAME ...]

pretorin preflight init is the low-friction setup path for a fresh machine: it canonicalizes linked Git worktrees to the primary checkout, detects common local tools (gh, az, aws, kubectl) and local docs/policy folders, then binds those resolvers. GitHub probes are pinned to the repository identity when it can be derived safely, and Kubernetes probes are pinned to the discovered context. Disposable worktree paths are not added. An explicit source_providers configuration gates Azure, AWS, and Google Cloud host discovery so an out-of-scope CLI on PATH does not create a binding. It skips existing mappings unless you pass --replace, and it verifies by default (--no-verify just writes the mappings).

pretorin preflight prune is dry-run by default. It proposes removal of bindings tied to missing or known-ephemeral workspaces and collapses semantic duplicates, retaining the richest constraints and freshest recorded verdict. Use --apply to persist those safe removals and --scope <kind> to inspect only one source kind. Provider-scope mismatches and bindings without a currently connected result are advisory findings; prune never removes them automatically.

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

Use repeatable --env-key NAME when a source command needs an environment variable that is also a model-provider credential, for example --env-key ANTHROPIC_API_KEY. Only names are saved in the preflight artifact; values remain in the invoking host environment. A fresh, machine-verified binding grants that key to a Campaign child even when it uses a different model provider. Unverified or merely attested bindings cannot grant these credentials. Pretorin Campaign authority variables cannot be granted. Run pretorin preflight verify after binding.

--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.