ADR-001: Rust Monorepo
On this page
Context
CRAIG requires multiple independent services (rules, cases, placement, exchange, web UI, CLI) that share common patterns for authentication, database access, messaging, and API scaffolding. We needed to choose between a polyrepo (one repository per service) and a monorepo (all services in one repository).
Decision
Use a Cargo workspace monorepo with shared crates and independent service binaries.
The workspace has grown to 63 members (as of 2026-08; the living inventory is Shared Crates & Workspace Inventory), including:
-
shared crates (
craig-common,craig-auth,craig-db,craig-mq,craig-api,craig-store,craig-test-lib,craig-reference,craig-intake-sdk,craig-crypto, …) -
9 API services (
craig-rules,craig-cases,craig-placement,craig-exchange,craig-financial,craig-reporting,craig-security,craig-intake,craig-composition) -
1 web BFF (
craig-web), 1 CLI (craig-cli) -
tools (
craig-seed,mock-server, …) and thextasktask runner
Rationale
-
Shared code is first-class: Authentication, error handling, pagination, and telemetry are shared crates with workspace-level version pinning. Changes propagate instantly to all consumers.
-
Atomic refactoring: Cross-cutting changes (e.g., updating the auth middleware or pagination format) can be made in a single commit across all services.
-
Unified CI: One pipeline tests, lints, and builds everything. Dependency caching via
Cargo.lockhash. -
Rust edition 2024: The entire workspace uses the same edition, MSRV, and dependency versions.
-
Simplified Docker builds: A single multi-stage Dockerfile builds all service binaries in one
cargo buildinvocation, maximizing layer caching.
Consequences
-
All services must use compatible dependency versions (enforced by workspace dependency inheritance).
-
CI runs the full test suite on every push — acceptable given the fast Rust compilation with incremental builds and caching.
-
Developers need the full repository cloned to work on any service.