Configuring Zones
zones.toml sits beside config.toml in the machine config directory
(/etc/wardcell), not in the policy root — the policy root holds only
.sbx fragments. It is a machine setting, like the rest of config.toml:
root-owned, and the switch that turns zones on cannot be introduced or dropped
by pointing --policy-root elsewhere.
[zones.anonymous]profile = "anonymous" # resolved exactly like `--profile anonymous`default = true # used when no --zone is givenenter_from = ["*"] # reachable from any zone
[zones.user]profile = "developer"description = "Signed in to the company registry"authenticated = true # turn on credential injectionenter_from = ["anonymous"]requires_approval = true # every entry must be approved firstTOML rather than .sbx on purpose: zones are identity and topology, not
filesystem and network rules, and they are not resolved by the merge
algorithm at all. A separate concern gets a separate file.
Fields
Section titled “Fields”profile | required. The fragment to resolve for this zone’s reach. |
default | this zone is used when run/draft gets no --zone. At most one zone may set it. |
description | what the zone is for, shown by wardcell zone list. An agent inside a sandbox chooses a zone by it. |
enter_from | which zones may enter this one with wardcell zone enter. ["*"] means any. |
authenticated | turn on credential injection. Default false. |
requires_approval | every entry into this zone must be approved, after enter_from has allowed it. Default false. See Entry Approval. |
approval_timeout | how long such an entry waits for its answer — 90s, 30m, 4h. Omit it and the entry waits as long as the approver takes. |
enter_from defaults to [] — no zone may enter this one. Fail closed,
like everything else.
No plugin is named here
Section titled “No plugin is named here”authenticated and requires_approval say what a zone needs. Which program
answers is named once on the machine, in
/etc/wardcell/config.toml:
[plugin]path = "/usr/local/libexec/wardcell/wardcell-plugin"That split is what makes a policy root portable. It is the artifact an organisation distributes and versions; which secret store holds its tokens and where its approvals go belong to the fleet it is deployed to, and one root then serves machines wired to entirely different programs.
A run whose policy needs something the machine’s plugin cannot answer fails before it starts, naming the zone, the setting, and the method:
error: zone 'release' sets requires_approval = true, needing 'approvals.zone', which the plugin '/usr/local/libexec/wardcell/wardcell-plugin' does not implement. It implements: credentials.resolve.See Writing Plugins for the protocol, and two examples that implement all of it.
Note default and enter_from are independent: a zone can be the default
entry point and also reachable by escalation, or neither.
Selecting a zone
Section titled “Selecting a zone”wardcell run --zone user -- git pushwardcell policy draft --zone user -- git push
# explain and render take --zone as a convenience — they resolve the zone's# profile for display and never execute anything, so identity is not involvedwardcell policy explain --zone userOmit --zone and the default = true zone is used.
--profile is rejected once zones exist
Section titled “--profile is rejected once zones exist”Not silently overridden — a usage error.
Without this, anyone could bypass enter_from and default by passing a wider
--profile alongside --zone, which would make every guarantee here
meaningless. A zone’s profile field is the only source of its reach.
Mandating zones
Section titled “Mandating zones”/etc/wardcell is root-owned machine config an org controls. Shipping a
zones.toml there makes every run on that machine go through a zone, with no
flag or environment variable to opt back out — and because it lives outside the
policy root, pointing --policy-root at a different fragment tree does not
escape it.
An org that wants this ships a default = true zone tight enough for everyday
work and gates anything wider behind enter_from:
[zones.work]profile = "developer-readonly"default = trueenter_from = [] # nothing escalates into the default zone
[zones.release]profile = "release"authenticated = trueenter_from = ["work"] # and only from thereThe same trust boundary already makes base.sbx non-overridable: escaping it
means pointing wardcell at a different policy root entirely. Close that too with
policy_root.allow_override = false in
/etc/wardcell/config.toml, and consider
workspace_policy.mode = "off": in the default extend mode, a workspace’s
.wardcell.sbx applies in every zone and can add to any of them.