Summary#
- Adds `Config` struct to the `common` crate (serde-deserializable from TOML) with v0.1 fields: `bind_address`, `port`, `data_dir`,
`database_url`, `public_url`, and empty stub sections `[blobs]`, `[oauth]`, `[iroh]`
- `EZPDS_*` env var overrides (prefix: `EZPDS_`) applied on top of TOML via pure `apply_env_overrides` — no I/O in the Functional Core
- Relay binary gains `--config`/`EZPDS_CONFIG` CLI arg (clap), loads config on startup, fails fast with clear error message on invalid
config; logging via `RUST_LOG`-aware `EnvFilter`
- 13 tests: TOML parsing, env var overrides, missing required field errors, I/O and parse error paths
## Architecture notes
FCIS pattern applied:
- `config.rs` — **Functional Core**: `Config`, `RawConfig`, `ConfigError`, `apply_env_overrides` (takes explicit env `HashMap`),
`validate_and_build`
- `config_loader.rs` — **Imperative Shell**: `load_config` (reads file + real env), `load_config_with_env` (`pub(crate)` for test
isolation)
- `relay/src/main.rs` — **Imperative Shell**: CLI parsing, config loading, structured logging
## Test plan
- [ ] `cargo test --workspace` — 13 tests pass, 0 failures
- [ ] `cargo clippy --workspace -- -D warnings` — no warnings
- [ ] `cargo fmt --all --check` — clean
- [ ] `cargo build --package relay` — builds successfully
- [ ] Manual smoke test: run `./target/debug/relay --config /nonexistent.toml` and confirm error message is `error: failed to load
config from /nonexistent.toml: failed to read config file: No such file or directory (os error 2)`
- [ ] Manual smoke test: create a minimal `relay.toml` with `data_dir` and `public_url`, run `./target/debug/relay` and confirm
structured log line at startup
Closes MM-69