Repository navigation
Description
fleet-config: HOME unset/empty falls back to "." — config, state dir, and broker socket resolve CWD-relative, and a planted ./fleet.toml loads
Evidence (verified this run, laptop primary @ a719a69)
pkgs/fleet/crates/fleet-config/src/lib.rs:198-200:
fn home_dir() -> PathBuf {
env_path("HOME").unwrap_or_else(|| PathBuf::from("."))
}home_dir() feeds Config::file_path() (lib.rs:216-224), Config::state_dir() (lib.rs:396-398), and Config::broker_socket() (lib.rs:273-291, via resolve_under_home / resolve_under). #5473 made empty XDG/FLEET_* values count as unset, but when HOME itself is unset or empty — and no absolute XDG base is set — every one of these paths becomes relative to the process's current working directory.
Probe (laptop, ~/git/fleet/probe-fleetconfig-home, real fleet-config crate as a path dependency; run from a scratch dir containing a planted ./.config/fleet/fleet.toml with [domains] planted = false; environment explicitly scrubbed):
env -u HOME -u XDG_CONFIG_HOME -u XDG_STATE_HOME -u FLEET_CONFIG -u FLEET_BROKER_SOCKET:file_path=./.config/fleet/fleet.tomlstate_dir=./.local/state/fleetbroker_socket=./.cache/laptop-agent/broker.sockConfig::load()succeeds anddomain_enabled("planted") == false— the planted CWD config was loaded (an unknown domain defaults to enabled;falsecan only come from the planted file).
HOME=(empty) with empty XDG bases: identical CWD-relative results, planted config loads.- Control (
HOME=/home/user): all paths anchor under/home/user, planted CWD config ignored.
Note: a process environment that happens to set absolute XDG_CONFIG_HOME/XDG_STATE_HOME masks the config/state paths (the broker socket has no XDG source and stays CWD-relative), which is presumably why this survived #5473's fix — that issue covered empty XDG values given a present HOME.
Why it matters
- A fleet process started without HOME (cron, a minimal systemd unit,
env -i, a container) silently reads its configuration from whoever controls its working directory — the exact planted-config hazard fleet-config: empty XDG env vars resolve to CWD-relative paths (a planted ./fleet/fleet.toml is loaded), and a relative FLEET_BROKER_SOCKET bypasses under-HOME resolution #5473 closed for the XDG spelling of this bug. - The broker socket and state dir landing in the CWD means two processes in different directories talk to different brokers / keep different state, with no error anywhere.
- Siblings, same class, different crates and different wrong anchors: atlas-search(fleet-search): HOME unset/empty resolves state/config/token paths relative to the CWD (literal ~ dir) #5640 (atlas-search / fleet-search, literal
~CWD dir) and fleet-queue(client): HOME unset/empty makes home() empty — broker socket, token, and worker signal paths all anchor at the filesystem root #5673 (fleet-queue client, filesystem root). This one is fleet-config's own copy; neither sibling covers it.
Acceptance criteria
- With HOME unset or empty (and no absolute XDG/FLEET override), fleet-config never resolves the config file, state dir, or broker socket relative to the CWD: it either resolves a real home (e.g. passwd entry) or fails loudly with an actionable error naming HOME.
- A planted
./.config/fleet/fleet.tomlin the working directory is never loaded in that environment. - Pinning tests cover HOME unset and HOME empty for
file_path,state_dir, andbroker_socket(the existing fleet-config: empty XDG env vars resolve to CWD-relative paths (a planted ./fleet/fleet.toml is loaded), and a relative FLEET_BROKER_SOCKET bypasses under-HOME resolution #5473 tests cover empty XDG with HOME present). - Behavior with HOME set is unchanged; existing fleet-config tests stay green.
Activity
developing-today commentedon Nov 5, 2026
CODE-1426
dezren39 commentedon Nov 5, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 5, 2026
🤖 Agent note · picked up
158 remaining items
dezren39 commentedon Nov 6, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 6, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 6, 2026
🤖 Agent note · PR opened; queue reconciliation pending
cargo test -p fleet-config(17 passed), and the changed fleet consumer package tests all pass. PR CI is queued.repo-queue completetimed out with a PostgREST global timeout twice; checkpoint/list/fail/health requests are also timing out. No GitHub work should be repeated. The next action is to reconcile task 9788 topr_openedwhen the queue API responds.