Skip to content

Layers and Merge Rules

Three layers, resolved in order.

LayerWhatRule
1. basebase.sbxalways loaded, always first, never overridden
2. selectedfragments from selects_on, --profile, requiresadd freely; order does not matter
3. workspacethe .wardcell.sbx in the working directorymay add, but never weaken base.sbx

Layer 2 is order-independent by design. Fragments are parsed into one IR and merged by an explicit algorithm — nothing is concatenated, so there is no “last one wins” to reason about.

Two rules on overlapping paths resolve by specificity — the more path components, the more specific — not by declaration order.

base: deny_read ["~"]
fragment: allow_read ["~/projects/app"]
→ ~/projects/app is readable; the rest of ~ is not

Three ways this errors instead:

ErrorWhen
BaseOverridea layer-2/3 fragment tries to loosen a base-layer deny at equal-or-lesser specificity
SameLayerTietwo layer-2 fragments assert allow and deny on the same path at equal specificity
WorkspaceOverridesBasea .wardcell.sbx grants something inside a path base.sbx denies

A SameLayerTie is an authoring ambiguity, so it is rejected rather than silently resolved. Fix it by making one rule more specific.

Longest-path-wins is what lets a shared fragment carve ~/.ssh/known_hosts out of a base deny_read ["~/.ssh"]. The workspace layer does not get that: an allow in a .wardcell.sbx on or inside any path base.sbx denies is refused, however specific.

A workspace policy may add fs, network and environment grants like any fragment, except inside a base.sbx deny, and never native rules, which render after base.sbx and could undo any of it. Network and environment need no extra check: a deny wins over every allow whichever layer wrote it. An organisation can turn the layer off in config.toml. See Workspace Policies.

Naming one destination both as an allow_http block (inspected) and in allow_tcp (spliced opaquely) is an error. The two are not additive — one would silently win, and the narrower would look enforced while doing nothing.

The test is whether they share any destination, not whether they were spelled the same:

allow_http "api.example.com" # ports 80 and 443
allow_tcp ["api.example.com:443"] # ← error: overlaps on 443
allow_http "*" # every host, 80 and 443
allow_tcp ["db.internal:5432"] # ← fine: ports cannot intersect
  • Adding reach? Write a new fragment. Grants union.
  • Removing reach? Add a deny_*. It wins from anywhere.
  • Hit a tie? Make one rule more specific.
  • .wardcell.sbx rejected? It is reopening something base.sbx denies. Put the grant in a fragment in the policy root, if it belongs anywhere.