Core concepts
Policy
Why Warden compiles policy into canonical MIR, where that fits in the pipeline, and the shortest path from a policy source to an enforced decision.Why compiled policy exists
You describe what a command may do in terms that make sense to you: this directory readable, that one writable, this host reachable. A backend needs something else entirely — an SBPL profile, a namespace layout, a set of mounts. Between those two ends sits a translation problem, and where it happens decides what the system can promise.
Warden resolves it once, ahead of time, rather than in each backend. Your policy source is compiled into a canonical MIR: a single, already-resolved statement of what the workload may do. Precedence between overlapping rules, ordering, normalisation and deduplication are all settled during that compilation. What reaches a backend is unambiguous, and backends enforce it without ever re-interpreting your intent.
That choice buys three properties worth naming, because the rest of Warden depends on them:
- Portable — the same MIR expresses the same decision on macOS and on Linux. A policy reviewed once is a policy that travels.
- Backend-agnostic — the planner compares the MIR's requirements against each backend's capabilities, instead of every backend parsing policy on its own. Adding a backend does not mean re-implementing policy semantics.
- Content-addressed — the MIR has a digest, so the exact decision that was enforced can be named, compared and audited afterwards. This is what makes an execution receipt evidence rather than a log line.
Where policy fits
Policy sourceJSON, inline flags or the C builder
Canonical MIRone resolved, digestible decision
Plannermatches requirements to backend capabilities
Backendenforces the decision as written
- Policy source → Canonical MIR
- Canonical MIR → Planner
- Planner → Backend
Compilation happens once, before anything is enforced. Everything downstream consumes the canonical form: the planner reads its requirements, the backend applies them, and the receipt records its digest.
Policy is the first stage, and it is deliberately the only stage that interprets your intent. Read Architecture for the full picture, including where Egress and receipts attach.
What you actually write
MIR is the compiled form, not the thing you author. In practice you supply one of three sources, and Warden compiles it for you:
| Source | You write | Typical use |
|---|---|---|
| Inline flags | --ro, --rw, --allow-read, --allow-write, --net | one-off commands, scripts, CI steps |
| JSON policy | a strict JSON policy source, passed with --policy | a reviewed policy shared across commands |
| C builder | calls against the MIR builder API | embedding Warden in another product |
The binary .mir file is optional in all three cases. A caller can compile a
JSON source in memory and hand Warden the resulting object without ever writing
a file to disk.
The shortest path from source to enforcement
Most CLI users never handle a .mir file. --policy takes a strict JSON policy
source, compiles it to canonical MIR in memory, and runs the command under it:
maelys-warden run \
--policy examples/policies/workspace-readonly.json \
--emit-mir /tmp/effective.mir \
--receipt /tmp/execution.json \
-- make test--emit-mir serialises exactly the canonical decision that was used, and
--receipt records the digest of that decision next to the backend that
enforced it. Neither file is written unless you ask for it.
An already-compiled MIR is passed with --plan instead of --policy, which is
the right shape for a policy that was reviewed, signed or distributed
separately:
maelys-warden run --plan /tmp/effective.mir -- make testBecause the compilation is deterministic, recompiling the same source reproduces the same digest. That is what lets you prove, after a run, that the policy which was reviewed is the policy that was enforced.
Summary
- Warden compiles your policy source into canonical MIR — one resolved, unambiguous decision — before anything is enforced.
- Canonical form is what makes the decision portable across platforms, reusable across backends, and auditable by digest.
- You author inline flags, a JSON source, or builder calls; you rarely handle
MIR directly, and the
.mirfile is optional. --policycompiles a source in memory;--planruns an already-compiled MIR;--emit-mirand--receiptcapture the decision and the evidence.
Where to go next
- Execution receipts — what a run proves after the fact, and how a MIR digest appears in it.
- Architecture — where compilation sits relative to the planner, backends and Egress.
- Backend capability matrix — which requirements each backend can actually satisfy.
- CLI reference — every policy source flag and its invalid combinations.
- policy.maelys.dev — the full authoring reference: the JSON/MIR language, typed permission entries, the C builder API and offline compilation.