Binions is one Cargo workspace of pure Rust — building it is plain cargo build, and contributing to it needs only a standard Rust toolchain. This page covers the toolchain, the workspace layout, how the project is built and tested, and the continuous-integration gates that protect every change.
This is for platform contributors. End users never build from source — they
apt installsigned packages (see Installation). This section is for people working on the daemons themselves.
| Language | Rust (stable channel), pinned by a rust-toolchain.toml at the repo root |
| Minimum version | Rust 1.95 (the workspace minimum supported version) |
| Components | rustfmt, clippy, rust-src, rust-analyzer (installed automatically by the toolchain file) |
| Edition | 2021 |
| Async runtime | Tokio |
Because the toolchain is pinned in-tree, a fresh checkout plus rustup gives every contributor the exact same compiler, formatter, and linter — no per-machine drift.
One workspace holds the shared libraries and every daemon. Each daemon is its own crate that compiles to a single binary and ships as a single systemd service.
binions-src/
├── Cargo.toml # [workspace] + shared [workspace.dependencies]
├── rust-toolchain.toml # stable channel + components
├── crates/ # 5 shared libraries
│ ├── common-events/ # envelope, taxonomy, version registry
│ ├── common-redis/ # pools, key builders, stream helpers
│ ├── common-broker/ # multi-provider email/queue + storage
│ ├── common-microservice/ # the daemon framework
│ └── common-license/ # licensing
├── services/ # one directory = one daemon = one binary
│ ├── mailbox-service/ database-service/ aiinjector-service/ …
│ └── … # 13 daemons in total
└── deploy/ # ansible, systemd units, scripts, firewall, …
Shared dependencies are declared once in [workspace.dependencies] (Tokio, serde, serde_json/yaml, schemars, chrono, uuid, anyhow, thiserror, the Redis client, axum, and the OpenTelemetry OTLP exporter) and inherited by every crate, so versions stay consistent across the whole tree.
# build the whole workspace
cargo build --release
# run the full test suite (unit + property-based)
cargo test
# format and lint (the same checks CI runs)
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
Some capabilities are opt-in Cargo features to keep default builds lean — for example the broker protocols imap, mqtt and amqp. Enable them per crate when you need them.
The AsyncAPI tool. A feature-gated helper,
asyncapi-emit, prints the event-bus contract as AsyncAPI 2.6 JSON. CI uses it to detect contract drift (below); you can run it locally to inspect the contract.
Every merge request runs a pipeline of fast, fail-early gates before code can merge:
| Stage | Gate | What it protects |
|---|---|---|
| audit | cargo-deny | Known security advisories in the dependency graph |
| audit | cargo-machete | Unused dependencies (manifest hygiene) |
| schema | AsyncAPI drift | Regenerates the contract and diffs it against the committed snapshot |
| test | Workspace tests | Unit + property-based tests across all crates |
Each daemon exposes a Prometheus /metrics endpoint and exports traces over OpenTelemetry (OTLP/gRPC) to Jaeger. Because a daemon emits a synthetic boot span on startup, it appears in Jaeger from the moment it runs — even before it has handled any business traffic. Health is at /health/live and /health/ready on loopback. See Monitoring & tracing for the operator view.
The deploy/ tree holds everything that turns the binaries into a running host: Ansible playbooks, systemd unit templates, per-daemon deploy scripts, infrastructure provisioners (Redis, PostgreSQL, MinIO), the nftables firewall, logrotate, cron jobs, and reverse-proxy configuration. The released form of all of this is the signed apt packages end users install.