# M5a task 16: the gate passes on macOS as well as on Linux **Branch:** `m5a` (run `git switch m5a`; `git status --short` must be empty, otherwise stop) **Commit subject:** `gate: pass on macOS: tests use /tmp, gatewayd finds its uid without /proc` ## Goal Work moved to titan, a Mac, on 2026-09-24. There `make gate` fails although the code is right, because three places assume Linux. The harness itself still runs on straylight (Linux); this task only makes the gate pass on both. No behaviour change on Linux, and no new test. 1. **Unix socket paths are too long.** Tests put sockets under `std::env::temp_dir()`. On macOS that is `/var/folders/…/T/`, about 50 bytes, and a socket's whole path may be at most 104 bytes there, so some tests' daemons cannot bind (for example brokerd's `serve_runner.rs` and gatewayd's `serve_restart.rs`). A new `.cargo/config.toml` sets `TMPDIR=/tmp` for every process Cargo runs, tests included. 2. **`gatewayd` reads `/proc/self`** for the user id it runs as, when it checks a secret file's owner. macOS has no `/proc`. `std` has no call for the user id, and `unsafe` (for `libc`) is not allowed, so a new function `user_id` takes the owner of a pipe the process has just made, which is the user the process runs as on Linux and on macOS (checked on both: 1000 on talos, 501 on titan, the same as `id -u`). 3. **`toolkit`'s `shell.rs` test** expects `pwd` to print `/tmp`; on macOS `/tmp` is a link to `/private/tmp`, and `pwd` prints the resolved path. A new version of that given test compares with the resolved path. ## Files - Create: `.cargo/config.toml` (at the repository root, next to `Cargo.toml`) - Copy: a **new version** of the given `crates/toolkit/tests/shell.rs`, from `docs/plans/M5a/files/crates/toolkit/tests/shell.rs` - Modify: `crates/gatewayd/src/secrets.rs`, `docs/implementer-log.md` ## The changes, exactly **1. Create `.cargo/config.toml`** with exactly this content: ```toml # Tests put Unix sockets under `std::env::temp_dir()`. macOS's is long (/var/folders/…/T/), and a # socket's path there can pass the 104 bytes macOS allows, so every process Cargo runs, tests # included, uses /tmp. [env] TMPDIR = { value = "/tmp", force = true } ``` **2. `crates/gatewayd/src/secrets.rs`**, in `read_checked`. Nothing else in the file changes. **a.** In the comment, the line ```rust // on `named`): the uid of "/proc/self"; " is not owned by the user gatewayd runs as"; ``` becomes ```rust // on `named`): the uid of `user_id()`; " is not owned by the user gatewayd runs as"; ``` **b.** The three lines ```rust let owner = std::fs::metadata("/proc/self") .map_err(|e| format!("cannot read /proc/self: {}", e))? .uid(); ``` become the one line ```rust let owner = user_id()?; ``` **c.** Insert this function immediately above the line `/// The text without one trailing newline; not empty; UTF-8.` (the doc comment of `value`), with one blank line between them: ```rust /// The user id this process runs as: the owner of a pipe it has just made. `std` has no call for /// it, and `/proc/self` is Linux only. fn user_id() -> Result { let (reader, _writer) = std::io::pipe().map_err(|e| format!("cannot make a pipe: {e}"))?; let pipe = std::fs::File::from(std::os::fd::OwnedFd::from(reader)); let meta = pipe .metadata() .map_err(|e| format!("cannot read a pipe: {e}"))?; Ok(meta.uid()) } ``` No `use` line changes: `MetadataExt` (for `.uid()`) is already imported, and the rest is named in full. ## Steps - [ ] **1. Create `.cargo/config.toml`**, then copy the test: `cp docs/plans/M5a/files/crates/toolkit/tests/shell.rs crates/toolkit/tests/` - [ ] **2. Make the three edits to `secrets.rs`.** Run `cargo fmt --all`. - [ ] **3. Run the tests.** `cargo test -p gatewayd -p toolkit -p brokerd`: every suite passes. - [ ] **4. Run the gate.** `make gate`. Expected last line: `gate: ok`, with 936 tests, the same as before this task. On macOS it failed before this task, with 8 tests failing; now it passes. - [ ] **5. Log and commit.** `git add .cargo/config.toml crates/gatewayd crates/toolkit docs/implementer-log.md && git commit` ## Done when - `make gate` prints `gate: ok` with 936 tests. ## Stop and report if - Any line quoted above is not in the file exactly as shown. - `cargo-deny` is missing (`error: no such command: deny`): report it, do not install anything. - Any test fails after the changes. Do not change a test.