Rule CLI
trustacks rule is the command-line tool for TruStacks policy. It writes,
tests, lints and signs rules in a local checkout, with no control plane and no
account. It is the local alternative to Propose as PR in the app: use
it to write a rule by hand, or to land a rule drafted by /rule new from
your own checkout. See Add your own rule.
Running it
There is no standalone CLI package. Run it from the runner image, which
also carries opa, oras, and cosign:
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD:/work" -w /work \
ghcr.io/trustacks/runner:<version> \
trustacks --helpIf you work from a source checkout of the runner, uv run trustacks does the
same.
From 0.2.17, rule test, lint and sign run opa with the same
restricted builtins the runner uses (no network, environment or schema
$ref fetching), so a rule that passes locally compiles on the runner too.
The runner image carries a matching opa. If you use your own opa from a
source checkout and it is much older, you may need to upgrade it.
Conventions
- Exit code
0on success,1on any failure. - Output is for people (Rich formatting). There is no JSON output mode.
- There is no config file and no
logincommand:trustacks ruleworks on local files only.
Overlay rules: trustacks rule
Every rule command takes --overlay PATH, a local checkout of your overlay
repo. It defaults to the current directory and must contain
environment-profile.yaml at its root. Rules live in rules/<rule_id>/.
trustacks rule new
trustacks rule new <rule_id> [--description TEXT] [--package NAME]Scaffolds rules/<rule_id>/<rule_id>.rego and <rule_id>_test.rego. The
rule ID must meet the naming standard. The
package defaults to overlay.<namespace>_<name>. A --package you pass
must start with overlay.; anything else is refused, because the runner
rejects overlay rules outside data.overlay
(details).
The stub’s deny condition is false, so it never fires until you replace
it. The test file ships one passing baseline test and a commented template
for the real one. Refuses to overwrite an existing rule directory.
trustacks rule new acme.requires_runbook_link \
--description "Every service ships a runbook link"The stub declares every rule metadata field, as a structural rule that applies everywhere:
rule_metadata := {
"acme.requires_runbook_link": {
"description": "Every service ships a runbook link",
"kind": "structural",
"required_tooling_categories": [],
"practice_dimensions": [],
"tier_scope": ["any"],
"target_kinds": ["any"],
},
}
rule_index := rule_metadataChange kind to "behavior" and name at least one practice in
practice_dimensions if the rule judges how a change’s files behave. Add
"subjects": ["proposal", "repo"] to include it in the
repo audit. Without --description,
the description is a TODO placeholder.
trustacks rule test
trustacks rule test [rule_id] [-v | --verbose]Runs opa test on one rule’s directory, or on all of rules/. --verbose
prints each test name. Exits with opa’s status. An overlay with no rules/
directory exits 0.
trustacks rule lint
trustacks rule lint [rule_id]Checks rule ID validity, that both files exist, that the rule declares a
package and a rule_metadata map keyed by its ID, then runs opa check,
the overlay confinement check (every package under overlay., data only
in data.overlay, no symlinks, allowlisted file types) and the
rule metadata check: every
required field declared, with values in the schema. Without opa on your
PATH, it skips opa check, the package part of confinement and the
metadata check. See Policy linter for the full list and what it
does not check.
trustacks rule sign
trustacks rule sign [--bundle-ref REF] [--registry HOST:PORT] [--tag TAG]
[--key PATH] [--signing-config PATH]
[--insecure | --no-insecure]Builds an OPA bundle from rules/ (with a rule_inventory.json), pushes it
with oras, and signs the pushed digest with cosign. Every rule ID is
checked against the naming standard first, and the overlay confinement
check runs before the build: an overlay that reaches outside data.overlay
is refused, not signed. It does not run the rest of lint, or test.
| Flag | Default |
|---|---|
--bundle-ref | <registry>/trustacks/policy/overlay/<profile name>:<tag>, where the profile name is name: in environment-profile.yaml |
--registry | zot.localtest.me:8080 |
--tag | dev |
--key | .policy-keys/cosign.key |
--signing-config | .policy-keys/signing-config.json (offline, no transparency log) |
--insecure / --no-insecure | --insecure (plain HTTP) |
The defaults target the local development registry and a local key, and
per-customer signing keys are not built. A hosted runner (0.2.17 and later)
does not need a bundle: it loads your rules from rules/ in your platform
repo. See the constitution page.
Not in the CLI
These appeared in earlier versions of this page and do not exist: rule list, rule show, env declare, env validate, env diff, login,
status, version, --output json, and ~/.trustacks/config.yaml. Browse
rules on the Rules page instead.
Where to go next
- Policy linter · what
rule lintchecks - Rule-naming standard · valid rule IDs
- Constitution · the rules your overlay adds to