Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR 0002: Workspace structure and crate boundaries

Status: Accepted Date: 2026-06-16

Context

Arbitraitor spans retrieval, storage, analysis, policy, execution, plugins, receipts, updates, and CLI presentation. Clear crate boundaries enforce the security invariant that no detector, parser, or plugin can call the release or execution layer directly.

Decision

Single monorepo with 25 workspace crates under crates/:

CrateResponsibilityI/O
arbitraitor-modelSerializable domain types (newtypes, enums, structs)None
arbitraitor-coreState machine orchestrator, invariant enforcementNone
arbitraitor-policyTOML policy → internal AST → verdictPolicy files only
arbitraitor-fetchHTTP retrieval behind Fetcher traitNetwork
arbitraitor-storeContent-addressed quarantine store (CAS)Filesystem
arbitraitor-artifactContent type identification and classificationRead-only
arbitraitor-analysisDetector coordinationRead-only
arbitraitor-shellPOSIX shell / Bash / Zsh static analysisRead-only
arbitraitor-powershellPowerShell static analysisRead-only
arbitraitor-yaraxYARA-X in-process scanningRead-only
arbitraitor-avClamAV / Defender adaptersSubprocess
arbitraitor-archiveArchive extraction under resource limitsFilesystem
arbitraitor-intelIntelligence feed matchingLocal files
arbitraitor-provenanceDigest pinning, signature verificationCrypto + subprocess
arbitraitor-execMediated execution brokerProcess spawning
arbitraitor-sandboxPlatform isolation adaptersPlatform APIs
arbitraitor-receiptReceipt creation, signing, queryFilesystem
arbitraitor-updateTUF-style signed update channelNetwork
arbitraitor-plugin-apiPlugin ABI types, WIT definitionsNone
arbitraitor-plugin-hostWasmtime host + subprocess fallbackSubprocess + WASM
arbitraitor-wrapperDownloader argument translationNone
arbitraitor-package-managerHomebrew / Arch lifecycle mediationSubprocess
arbitraitor-cliArgument parsing and presentation onlyTerminal
arbitraitor-testkitTest fixtures, mock servers, generatorsTest-only
arbitraitor-mcpMCP server for AI agent gatewayNetwork

Boundary rules:

  1. arbitraitor-model contains serializable domain types and no I/O.
  2. arbitraitor-core owns state transitions and invariants, not presentation.
  3. arbitraitor-fetch knows networking but not policy syntax.
  4. arbitraitor-policy consumes normalized facts and produces decisions only.
  5. arbitraitor-cli performs argument parsing and presentation only.
  6. Platform-specific code lives behind traits in dedicated modules.
  7. Plugin ABI types live in arbitraitor-plugin-api and WIT definitions.
  8. No detector may call the release or execution layer directly.
  9. No wrapper plugin may directly perform network I/O unless a narrowly documented mode requires it.

Publishing: most crates use publish = false. Only the CLI and (later) the plugin SDK will be published before 1.0.

Consequences

  • Compile-time enforcement of dependency direction (Cargo cannot prevent all cycles, but the boundary rules create clear review checkpoints).
  • unsafe_code = "forbid" in core policy, receipt, model, and state-machine crates. Required unsafe isolated in platform/FFI crates.
  • Cross-crate communication uses typed domain types from arbitraitor-model, never raw strings for hashes, URLs, paths, or policy IDs.

Alternatives considered

  • Multi-repo: Rejected for pre-1.0. Makes atomic security changes, versioning, and cross-platform CI harder.
  • Fewer, larger crates: Rejected. Weakens boundary enforcement and makes parallel development harder.
  • Dynamic plugin ABI (.so/.dylib/.dll): Rejected. Equivalent to core compromise. Plugins use Wasmtime or subprocess protocol only.

References

  • docs/spec/tech-stack.md §3 (Workspace and crate boundaries)
  • docs/spec/spec.md §38.1 (Rust workspace layout)
  • Cargo.toml workspace members