Skip to content

EffortlessMetrics/cargo-allow

cargo-allow green checkmark logo

cargo-allow

CI GitHub release crates.io crates.io downloads docs.rs

MSRV License: MIT OR Apache-2.0

Source-tree exception ledger for Rust repositories.

No invisible source exceptions.

cargo-allow is a source-tree exception ledger for Rust repositories. It scans repository files without executing project code, then checks syntax-visible exceptions against policy/allow.toml.

It helps teams answer:

  • What source exceptions exist?
  • Why are they allowed?
  • Who owns them?
  • What evidence supports them?
  • When do they expire or need review?
  • Did this PR add, remove, broaden, weaken, or improve anything?
  • What should a human or agent fix next?

The First Useful Run

The first useful run should feel small:

one repo
-> one visible exception surface
-> one no-new policy
-> one CI receipt
-> one worklist item to close

That is the adoption spine: make retained exceptions visible, keep new debt out, record CI evidence, and give humans or agents a bounded repair queue.

The Problem

Most repositories accumulate exceptions:

  • unsafe
  • unwrap / expect / panic!
  • indexing and slicing
  • #[allow] / #[expect]
  • generated code
  • scripts, workflows, docs, config, and other non-Rust tracked files

The hard part is not finding one exception. The hard part is keeping retained exceptions owned, scoped, evidenced, reviewable, and difficult to silently broaden.

cargo-allow is the ledger layer.

What cargo-allow Does

cargo-allow scans source-tree inventory and compares findings to policy receipts. The durable policy file is policy/allow.toml.

Core workflows:

cargo-allow doctor
cargo-allow audit
cargo-allow check --mode no-new
cargo-allow diff --base origin/main
cargo-allow list
cargo-allow explain allow-0042
cargo-allow worklist --format json

What cargo-allow Does Not Claim

cargo-allow scans repository files directly. It may be installed as a Cargo external subcommand, but the primary UX is the standalone cargo-allow binary. cargo allow ... remains compatibility syntax for users who invoke it through Cargo.

cargo-allow does not compile the project or execute repository code. It does not require a successful build and does not invoke Cargo metadata, Cargo commands, rustc, Clippy, build scripts, proc macros, cargo-deny, cargo-vet, ripr, unsafe-review, or coverage tooling. It does not require network access or GitHub APIs for its own scan. Cargo.toml and Cargo.lock are files in the scanned source tree, not required build metadata.

It does not require:

  • Cargo metadata
  • cargo check or cargo test
  • rustc
  • Clippy
  • build scripts
  • proc macro expansion
  • dependency resolution
  • type analysis
  • MIR
  • control-flow or data-flow analysis
  • proof that unsafe code is correct
  • proof that tests are adequate
  • coverage proof
  • network access
  • GitHub API access

Other tools can provide evidence. cargo-allow owns the durable source-exception ledger.

Current reports may claim:

No new unreceipted findings were found in scanned source-tree inventory.

They must not claim that no unsafe, panic, lint suppression, or other exception exists outside the syntax-visible surface that was scanned.

Where cargo-allow Fits

cargo-allow is not a linter, compiler wrapper, dependency-policy tool, or unsafe proof system.

Clippy:
  flags code patterns.

cargo-deny / cargo-vet:
  govern dependency and supply-chain policy.

ripr / unsafe-review / coverage:
  can provide evidence for retained exceptions.

cargo-allow:
  owns the source-exception ledger: what is allowed, why, by whom, where,
  with what evidence, until when, and whether this PR weakened posture.

Other tools can provide evidence. cargo-allow owns the durable receipt.

Quick Start

Most users start from the surface they already own.

User type First action Main doc
Maintainer Run cargo-allow doctor, then cargo-allow audit. Getting started
New adopter Choose the closest path: source exceptions, no-new, spec-system, CI, or cross-repo rollout. Onboarding
CI owner Add cargo-allow check --mode no-new and upload the receipt. CI guide
Reviewer Run cargo-allow diff --base origin/main. PR posture
Auditor Run cargo-allow list and cargo-allow explain <id>. Explain an allow
Migrator Run cargo-allow migrate --repo-policy <dir>. Migration
Agent operator Run cargo-allow worklist --format json. Agent worklists

First Run

Install:

cargo install cargo-allow --locked

For a specific published release:

cargo install cargo-allow --version 0.1.9 --locked

Use the latest published version shown on crates.io. Do not copy release-candidate versions until they are published.

Check setup:

cargo-allow doctor

Inventory current exceptions:

cargo-allow audit

Start strict, for a small repo:

cargo-allow init --root .

Adopt no-new-debt, for an existing repo:

cargo-allow propose --write policy/allow.toml
cargo-allow check --mode no-new

Generated baseline entries are intentionally uncomfortable. Review them, narrow them, add evidence, or remove them.

CI

For pull requests:

cargo-allow diff \
  --base origin/main \
  --format markdown \
  --output target/cargo-allow/pr-summary.md

For mainline:

cargo-allow check \
  --mode no-new \
  --format markdown \
  --receipt target/cargo-allow/check.receipt.json \
  --output target/cargo-allow/check.md

Upload target/cargo-allow/ as a CI artifact, especially on failure.

Example Review Signal

REVIEW REQUIRED allow-0042

kind: panic
family: indexing_slicing
path: crates/parser/src/span.rs
owner: parser
classification: validated_span_invariant

Evidence:
  ✓ doc:docs/safety/parser-spans.md exists
  ? test:parser_rejects_invalid_text_range not validated offline

Current match:
  ast_kind: index_expr
  container: slice_checked_text_range
  selector precision: high

Claim boundary:
  source-tree/source-syntax only; no macro expansion, type analysis, MIR,
  control-flow, data-flow, or proof-tool execution.

A matching policy receipt is intentionally specific:

[[allow]]
id = "allow-0042"
kind = "panic"
family = "indexing_slicing"
path = "crates/parser/src/span.rs"
owner = "parser"
classification = "validated_span_invariant"
reason = "Parser validates TextRange before slicing."
created = "2026-06-01"
review_after = "2026-09-01"
evidence = ["doc:docs/safety/parser-spans.md"]

[allow.selector]
ast_kind = "index_expr"
container = "slice_checked_text_range"

Evidence Diagnostics

Evidence references can point to local files or traceability handles.

Locally checked examples:

doc:docs/safety.md
spec:docs/specs/parser.md
adr:docs/adr/0001.md
ripr:target/ripr/span-gap.json
unsafe-review:target/unsafe-review/ffi.json
coverage:target/coverage/receipt.json

Traceability-only examples:

test:parser_rejects_invalid_text_range
issue:#123
pr:#456
legacy-policy:no-panic-baseline

cargo-allow does not run those tools. It classifies what it can see and reports what is missing.

Worklists for Humans and Agents

cargo-allow worklist --format json

Worklist items are intended for bounded human or agent work:

broken_evidence_link
weak_evidence_reference
baseline_debt
stale_allow
broad_scope
unsafe_missing_evidence
new_unreceipted_finding

Use the suggested actions and proof commands. Do not suppress findings just to pass CI.

Current Scope

Surface Current state
Source inventory Git-tracked files first, filesystem fallback when needed.
Rust scanning Source-syntax unsafe, panic-family, indexing/slicing, and lint suppressions.
Non-Rust scanning Tracked scripts, workflows, docs/config, generated files, and other governed surfaces.
Policy policy/allow.toml receipts with owner, reason, classification, lifecycle, selector, and evidence.
Evidence Local evidence path checks plus traceability-only references. No proof-tool execution.
PR posture diff --base ... reports new, removed, broadened, weakened, and improved exception posture.
Worklists JSON queues for humans and agents to close retained-risk seams.
Migration Legacy policy adapters for replacing bespoke xtask/TOML allowlists.

Supporting Docs

Need Doc
Choose an adoption path Onboarding
First hour Getting started
Claim boundaries Claim boundaries
Run in CI CI guide
Explain retained exceptions Explain an allow
Repair evidence Fix broken evidence
Feed agents work Agent worklists
Migrate legacy policy Migration from xtask
Understand the model Source exception ledger
Understand PR posture PR posture
Understand policy weakening Policy weakening
JSON artifacts JSON schemas
Crate responsibilities Crates
Changelog CHANGELOG.md

Crates

Most users only need cargo-allow.

The workspace uses allow-* crates for implementation layers:

  • allow-core
  • allow-policy
  • allow-policy-legacy
  • allow-inventory
  • allow-files
  • allow-rust
  • allow-match
  • allow-diff
  • allow-report

These crates are public because the workspace is split cleanly, but their primary purpose is supporting cargo-allow. See the crate responsibility guide and crate namespace policy before adding new public crates.

Development

Use nearby project patterns, keep changes narrow, and validate source-tree posture before publishing a README or policy change:

cargo test -p cargo-allow readme
cargo run -p cargo-allow -- check --mode no-new --format markdown --receipt target/cargo-allow/check.receipt.json --output target/cargo-allow/check.md

License

MIT OR Apache-2.0

About

Repo Allowlist for Rust

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors