Skip to content

Formatting a Policy

A .sbx file has one canonical shape, and wardcell policy fmt rewrites a file into it:

Terminal window
wardcell policy fmt .wardcell.sbx # rewrite one file
wardcell policy fmt policies/ # rewrite a whole tree
wardcell policy fmt --check policies/ # CI: fail if anything is not formatted

The point is diffs. Two people writing the same rules, or one person editing by hand, land on the same bytes — so a git diff shows a grant that changed, not a list someone re-wrapped or re-sorted. It is the gofmt bargain: there are no style options, because the value is that every file comes out the same.

wardcell policy draft already writes this form, so a drafted or updated file needs no second pass.

  • Sections run in a fixed order: schema_version, selects_on, offer_on, requires, then env, args, fs, net, native. Blocks group by section, and within a section the common (untagged) block comes first, then [linux], then [macos] — so every fs block sits together, not every tagged block pushed to the end.
  • Rules sort within each block, and entries sort within each list — one entry per line, so adding or removing one is a one-line diff. Hosts sort by their labels read right to left, so a whole domain clusters: *.example.com sits next to api.example.com, and literal addresses sort after every name.
  • Duplicate entries are removed. A value repeated in a list grants nothing the first does not, so the extra copies are dropped (a comment on one is kept on the one that stays). Argument and native lists are the exception — their order decides which value wins, so they are left exactly as written.
  • Whitespace is normalised: two-space indent, one blank line between blocks, a single space before a trailing #.
  • Comments are preserved exactly and travel with the rule they sit on. A comment that must stay with a specific entry has to be that entry’s trailing comment; a line above a list is read as belonging to the whole list and stays at its head.

Formatting never changes what a policy grants: the command re-parses its own output and leaves the file untouched if the grant set would differ.