Docs · Policy check
Gate merges on declared policy.
Available · Runs locallyledgerful policy check evaluates a flat, named rule set against PR/diff/ledger state and exits nonzero on violation — offline, deterministic, no engine network code.
Honest limit
Policy as code is evaluation of declared rules, not a compliance certificate.
Honest limit: policy check evaluates the declared rules over the presented ledger and risk inputs. It is not a compliance verdict, certification, or proof that a change is safe. Chain continuity strengthens the presented ledger; it is still not a substitute for your org's change-management process.
Availability
The command is on the public engine source. Install from source (or a release binary that includes it).
Source install (includes policy check):
cargo install --git https://github.com/Ryan-AI-Studios/Ledgerful --bin ledgerful --lockedThe v0.1.8 prebuilt release binaries predate this command. Use a source install, or a later release that ships policy check, until the next numbered release catches up. Confirm with ledgerful policy check --help.
Base-branch policy constraint
Read this before wiring CI.
Bypass-proof default: In CI the enforced policy is the base branch's (or a trusted --policy path), not your PR's. Edits to .ledgerful/policy.toml in a PR branch do not change the gate until they are merged and reviewed on the base branch.
When you run ledgerful policy check --pr origin/main...HEAD, Ledgerful loads .ledgerful/policy.toml via git show <base_ref>:.ledgerful/policy.toml. A policy change only takes effect after it is merged to the base branch. To pin an org-level file instead, pass --policy /path/to/org-policy.toml (trusted path).
Invocation
Human report by default; machine JSON for CI wrappers.
ledgerful policy check
ledgerful policy check --pr origin/main...HEAD
ledgerful policy check --pr origin/main...HEAD --fail-on high
ledgerful policy check --policy .ledgerful/policy.toml
ledgerful policy check --pr origin/main...HEAD --format json| Flag | Description |
|---|---|
--pr <range> | PR-style range (base...head, base..head, or bare base). Evaluates the committed range only. |
--fail-on <level> | Override config rules.fail_on for this run: off | low | medium | high. |
--policy <path> | Trusted policy file (org/CI). Skips base-branch and working-tree resolution. |
--format json|text | Machine contract (json) or human report (text, default). |
Evaluation target
Local mode predicts CI for committed content and still catches pending work before push.
| Mode | What is inspected |
|---|---|
--pr | Committed range only — risk from the PR diff; committed ledger signatures and bound verification runs when a ledger DB is presented. Does not inspect pending DB transactions or the sidecar. |
| Local / default | Pending ledger txs, the pending_hook_tx sidecar, and working-tree risk when evaluable. |
Git-only vs ledger-backed: .ledgerful/ is gitignored (state stays local). Force-add policy.toml for CI. Clean runners have no ledger.db unless your pipeline presents one. Use CI-safe rules (git-evaluable only) on the base branch unless you restore a ledger artifact.
Built-in rules
Named, parameterized rules in a flat TOML config. No expression-language DSL.
| Rule id | Default (local / full) | Behavior |
|---|---|---|
require_signed_entries | on | Any committed entry with missing or invalid signature/public_key is a violation. Fail-closed if the ledger database is absent (present an artifact or disable the rule). |
no_pending_tx | on | Local only: pending ledger transactions and the pending_hook_tx sidecar are violations. Skipped under --pr (committed range only). |
verification_must_pass | on | A bound verification run for the evaluation target must pass. Fail-closed if the ledger database is absent or no bound run exists. Under --pr, every changed path needs a covering bound run (newest covering run is decisive). |
max_risk_without_adr | high | When risk is at or above the threshold, every changed path needs covering ADR evidence for this change set. Set to off to disable. |
fail_on | high | When risk is at or above the threshold, emit a violation. Risk uses the same levels as scan --pr. Set to off to disable. |
Config examples
Flat .ledgerful/policy.toml. Force-add it so the base branch can serve it via git show.
CI-safe (recommended base branch)
# .ledgerful/policy.toml (force-add; .ledgerful/ is gitignored)
preset = "enforce"
[rules]
require_signed_entries = false # needs presented ledger.db
no_pending_tx = true # skipped under --pr; useful locally
verification_must_pass = false # needs presented ledger.db + bound runs
max_risk_without_adr = "high" # off | low | medium | high
fail_on = "high" # off | low | medium | high
Full local / ledger-backed
preset = "enforce"
[rules]
require_signed_entries = true
no_pending_tx = true
verification_must_pass = true
max_risk_without_adr = "high"
fail_on = "high"
Presets: observe evaluates and warns but always exits 0. enforce blocks (nonzero exit) on violations. These presets subsume gate.mode (observe / enforce) without a breaking change — mode transitions still write signed MAINTENANCE ledger entries. Policy and mode never enter the Ed25519 signing basis.
JSON machine contract
--format json is the machine contract for CI wrappers (including the GitHub Action surface). Versioned; camelCase.
{
"schemaVersion": 1,
"violations": [
{
"ruleId": "no_pending_tx",
"file": ".ledgerful/state/ledger.db",
"line": null,
"message": "pending ledger transaction a1b2c3d4 (entity=src/foo.rs)",
"severity": "error"
}
],
"passed": false,
"mode": "enforce",
"policySource": "base-branch"
}
Per violation: ruleId, file, line, message, severity. passed is true only when there are zero violations. Optional notes is omitted when empty.
CI usage and permissions
Pairs with the GitHub Action surface: policy check only evaluates and exits; posting comments or check-runs stays in the Action wrapper.
| Permission | Why |
|---|---|
contents: read | Checkout and git show of the base-branch policy file. |
pull-requests: read | Optional Action wrapper may read PR metadata for annotations. |
checks: write | Optional: native check-run from the 0047 Action wrapper. Not required for policy check itself. |
name: Ledgerful policy gate
on:
pull_request:
permissions:
contents: read
pull-requests: read
checks: write
jobs:
policy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install ledgerful
run: cargo install --git https://github.com/Ryan-AI-Studios/Ledgerful --bin ledgerful --locked
- name: Policy check
run: |
ledgerful policy check \
--pr origin/${{ github.base_ref }}...HEAD \
--format json \
--fail-on high
- Prefer a committed base-branch
policy.tomlwithpreset = "enforce"and CI-safe rules. If the base has no policy file,--prsynthesizes the same CI-safe enforce defaults (policySource: "synthesized"). fetch-depth: 0(or an explicit fetch of the base ref) is required sogit showcan resolve the base policy.- To enforce ledger-backed rules in CI, present a ledger artifact and enable those rules on the base branch.
- The engine path is offline: no network crates on the policy path. Network posting (if any) belongs to the Action wrapper, never the engine.
Related: GitHub Action docs (Action install status is separate from this CLI gate) and the Trust policy-as-code summary.