CI
Checking a policy file with interbolt validate in CI or pre-commit.
CI
interbolt validate
interbolt validate policy.yamlPerforms schema and CEL checks only; see Policies: static validation for the full list. It never executes an agent and never observes live taint, and imports no consumer code, which is what lets it run anywhere a file can be read: CI, pre-commit, a developer's shell. It runs in milliseconds.
Problems come in two kinds, and the exit code follows the more serious one:
- Errors (a schema violation, a CEL parse failure, an unreachable rule, a
reference to an uncomputed trifecta leg or
run.field, a policy declaringversion: "1.0"or a sink entry written as a bare rule list) exit1. - Warnings (a
t.sourcecomparison, a sink entry with nocapabilities:key once another entry declares one) print but exit0, so a policy that is valid with warnings does not fail the build.
The Python-level equivalent, for a custom CI script or a test. Warnings are
prefixed warning: , so filter them out if you want the same behavior as
the CLI:
from interbolt import Policy
problems = Policy.validate("policy.yaml")
errors = [p for p in problems if not p.startswith("warning: ")]
if errors:
raise SystemExit("\n".join(errors))Pre-commit
# .pre-commit-config.yaml
- repo: local
hooks:
- id: interbolt-validate
name: interbolt validate
entry: interbolt validate policy.yaml
language: system
pass_filenames: falsePair it with decision tests
A clean validate means the policy is well-formed, not that it matches your
agent. It cannot see a sink key that matches no guarded tool, an args.*
reference that does not match a real signature, or a carve-out rule placed
below the rule it was meant to except. See
Policy evaluation internals: what it does not catch.
It also cannot tell you whether a specific agent's access silently changed: adding an agent to a group changes what fires for it with no rule edit at all. See Explain for the golden-file pattern that covers that gap.
Cover those with check()-based decision tests in the same job, so the
static and dynamic checks land together:
interbolt validate policy.yaml && pytest tests/test_policy.pySee Testing for the test patterns.
The INTERBOLT_MODE escape hatch
interbolt validate is the static check. The dynamic counterpart is running
your actual test suite with the policy enforced. If a known-noisy or
in-progress policy is blocking an unrelated CI job, the INTERBOLT_MODE
environment variable overrides both configure(mode=...) and the policy
file's defaults.fail_mode:
INTERBOLT_MODE=monitor pytestThis downgrades evaluation errors to log-and-proceed without disabling real
block decisions. The override logs a WARNING whenever it changes the
effective mode, so it is meant as a visible, one-off operator action, not
something to set as a CI configuration default.
See Auditing for running the laundering audit against a recorded workload in a staging job.