Skip to content

Native Rules

When the DSL has no verb for something the backend supports, a native block passes raw rules through unchanged.

[macos]
native {
seatbelt [
"(allow mach-lookup (global-name \"com.apple.example.service\"))",
]
}

The text is not validated, not parsed, and not portable. wardcell emits it verbatim into the rendered profile. A syntax error surfaces as a sandbox-exec failure at run time, not as a resolve error with a line number.

It also does not participate in the merge algorithm. Specificity, deny-beats- allow and the layer rules all operate on structured rules; a native rule sits outside them.

seatbelt is the only field. Bubblewrap has no rule language to pass through — its interface is command-line flags, so there is nothing analogous to expose.

A native block is therefore always macOS-only in practice. Tag it [macos] to make that explicit.

Legitimately: a Mach service, an IOKit class, or another Seatbelt operation the DSL does not model. chromium-headless is the real example in the bundled tree.

Otherwise, treat reaching for it as a signal that a verb is missing. The structured verbs are checked, cross-platform and explainable; a native rule is none of those, and you own it forever — including when a future macOS changes the operation’s name.