ADR-007: Dependency Audit and Upgrade Decisions

On this page

Status

Accepted

Context

As part of pre-Phase 6 hardening, all workspace dependencies were audited against crates.io (March 2026). At that audit point, 30 direct workspace deps existed; 23 were already at their latest version. Seven required action: 4 upgrades, 1 removal, and 2 deferred with documented rationale.

Since March 2026, additional direct workspace deps have landed. As of 2026-04-20 the [workspace.dependencies] block carries ~40 direct crates. Notable additions not reflected in the 30-dep audit below:

  • tower-cookies (3) + aes-gcm-siv / aead — landed with ADR-013 (stateless encrypted session cookies, !81).

  • thiserror (2) — typed error enums at service/SDK boundaries (EngineError in craig-rules, IntakeError::ResponseDecode in craig-intake-sdk; see CHANGELOG 2026-04-19).

  • csv (1) — federal flat-file emission; replaces hand-rolled format!()-based TSV in craig-reporting AFCARS export (CHANGELOG Step 8).

  • ammonia (4) — HTML sanitization on public-intake narrative fields.

  • p256 + base64ct + sha2 (ADR-010 JWS detached signatures) across craig-intake-sdk and craig-test-lib.

  • craig-intake-sdk, craig-crypto, craig-reference promoted to [workspace.dependencies] so downstream crates can reference via workspace = true instead of path deps.

  • craig_common::build_shared_client (new module, not a separate dep) — single-source-of-truth reqwest::Client builder landed 2026-04-20 to close four "per-call Client::new()" TODOs.

Refresh the full dep inventory as part of the next hardening plan; the list below is retained for historical traceability of the March 2026 decisions.

Decisions

Upgrades Applied

Crate From To Notes

tabled

0.17

0.20

Zero code changes; our usage avoids all renamed APIs

jsonwebtoken

9

10

Added rust_crypto backend feature (see jsonwebtoken Crypto Backend Choice)

zen-engine

0.25

0.54

Decision type no longer generic; input/output uses Variable type; ~15 lines changed across 3 files

lapin

2

4

String params → ShortString (.into() calls); tokio is default runtime in v4; ~25 lines changed across 4 files

Removed

Crate Version Rationale

serde_yaml

0.9

Deprecated by author (dtolnay, March 2024). The community fork serde_yml has a RUSTSEC advisory for unsoundness (RUSTSEC-2025-0068). Rather than adopt another YAML library, the -f yaml CLI output format was removed — JSON (-f json) and table (-f table) formats cover all use cases, and JSON is a valid YAML superset.

Deferred

Crate Current Latest Rationale

toml

0.8

1.0

toml 1.0 was released February 11, 2026 (3 weeks before this audit). Our usage is strictly from_str/to_string_pretty, so the upgrade will be trivial when 1.0 has stabilized. Revisit Q3 2026.

reqwest

0.12

0.13

reqwest 0.13 switches the default TLS crypto provider to aws-lc-rs, which requires NASM on Windows. Since CRAIG targets Windows as a development platform and does not require any 0.13-specific features, we defer until the NASM requirement is resolved upstream or we adopt NASM as a dev prerequisite. Revisit when reqwest 0.12 reaches end of support.

jsonwebtoken Crypto Backend Choice

jsonwebtoken 10 requires selecting a crypto backend: aws_lc_rs or rust_crypto.

We chose rust_crypto (RustCrypto project: rsa, sha2, p256, p384) because:

  • Pure Rust — builds on all platforms without native toolchain dependencies (no NASM, no cmake)

  • Consistent with our decision to defer aws-lc-rs adoption (see reqwest deferral above)

  • Acceptable performance for JWT validation workloads (low volume, not a hot path)

If FIPS compliance becomes a requirement, switch to aws_lc_rs which provides FIPS-validated cryptography.

zen-engine LocalPoolHandle Decision

zen-engine’s evaluate() future is !Send (uses Rc internally). The upstream documentation recommends tokio_util::task::LocalPoolHandle for multi-threaded workloads.

We retain the existing manual approach: a dedicated OS thread running a single-threaded tokio runtime, communicating via mpsc channel. This is:

  • Explicit and easy to reason about (~20 lines of code)

  • Already proven in production testing (67+ ruleset evaluation tests)

  • Does not add a tokio-util dependency

Revisit if zen-engine removes the !Send constraint in a future release.

Consequences

  • The workspace compiles and passes all tests with the upgraded dependencies

  • The serde_yaml crate is fully removed from the dependency tree

  • The CLI -f yaml output format is no longer available; users should use -f json instead

  • Two dependencies (toml, reqwest) remain pinned at older versions with documented upgrade paths

  • The jsonwebtoken crypto backend can be changed by modifying a single Cargo.toml feature flag

Edit this page · latest