# M3b task 01: the tools' arguments and the host rules move to `proto` **Branch:** `m3b` (create it: `git switch master && git switch -c m3b`; `git status --short` must be empty first, otherwise stop) **Commit subject:** `Move the tools' arguments and the host rules to proto` ## Goal Two programs will now read the same things: `brokerd` parses the model's tool arguments and checks hosts, and `toolkit` (inside the container) reads the same arguments and checks the same hosts. Each must have **one** definition. Move them into `proto`; `brokerd` uses them from there. Nothing changes in behaviour: every existing test passes unchanged. ## Files - Copy: `crates/proto/tests/tools.rs`, `crates/proto/tests/hosts.rs` - Create: `crates/proto/src/tools.rs`, `crates/proto/src/hosts.rs` - Modify: `crates/proto/src/lib.rs`, `crates/brokerd/src/args.rs`, `docs/implementer-log.md` ## Interfaces `crates/proto/src/tools.rs` (module doc: the four tools' arguments, shared by `brokerd` and `toolkit`): ```rust use serde::{Deserialize, Serialize}; // Each: #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct ReadFileArgs { pub path: String } pub struct WriteFileArgs { pub path: String, pub content: String } pub struct ShellArgs { pub command: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub cwd: Option, } pub struct HttpFetchArgs { pub url: String } ``` These are the four private structs at the bottom of `brokerd/src/args.rs` today (`ReadFileArgs`, `WriteFileArgs`, `ShellArgs`, `HttpFetchArgs`), made public, with `Debug, Clone, PartialEq, Eq` added. **Move** them: delete them from `args.rs` and `use proto::tools::{…}` there instead. `crates/proto/src/hosts.rs` (module doc: host names and patterns, shared by `brokerd` and the egress proxy): ```rust pub fn valid_host(host: &str) -> bool; pub fn valid_host_pattern(pattern: &str) -> bool; pub fn host_matches(pattern: &str, host: &str) -> bool; fn valid_label(label: &str) -> bool; // private, as it is now ``` **Move** these four functions from `brokerd/src/args.rs`, bodies and doc comments unchanged. In `args.rs`, where they were, put: ```rust /// Moved to `proto::hosts` in M3b, so `toolkit` checks hosts with the same rules. pub use proto::hosts::{host_matches, valid_host, valid_host_pattern}; ``` so that `brokerd::args::valid_host` and the others still exist for `brokerd`'s code and tests. `url_host`, `valid_path`, `inside` and `MAX_URL` stay in `args.rs`. In `crates/proto/src/lib.rs`: add `pub mod hosts;` and `pub mod tools;` in alphabetical order with the other `pub mod` lines. No `pub use` for them: callers write `proto::tools::ShellArgs` and `proto::hosts::host_matches`. `args.rs` no longer needs `use serde::{Deserialize, Serialize};` once the structs are gone; remove it if the compiler says it is unused. ## Steps - [ ] **1. Branch and copy.** `git switch master && git switch -c m3b`, then `cp docs/plans/M3b/files/crates/proto/tests/tools.rs docs/plans/M3b/files/crates/proto/tests/hosts.rs crates/proto/tests/` - [ ] **2. See them fail.** `cargo test -p proto --test tools --test hosts`. Expected: they do not compile (`proto::tools` and `proto::hosts` do not exist). - [ ] **3. Move the code** as above. Run `cargo fmt --all`. - [ ] **4. See them pass.** `cargo test -p proto --test tools --test hosts`. Expected: 3 and 3 passed. Then `cargo test -p brokerd --test args --test grants --test policy`: all pass, unchanged. - [ ] **5. Check nothing is defined twice.** `grep -rn "fn valid_host\|struct ShellArgs" crates/` must show only `crates/proto/src/`. - [ ] **6. Run the gate.** `make gate`. Expected last line: `gate: ok`. - [ ] **7. Log and commit.** Add your row to `docs/implementer-log.md`, then `git add crates/proto crates/brokerd docs/implementer-log.md && git commit` ## Done when - Both new suites pass, every existing suite passes, `make gate` prints `gate: ok`. ## Stop and report if - A given test needs a change to pass. - An existing test fails after the move.