The work moved to titan (macOS), where the gate failed for reasons older than M5a: sockets under macOS's long TMPDIR pass its 104-byte limit, gatewayd reads /proc/self for its uid, and /tmp is /private/tmp. Task 16 sets TMPDIR=/tmp for every process Cargo runs (.cargo/config.toml [env]), has gatewayd take its uid from the owner of a pipe it makes (no dependency, no unsafe), and hands over a toolkit shell.rs that compares resolved paths. On a scratch tree the gate passes on titan and on talos with 936 tests, and a wrong uid fails 7 gatewayd tests. Tasks 16 to 19 are renumbered 17 to 20. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.4 KiB
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.
- 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'sserve_runner.rsand gatewayd'sserve_restart.rs). A new.cargo/config.tomlsetsTMPDIR=/tmpfor every process Cargo runs, tests included. gatewaydreads/proc/selffor the user id it runs as, when it checks a secret file's owner. macOS has no/proc.stdhas no call for the user id, andunsafe(forlibc) is not allowed, so a new functionuser_idtakes 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 asid -u).toolkit'sshell.rstest expectspwdto print/tmp; on macOS/tmpis a link to/private/tmp, andpwdprints 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 toCargo.toml) - Copy: a new version of the given
crates/toolkit/tests/shell.rs, fromdocs/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:
# 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
// on `named`): the uid of "/proc/self"; "<path> is not owned by the user gatewayd runs as";
becomes
// on `named`): the uid of `user_id()`; "<path> is not owned by the user gatewayd runs as";
b. The three lines
let owner = std::fs::metadata("/proc/self")
.map_err(|e| format!("cannot read /proc/self: {}", e))?
.uid();
become the one line
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:
/// 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<u32, String> {
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. Runcargo 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 gateprintsgate: okwith 936 tests.
Stop and report if
- Any line quoted above is not in the file exactly as shown.
cargo-denyis missing (error: no such command: deny): report it, do not install anything.- Any test fails after the changes. Do not change a test.