Files
boxmaker/docs/plans/M3b/01-proto-tools-hosts.md
T
kyleandClaude Opus 5.5 b426ca1958 Specify and plan M3b: the runner and the tools
A draft spec for the owner's review and 13 offline tasks with their given
tests: shared tool arguments and host rules in proto, the sealed fetch
target (M3a finding 14), the toolkit tools and SOCKS5 egress proxy, and
brokerd's [runner], podman argument lists, runtime and proxy lifecycle. Each
task's tests were run against a reference at that task's end state (560 to
638 tests, clippy clean); the reference is not in the repository. Adds the
runner-unavailable runbook entry and tip T23 (ETXTBSY in script tests).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:29:27 -07:00

4.0 KiB

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):

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<String>,
}
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):

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:

/// 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.