Skip to main content

How Stave Works

Stave is a pipeline with four stages: inputs, schema validation, evaluation, and structured output. Each stage is shown below.

1. Inputs

Two inputs feed the pipeline — observation snapshots captured from your infrastructure, and control definitions that encode your safety policies.

Each observation file is a flat JSON snapshot of your infrastructure at a specific point in time. Each control is a YAML file defining a safety property that must hold true. Stave ships with 2,891 controls across 85 domains, and you can write your own.

2. Schema Validation

Both inputs are validated against embedded JSON Schema (Draft 2020-12) before evaluation begins. If validation fails, Stave exits with code 2 and no evaluation runs.

Valid inputs proceed to evaluation:

Invalid inputs halt the pipeline:

# Validate inputs before evaluation
stave validate --controls ./controls --observations ./observations

3. Evaluation

After validation, the engine builds a timeline for each resource across all snapshots, then evaluates every control against every resource.

TypeBehavior
unsafe_stateViolation if the resource is attack surface
unsafe_durationViolation if the resource has been continuously unsafe longer than --max-unsafe
unsafe_recurrenceViolation if the resource has toggled unsafe repeatedly
prefix_exposureViolation if protected S3 prefixes are publicly readable

4. Output

Stave's output conforms to the out.v0.1 schema, enforced at the Go type level. The output is structured JSON designed for machine consumption by downstream systems — CI/CD pipelines, dashboards, ticketing integrations, and audit tools.

The output schema guarantees:

  • A run object with tool version, --eval-time timestamp, snapshot count, and deterministic input hashes
  • A summary with resources_evaluated, attack_surface, and violations counts
  • A findings array where each finding includes control_id, resource_id, evidence, and mitigation
  • Deterministic output: same inputs with --eval-time always produce byte-for-byte identical JSON
# Evaluate and pipe to downstream tools
stave apply \
--controls controls/s3 \
--observations ./observations \
--max-unsafe 7d \
--eval-time 2026-01-15T00:00:00Z \
| jq '.findings[] | select(.severity == "critical")'

Schema Locations

SchemaFormatLocation
obs.v0.1JSON Schema Draft 2020-12schema_canonical/obs.v0.1.schema.json
ctrl.v1JSON Schema Draft 2020-12schema_canonical/ctrl.v1.schema.json
out.v0.1Go struct contractEnforced by internal/adapters/output/writer.go

Observations and controls are validated at runtime against the embedded JSON Schema files. The output schema is defined by Go struct types — downstream consumers can rely on the out.v0.1 field contract being stable across patch releases.