plan → apply loop.
The dashboard remains fully usable. A project can mix both: the platform team
keeps critical controls in git, while a compliance lead tunes others from the
UI. Neither surface can silently clobber the other.
Why you might want this
Review before enforcement
A change to what gets blocked in production goes through the same review as
any other change, with a diff a reviewer can read.
Reproducible across environments
The same files apply to
staging and prod, so the two cannot drift apart
by accident.An audit trail that proves itself
Every apply records the content hash of each file, so an auditor can see
exactly what was deployed and when.
Catch mistakes before they ship
zespan policy validate runs offline as a pre-commit hook — no network, no
API key.The authoring loop
1
Scaffold a policy
policies/pii-egress.yaml with a starter policy in dryrun mode.2
Validate locally
3
See what would change
4
Apply
apply always computes a fresh plan first and sends its hash along, so you
can never apply a plan you did not see. If the state changed in between, the
apply is refused rather than silently applied to different state.Ownership: what code owns and what the dashboard owns
Every guardrail row carries an ownership marker. This is the mechanism that makes mixing the two surfaces safe.Detaching a policy
Sometimes you need to change a policy from the dashboard — during an incident, say, when editing a file and opening a PR is too slow. Open the guardrail’s detail page and choose Detach. Ownership moves to the dashboard, the form becomes editable, and the nextzespan policy apply reports
the policy as a conflict and refuses to overwrite it:
zespan policy apply --force to take ownership back.
Removing a policy is a hard stop
If a policy disappears from your file set,apply refuses:
--allow-remove makes it deliberate.
The enforcement ladder
spec.enforcement sets the policy’s posture. It applies to every rule in the
policy, so you can move a whole policy along the ladder in one line:
Note that
warn also softens redact — a policy explicitly placed in warn mode
must be observable without changing what your application receives.
Governing models, secrets and output shape
Three primitives exist specifically for policy files, beyond the content guardrails you may already use:model_governance
Allow/deny model globs, a required provider, and data-residency regions.
secret_egress
Credentials and tokens in output, matched against a maintained pattern set.
schema_contract
Output validated against your own JSON Schema, not just “is it JSON”.
- If
requireProvideris set and the provider cannot be determined from the model name, the rule fails rather than guessing. A guess would silently admit a model nobody vetted. - If
allowRegionsis set and the caller did not report a region, the rule fails. Passing would report a data-residency control as satisfied when it was never actually evaluated.
Scoping a policy to environments
appliesTo.environments is a guard, not a router. It does not expand one
apply into several, and it never sends a policy anywhere you did not name on the
command line. It does exactly one thing: apply refuses to write a policy into
an environment the policy does not list.
--env production
resolves to the prod environment, so a policy listing prod applies cleanly
under either spelling; omitting --env resolves to the project’s default
environment and is checked against that. A policy that lists no environments is
unconstrained and applies wherever you point it.
Nothing is written when the guard fires — this refusal is checked before every
other one, so you hear about a misdirected apply before you hear about a stale
plan.
Scoping a policy to models
environments, this one is checked on every request: the policy’s
rules simply do not fire for a request reporting a model outside the list.
Globs use * only. A request that reports no model at all is out of scope
rather than blocked — passing an unvetted request through a model-scoped
control would be a worse default than skipping it, and model_governance
already established the convention.
Scheduling
A policy can apply only during certain days and hours:timezone: UTC is honoured today; any other value falls back to UTC rather than
using the server’s local offset, which would make the same policy behave
differently depending on where it ran.
Adopting a project that already has guardrails
You do not have to hand-write a file for every guardrail you already built.zespan policy pull generates them from what is already there:
1
Generate the files
policies/, and prints a warning for
anything it could not express exactly (see below). It never overwrites a file
you have already edited unless you pass --force.2
Check that it round-trips
3
Take ownership
--adopt is required for the same reason --allow-remove is: taking over a
guardrail makes it read-only for whoever built it in the dashboard, and that
should be a decision rather than a side effect.
What pull cannot express
Generation is not lossless, and it says so at the time rather than letting you
discover it later:
Reviewing changes in the dashboard
Guardrails → Review changes does whatzespan policy plan does: paste or
upload policy files and see the same change set, computed by the same endpoint,
so the two cannot disagree.
It is deliberately read-only. Reviewing needs policy:read, which every role
has; applying needs policy:apply, which only owner and admin have. Somebody
reviewing a pull request should not need a terminal, and should not gain the
ability to apply by using the dashboard instead.
Before you enforce
Promoting a policy todeny requires a backtest or an explicit --untested.
zespan policy test runs the policy over your own recorded traffic and shows
what it would have caught and what it would have broken — see
Policy testing.
Policies can also be evaluated in-process by the SDK rather than over the
network, for the rules that are pure functions — see
Local evaluation.
What is not in this release
- Compliance packs — installable HIPAA / EU AI Act / PCI / OWASP-LLM policy sets.
- Custom expressions and webhooks — CEL predicates and customer-hosted evaluation endpoints.
Next steps
File reference
Every field, its type, and whether it is required.
zespan policy
The full CLI verb reference.
Guardrails
The dashboard side, including the code-managed badge and Detach.
CLI overview
Configuration precedence for API keys and project ids.

