Skip to content

fleet-config: a relative XDG_CONFIG_HOME / XDG_STATE_HOME is used verbatim — config and state resolve CWD-relative and a planted fleet.toml loads even with HOME set #6396

Closed

Description

@dezren39

fleet-config: a relative XDG_CONFIG_HOME / XDG_STATE_HOME is used verbatim — config and state resolve CWD-relative and a planted ./fleet.toml loads even with HOME set

Summary

fleet-config treats an empty XDG base as invalid (#5473), but a non-empty relative XDG base is used verbatim. The XDG Base Directory specification requires relative values in these variables to be considered invalid and ignored. As a result, with HOME set correctly, XDG_CONFIG_HOME=relcfg makes the config path relcfg/fleet/fleet.toml — relative to the process's current working directory — and Config::load() loads a fleet.toml planted in the working directory. XDG_STATE_HOME relative likewise puts the state dir (and the materialized shims dir under it) in the CWD.

This is a distinct trigger from the two filed siblings: #5473 (closed) covered empty XDG values; #5737 (open) covers HOME unset/empty falling back to ".". Neither covers a non-empty relative XDG base with HOME present and correct.

Evidence (file:line, origin/main @ 967fb22; pkgs/fleet unchanged between laptop HEAD and origin/main)

  • pkgs/fleet/crates/fleet-config/src/lib.rs:211-223 — the crate's own comment: "the XDG base-directory spec treats an empty base as invalid; taking one literally here would turn the config file, the state dir, and the broker socket into CWD-relative paths (issue 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)". non_empty_path filters only the empty case; env_path returns any non-empty value, relative included.
  • pkgs/fleet/crates/fleet-config/src/lib.rs:252-263 — file_path_from: let base = xdg_config_home.unwrap_or_else(|| home.join(".config")); base.join("fleet").join("fleet.toml") — a relative base stays relative.
  • pkgs/fleet/crates/fleet-config/src/lib.rs:442-445 — state_dir_from has the same shape for XDG_STATE_HOME; shims_dir() is state_dir()/shims.
  • The XDG spec (Base Directory Specification): "If an implementation encounters a relative path in any of these variables it should consider the path invalid and ignore it."

Verification (this run, laptop, real fleet-config crate)

Probe ~/git/fleet/probe-fleet-config-xdg-rel (path-depends on the real fleet-config crate; run from a scratch dir containing a planted relcfg/fleet/fleet.toml with [domains] planted = false):

  • HOME=/home/user XDG_CONFIG_HOME=relcfg XDG_STATE_HOME=relstate (FLEET_CONFIG unset):
    • file_path=relcfg/fleet/fleet.toml
    • state_dir=relstate/fleet
    • planted_enabled=false — the planted CWD config was loaded (an unknown domain defaults to enabled; false can only come from the planted file)
    • queue_enabled=true (control domain untouched)
  • Control, absolute XDG bases: paths anchor at the given absolute dirs; planted file ignored (planted_enabled=true).
  • Control, no XDG vars: file_path=/home/user/.config/fleet/fleet.toml, state_dir=/home/user/.local/state/fleet; planted file ignored.

Why it matters

Acceptance criteria

Activity

  1. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/fleetpkgs/fleet multicall binary + platform crates
    on Nov 5, 2026
  3. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  5. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  6. 62 remaining items

  7. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  8. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  9. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 6, 2026
  10. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/fleetpkgs/fleet multicall binary + platform crateskind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:donetask/fixhas a fix task queuedtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions