missive uses local, reproducible Rust dependency checks before release. The policy is intentionally conservative for advisories, crate sources, and duplicate versions, while allowing the permissive licenses currently present in the Cargo workspace graph.
The policy file is ../deny.toml. When cargo-deny is installed,
scripts/quality-gate.sh runs:
cargo deny --locked checkThe GitHub Actions Linux quality-gate job installs a pinned cargo-deny version
so CI enforces the same policy. Local developers can install or verify optional
tools with:
scripts/bootstrap-tools.sh --check
scripts/bootstrap-tools.shUseful direct commands:
cargo deny --locked check
cargo audit
cargo machete
cargo tree -d --all-featurescargo-audit and cargo-machete remain optional local gate checks: they are run
when installed and skipped with a warning when absent. cargo-deny is the source
of truth for the reviewed license/source/advisory/duplicate-version policy.
Allowed dependency licenses are listed in deny.toml as SPDX identifiers:
Apache-2.0andApache-2.0 WITH LLVM-exceptionMIT,ISC,BSD-2-Clause,BSD-3-Clause,BSL-1.0,Zlib, andUnlicenseUnicode-3.0for Unicode/ICU data crates used by URL/IDNA handlingCDLA-Permissive-2.0for trusted root data crates
Workspace crates are not ignored by the license check; their license comes from
workspace.package.license and should remain Apache-2.0 unless an ADR and
maintainer review change the project license.
When a new dependency introduces a new license:
- prefer a dependency with an already allowed permissive license;
- review the license text and obligations;
- document the reason in this file before adding it to
deny.toml; - rerun
cargo deny --locked checkand the full quality gate.
Do not add strong copyleft, network-copyleft, commercial, source-available, or unknown license terms without an explicit project decision.
cargo-deny uses the RustSec advisory database and denies yanked crates. The
current policy has no advisory ignores. If an advisory is ignored in the future,
the ignore entry in deny.toml must include a reason, a risk assessment, and a
planned removal condition in this document or a linked issue.
Allowed crate sources are limited to the crates.io registry. Unknown registries
and unknown Git dependencies are denied. If a future change pins a Git dependency
(such as an upstream A2A SDK revision), add the exact repository URL to
allow-git, document the pin/update process, and keep credentials out of Cargo
configuration and CI.
deny.toml denies duplicate crate versions by default. Existing duplicate-version
exceptions are reviewed transitive dependencies where missive cannot force a
single version without forking or prematurely replacing upstream crates:
| Crate line | Reason |
|---|---|
getrandom 0.2 |
Pulled by ring/rustls while newer getrandom is used by tempfile and a2a-lf. |
hashbrown 0.14 |
Pulled by rusqlite/hashlink while toml/indexmap use a newer line. |
unicode-width 0.1 |
Pulled by miette while textwrap uses unicode-width 0.2. |
windows-sys 0.52/0.60 and windows-targets 0.52 target crates |
Transitive Windows support split across ring, keyring, clap, and Tokio-era crates. |
wit-bindgen 0.46 |
Transitive WASI support through getrandom/proptest while a newer line is also present. |
When updating dependencies, run both cargo deny --locked check and
cargo tree -d --all-features. Remove a skip from deny.toml as soon as the
older transitive line disappears. New duplicate skips require a reason in
deny.toml and a short note in this document.
For routine dependency updates:
cargo update
cargo deny --locked check
cargo audit
cargo machete
scripts/quality-gate.shFor a targeted update:
cargo update -p crate-name
cargo tree -i crate-name --all-features
cargo deny --locked check
scripts/quality-gate.shBefore committing dependency changes:
- inspect
Cargo.lockfor unexpected large transitive changes; - confirm no new registries, Git URLs, or duplicate skips were introduced without documentation;
- confirm no advisories are ignored without a removal plan;
- update release, security, or protocol docs if a dependency materially changes TLS, storage, auth, protocol, or packaging behaviour.
A metadata-derived CycloneDX JSON SBOM can be generated locally without contacting third-party services:
scripts/generate-sbom.sh --output dist/missive-sbom.cdx.jsonThe script uses cargo metadata --all-features --locked, records workspace and
transitive Cargo packages, includes license expressions where available, and
writes dependency relationships. dist/, sbom/, *.cdx.json, *.spdx.json,
and default bom.json/bom.xml outputs are ignored or guarded as generated
artifacts; do not commit generated SBOMs unless a future release process
explicitly asks for reviewed artifacts.
Current SBOM limitations:
- it describes the Cargo workspace dependency graph, not OS packages, container base images, release workflow actions, or binary provenance;
- it is not a signed attestation;
- release archives do not yet bundle SBOMs by default.
For release hardening, generate an SBOM alongside checksums, inspect it with a CycloneDX-compatible tool if available, and attach it as a release artifact rather than committing it to the source tree.