# M4a task 03: `gatewayd.toml` **Branch:** `m4a` (run `git switch m4a`; `git status --short` must be empty, otherwise stop) **Commit subject:** `gatewayd: config, gatewayd.toml into a checked Config` ## Goal `gatewayd.toml` says where Mattermost is, where the token comes from, who may talk to Boxmaker and in which channels, and a few limits. It is **our** format: an unknown key anywhere is an error, and a value that is wrong is refused at start with a message that names it. Spec section 3. ```toml [mattermost] url = "https://straylight.scylla-hammerhead.ts.net" # https or http; no path ca_file = "/etc/boxmaker/extra-ca.pem" # optional; added to the system's roots [secrets.mattermost_token] credential = "mattermost-token" # exactly one of: credential, env, file [allow] users = ["abcdefghijklmnopqrstuvwxyz"] # Mattermost user ids (26 characters) channels = [] # channels and group messages allowed, by id; default none [loop] socket = "" # empty: /run/loop/loop.sock [paths] home = "/var/lib/boxmaker" # default: BOXMAKER_HOME, then /var/lib/boxmaker [limits] queue = 20 typing_every_ms = 3000 ping_every_ms = 30000 dead_after_ms = 60000 ``` ## Files - Copy: `crates/gatewayd/tests/config.rs`, `crates/gatewayd/tests/support/tmp.rs`, and the skeleton `crates/gatewayd/src/config.rs` - Modify: `crates/gatewayd/src/lib.rs` (`pub mod config;`), `docs/implementer-log.md` ## The skeleton Every type is written, with its serde attributes: `Config`, `MattermostConfig`, `SecretSpec`, `SecretSource`, `AllowConfig`, `LoopConfig`, `Paths`, `Limits` (with their defaults), `ServerUrl`, `ConfigError`, and the constant `MATTERMOST_TOKEN = "mattermost_token"`. Do not change them. The functions are `todo!()`, each with its steps above it. ## The messages, exactly `Config::problem` returns the first problem, in this order: | Problem | Message | |---|---| | `url` fails `parse_url` | `parse_url`'s message: `[mattermost] url "" must be http:// or https://, a host, an optional port, and nothing else` (the url with `{:?}`) | | `ca_file` not absolute | `[mattermost] ca_file "" must be an absolute path` (`{:?}`) | | no `[secrets.mattermost_token]` | `[secrets.mattermost_token] is missing` | | a secret whose `source()` fails | `[secrets.] ` | | `allow.users` empty | `[allow] users is empty: a gateway that answers nobody is a mistake` | | an id in `allow.users` or `allow.channels` that is not `valid_id` | `[allow] "" is not a Mattermost id (26 characters of a-z and 0-9)` (`{:?}`) | | a limit that is 0 (checked in the order queue, typing_every_ms, ping_every_ms, dead_after_ms) | `[limits] must be at least 1` | `SecretSpec::source`'s messages: | Case | Message | |---|---| | not exactly one of the three | `needs exactly one of credential, env and file` | | `credential` empty or with a byte that is not an ASCII letter, digit, `_`, `.` or `-` | `credential "" is not a credential name (letters, digits, _ . -)` | | `env` empty or with a byte that is not `A-Z`, `0-9` or `_` | `env "" is not a variable name (A-Z, 0-9, _)` | | `file` not absolute | `file "" must be an absolute path` | `Config::token_source` gives `source()` of `mattermost_token`, or `[secrets.mattermost_token] is missing`. `ConfigError`'s `Display` is `: `. ## Steps - [ ] **1. Copy.** `git switch m4a`, then `mkdir -p crates/gatewayd/tests/support && cp docs/plans/M4a/files/crates/gatewayd/tests/config.rs crates/gatewayd/tests/ && cp docs/plans/M4a/files/crates/gatewayd/tests/support/tmp.rs crates/gatewayd/tests/support/ && cp docs/plans/M4a/files/crates/gatewayd/src/config.rs crates/gatewayd/src/`. Add `pub mod config;` to `crates/gatewayd/src/lib.rs`. - [ ] **2. See it fail.** `cargo test -p gatewayd --test config`. Expected: it compiles and 7 tests fail with `not yet implemented`. - [ ] **3. Fill the functions one at a time**: `valid_id`, `parse_url`, `SecretSpec::source`, `ConfigError`'s `fmt`, then the `Config` methods. `cargo check -p gatewayd` after each. - [ ] **4. See it pass.** `cargo test -p gatewayd --test config`. Expected: 7 passed. - [ ] **5. Run the gate.** `cargo fmt --all`, then `make gate`. Expected last line: `gate: ok`. - [ ] **6. Log and commit.** `git add crates/gatewayd docs/implementer-log.md Cargo.lock && git commit` ## Done when - `cargo test -p gatewayd --test config` passes; `make gate` prints `gate: ok`. ## Stop and report if - A test wants a type changed. The types are the format; report instead.