Skip to main content

stave bisect

Bisect searches through timestamped snapshot history to find the exact
point in time when a control was first violated. Like git bisect for commits,
it binary-searches through a snapshot archive.

Modes:
bisect (default) Binary search — O(log N), finds the transition into the
current violation window. Fast for large archives.
scan Linear scan — O(N), finds ALL violation windows including
the earliest. Correct for non-monotonic histories.

Inputs:
--controls, -i Path to control definitions directory
--observations, -o Path to snapshot archive directory
--control-id ID of the single control to bisect (required)
--mode Search strategy: bisect or scan (default: bisect)
--format, -f Output format: text or json (default: text)
--now Override current time (RFC3339) for deterministic evaluation
--resource Scope to a specific resource ARN (optional)

Output:
Text mode shows the transition point with a property delta between
the last PASS and first VIOLATION snapshots. Timestamps use "between
A and B" language — Stave operates on snapshots and cannot attribute
changes to specific events within a window.

Exit Codes:
0 No violation found in the archive
2 Input error (missing flags, no snapshots)
3 Violation window(s) found
4 Internal error

Offline-only: reads local files; makes zero network connections; no cloud credentials.

Usage:
stave bisect [flags]

Examples:
# Find when a bucket became public
stave bisect -i controls/s3 -o snapshots/ --control-id CTL.S3.PUBLIC.001

# Scan for all violation windows over 12 months
stave bisect -i controls/s3 -o snapshots/ --control-id CTL.S3.PUBLIC.001 --mode scan

# Scope to a specific resource
stave bisect -i controls/ -o snapshots/ --control-id CTL.S3.ENCRYPT.001 --resource arn:aws:s3:::prod-bucket

Flags:
--control-id string Control ID to bisect (required)
-i, --controls string Path to control definitions directory (default "controls")
-f, --format string Output format: text or json (default "text")
-h, --help help for bisect
--mode string Search strategy: bisect or scan (default "bisect")
--now string Override current time (RFC3339)
-o, --observations string Path to snapshot archive directory (default "observations")
--resource string Scope to a specific resource ARN

Global Flags:
--allow-symlink-output Allow writing output through symlinks (default: refuse)
--force Allow overwriting existing output files
--log-file string Write logs to file (default: stderr)
--log-format string Log format: text|json (default "text")
--log-level string Log level: debug|info|warn|error (overrides -v)
--log-timestamps Include timestamps in logs (breaks determinism)
--log-timings Include timing information (breaks determinism)
--no-color Disable ANSI colors in output
--path-mode string Path rendering in errors/logs: base (basename only) or full (absolute paths) Resolved default may come from STAVE_* env vars, stave.yaml, user config, or built-in.
--quiet Suppress output (exit code only) Resolved default may come from STAVE_* env vars, stave.yaml, user config, or built-in.
--require-offline Assert offline operation: fail if proxy env vars (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY) are set
--sanitize Sanitize infrastructure identifiers (bucket names, ARNs, policies) from output Resolved default may come from STAVE_* env vars, stave.yaml, user config, or built-in.
--strict Enable strict integrity checks for embedded registries and references
-v, --verbose count Increase verbosity (-v=INFO, -vv=DEBUG)
-y, --yes Auto-confirm all interactive prompts (distinct from --force which controls file overwriting)