# Typed configuration crate and a bootstrap crate that owns all wiring Configuration was read ad hoc from `std::env` in many adapters, and the two binaries each carried hundreds of lines of adapter wiring (`wire_dependencies`, `create_event_publisher`, the worker's handler and job assembly). ADR-0005 made `composition` the single root for deps, but the binaries still named adapters themselves, and `infra-wiring` existed only so `application` could re-export an `AppConfig`. ## Decision **`config` crate.** One typed `config::AppConfig` with sections (`server`, `database`, `auth`, `events`, `nats`, `storage`, `image_conversion`, `metadata`, `federation`, `wrapup`), loaded once by the binary via `config::load()`. Layering, lowest to highest precedence: 1. built-in defaults; 2. `config.toml`, or the file named by `CONFIG_FILE` (a named file that is missing is an error); 3. environment variables, using the legacy names (`DATABASE_URL`, `PORT`, `JWT_SECRET`, ...) with no prefix. Every variable that ever worked keeps its name, meaning and default. A malformed value fails startup with an error naming the variable (`PORT=abc`). An empty or whitespace-only value is treated as unset, so the default applies (or `None` for optional fields) rather than being an error. Adapters take their section (or a typed config built from it), never raw environment strings. **`bootstrap` crate.** Replaces `composition` and `infra-wiring`. It is the only crate that names concrete adapters. It exposes `build_server(&AppConfig) -> ServerApp { router, addr }`, `build_worker(&AppConfig) -> WorkerApp { service }`, `build_server_on(&AppConfig, SqlitePool)` (the same router on a caller-provided pool, for tests) and `init_tracing`. `DbPool` and `EventBusBackend` live here. `application` keeps a small application-owned `AppConfig` / `WrapUpConfig` built from the `config` sections, so use-case deps structs and their test fixtures are unchanged, and `application` no longer pulls `sqlx` or `anyhow`. **Binaries are thin.** `server` and `worker` do dotenv, `config::load`, `init_tracing`, one `bootstrap::build_*` call and `axum::serve` / `service.run`. Their `[dependencies]` are limited to `bootstrap`, `config`, `tokio`, `axum`, `anyhow`, `dotenvy` and `tracing`; `make check-binaries-are-thin` enforces it. The `federation` and `nats` features forward to bootstrap. ## Consequences - Adding or changing an adapter touches `bootstrap` only; the binaries do not change. - The wiring is reachable from tests (`build_server_on`) without a process or a port. - `check-federation-off-social` now inspects `crates/bootstrap/src/federation.rs`: federation-off must still wire `LocalSocialService`, never social noops (ADR-0009). - Operators can move settings into `config.toml` incrementally; existing `.env` files keep working.