[Post-v0.1/P2] Make the macOS daemon endpoint independent of SSH TMPDIR #41

Open
opened 2026-09-03 16:30:52 +09:00 by natsukium · 4 comments
Owner

現状

  • macOS で daemon socket は ${TMPDIR}/felis.<uid>/ 配下(local_socket::resolve_local_socket)。GUI セッションの TMPDIRgetconf DARWIN_USER_TEMP_DIR 由来だが、SSH ログインの TMPDIR は未設定で /tmp にフォールバックする。結果、felis --host mac で SSH 経由の daemon と GUI の daemon が別 socket(別 daemon)になる。
  • 現行の mitigation はドキュメントのみ: how-to/attach-over-ssh.md "Attaching to a Mac: give the SSH login a TMPDIR" で export TMPDIR=$(getconf DARWIN_USER_TEMP_DIR).zshrc に書けと案内。
  • XDG_RUNTIME_DIR (Linux) も同様に SSH セッションで未設定になり得るが、felis はフォールバックで ~/.local/state 等を使うため二重化は起きにくい。macOS の TMPDIR だけが顕在化。
  • daemon 自体は起動時に socket パスをログするが、"二つの daemon が走っている" 自体は検出されない。doctordaemon 行は手元の daemon しか見ない。

問い(1.0 でしか変えられない)

socket 導出を TMPDIR 依存のまま凍結するか? 1.0 で決定的な場所($HOME 起点)に直すか?

破壊的変更案

  • 案A: socket を $HOME 起点に移す。 ~/.felis/daemon.sock または ~/Library/Application Support/felis/daemon.sock に統一。TMPDIR/XDG_RUNTIME_DIR の有無に依存しない。既存の TMPDIR 依存は deprecated としてフォールバックで読むが、新規は $HOME 起点のみ。local_socket::resolve_local_socketdocs/reference/cli.md "--socket" デフォルト表を同時更新。
  • 案B: TMPDIR 未設定時に警告/エラーで止める。 daemon 起動時と felis --host の relay 接続時に TMPDIR が空なら tracing::warn + doctordaemon 行で warn を出す。how-to/attach-over-ssh.md の手動 export を必須化ではなく検出可能に。
  • 案C: daemon 自身が二重起動を検出。 起動時に ~/Library/Application Support/felis/daemon.sock${TMPDIR}/felis.<uid>/daemon.sock の両方をチェックし、既存 daemon が見つかればそちらを案内して exit 2。--socket 明示時は対象外。

判定基準

  • macOS ユーザが ~/.ssh/configHost macForwardAgent yes だけを書いた状態で、felis --host mac とローカルの felis が同一 daemon(同一 daemon statussessions 行)を見に行くこと。
  • reference/cli.md "--socket" のデフォルト表と explanation/architecture/daemon-client-split.md の daemon 配置記述が、実装の resolve_local_socket と一致していること。
  • 1.0 後に socket パスを変えると既存セッションが orphan になるため、1.0 で決める必要があること(本レビュー前提: 互換性無視で今しか変えられない)。

対象ファイル

  • crates/felis-client-core/src/local_socket.rs, crates/felis-daemon/src/main.rs (--socket 既定), crates/felis-daemon/src/serve.rs, docs/reference/cli.md, docs/how-to/attach-over-ssh.md, docs/explanation/architecture/daemon-client-split.md, docs/explanation/architecture/ipc.md

cc @natsukium

## 現状 - macOS で daemon socket は `${TMPDIR}/felis.<uid>/` 配下(`local_socket::resolve_local_socket`)。GUI セッションの `TMPDIR` は `getconf DARWIN_USER_TEMP_DIR` 由来だが、SSH ログインの `TMPDIR` は未設定で `/tmp` にフォールバックする。結果、`felis --host mac` で SSH 経由の daemon と GUI の daemon が別 socket(別 daemon)になる。 - 現行の mitigation はドキュメントのみ: `how-to/attach-over-ssh.md` "Attaching to a Mac: give the SSH login a TMPDIR" で `export TMPDIR=$(getconf DARWIN_USER_TEMP_DIR)` を `.zshrc` に書けと案内。 - `XDG_RUNTIME_DIR` (Linux) も同様に SSH セッションで未設定になり得るが、felis はフォールバックで `~/.local/state` 等を使うため二重化は起きにくい。macOS の `TMPDIR` だけが顕在化。 - daemon 自体は起動時に socket パスをログするが、"二つの daemon が走っている" 自体は検出されない。`doctor` の `daemon` 行は手元の daemon しか見ない。 ## 問い(1.0 でしか変えられない) socket 導出を `TMPDIR` 依存のまま凍結するか? 1.0 で決定的な場所(`$HOME` 起点)に直すか? ## 破壊的変更案 - **案A: socket を `$HOME` 起点に移す。** `~/.felis/daemon.sock` または `~/Library/Application Support/felis/daemon.sock` に統一。`TMPDIR`/`XDG_RUNTIME_DIR` の有無に依存しない。既存の `TMPDIR` 依存は deprecated としてフォールバックで読むが、新規は `$HOME` 起点のみ。`local_socket::resolve_local_socket` と `docs/reference/cli.md` "--socket" デフォルト表を同時更新。 - **案B: `TMPDIR` 未設定時に警告/エラーで止める。** daemon 起動時と `felis --host` の relay 接続時に `TMPDIR` が空なら `tracing::warn` + `doctor` の `daemon` 行で `warn` を出す。`how-to/attach-over-ssh.md` の手動 `export` を必須化ではなく検出可能に。 - **案C: daemon 自身が二重起動を検出。** 起動時に `~/Library/Application Support/felis/daemon.sock` と `${TMPDIR}/felis.<uid>/daemon.sock` の両方をチェックし、既存 daemon が見つかればそちらを案内して exit 2。`--socket` 明示時は対象外。 ## 判定基準 - macOS ユーザが `~/.ssh/config` に `Host mac` と `ForwardAgent yes` だけを書いた状態で、`felis --host mac` とローカルの `felis` が同一 daemon(同一 `daemon status` の `sessions` 行)を見に行くこと。 - `reference/cli.md` "--socket" のデフォルト表と `explanation/architecture/daemon-client-split.md` の daemon 配置記述が、実装の `resolve_local_socket` と一致していること。 - 1.0 後に socket パスを変えると既存セッションが orphan になるため、1.0 で決める必要があること(本レビュー前提: 互換性無視で今しか変えられない)。 ## 対象ファイル - `crates/felis-client-core/src/local_socket.rs`, `crates/felis-daemon/src/main.rs` (`--socket` 既定), `crates/felis-daemon/src/serve.rs`, `docs/reference/cli.md`, `docs/how-to/attach-over-ssh.md`, `docs/explanation/architecture/daemon-client-split.md`, `docs/explanation/architecture/ipc.md` cc @natsukium
natsukium changed title from [v0.1/SSH Review] macOS TMPDIR 非共有による daemon 二重起動 to [Post-v0.1/P2] Make the macOS daemon endpoint independent of SSH TMPDIR 2026-09-03 16:57:30 +09:00
Author
Owner

Triaged to post-v0.1/P2. The duplicate-daemon behavior is a valid macOS lifecycle bug, but v0.1.0 claims support only for x86_64-linux; changing the default endpoint must not block that tag. The implementation issue remains open because changing it after macOS support is claimed could orphan live sessions.

Triaged to post-v0.1/P2. The duplicate-daemon behavior is a valid macOS lifecycle bug, but v0.1.0 claims support only for `x86_64-linux`; changing the default endpoint must not block that tag. The implementation issue remains open because changing it after macOS support is claimed could orphan live sessions.
Author
Owner

Triage plan (2026-09-03)

Source-grounded triage against main at 69076d42, reviewed through seven rounds of an independent reviewer (pi sol/luna) until it passed with no findings. The dependency order that supersedes the tracker's is posted on #12. Where a "Review amendments" section below conflicts with an earlier section, the amendment is the decision.

Claim check

The bug is real and reproducible from the source; one supporting claim about Linux is wrong.

  • Socket derivation: crates/felis-transport/src/socket.rs:28-48. On macOS SocketPath::resolve goes unconditionally to tmpdir_fallback(uid, $TMPDIR) (:29-31), which is ${TMPDIR:-/tmp}/felis.<uid>/daemon.sock (:39-47). On Linux it first tries directories::ProjectDirs::runtime_dir() (i.e. $XDG_RUNTIME_DIR/felis) and then the same TMPDIR fallback (:32-37).
  • So the issue's statement that Linux "falls back to ~/.local/state etc." is wrong: an SSH login without XDG_RUNTIME_DIR gets /tmp/felis.<uid> on Linux too. It rarely manifests because pam_systemd sets XDG_RUNTIME_DIR for SSH logins on systemd hosts, but the fix should not be macOS-only in its reasoning.
  • Resolution order: crates/felis-client-core/src/local_socket.rs:25-33 (--socket, then FELIS_SOCKET, then the platform default), documented at docs/reference/cli.md:602-612. The remote side of --host is felis-daemon relay, which resolves default_socket_path() in its own (sshd-provided) environment (crates/felis-daemon/src/main.rs:89-96) and autospawns felis-daemon serve --socket <that path> (relay.rs:103-117). A GUI-launched daemon resolves against the launchd TMPDIR. Two paths, two daemons — confirmed.
  • Mitigation is doc-only: docs/how-to/attach-over-ssh.md:176-183. Confirmed. doctor dials only the resolved target (crates/felis-cli/src/cli_doctor.rs:128-160) and DaemonStatus (connector.rs:683-690) carries no endpoint, so a second daemon is invisible — confirmed.
  • The rationale for 0700 dir / 0600 socket / "pathname sockets under the user's runtime dir" is at docs/explanation/security-model.md:267-290; no macOS-specific placement rationale is recorded anywhere, so the current TMPDIR choice is an undocumented default rather than a decision.
  • The tracker comment on the issue already answered the "1.0 or never" framing: v0.1.0 claims only x86_64-linux (docs/how-to/install.md:143-148: aarch64-darwin "Nothing runs on macOS"), so the macOS default endpoint is not part of any compatibility promise the tag makes.

Verdict

defer (keep post-v0.1.0, P2) — with a hard gate the label set should carry: this must land before the first release that claims macOS support, because that release is the one after which moving the default orphans live sessions. Deferral past v0.1.0 costs nothing: the freeze boundary lists "documented environment variables", and TMPDIR is an OS variable felis merely consumes; cli.md:602 documents the resolution order, not the macOS path. #12's "Contract freeze boundary" does not mention the endpoint default, and it should not be added.

Recommend option A in a specific form, plus a slice of C for observability; reject B as the primary fix (a warning still leaves two daemons).

Approach

  1. Derive the macOS runtime dir without the environment. Use confstr(_CS_DARWIN_USER_TEMP_DIR) — the same per-user, mode-0700 directory launchd puts in TMPDIR (getconf DARWIN_USER_TEMP_DIR is its shell spelling), stable across GUI and SSH logins, and a runtime location rather than a persistent one (~/Library/Application Support is backed up/synced and is where config.toml already lives, install.md:58; sockets do not belong there). Order on macOS becomes --socketFELIS_SOCKETconfstr dir → $TMPDIR/tmp. This keeps the GUI-side path identical to today (launchd's TMPDIR is that directory), so no existing GUI session is orphaned; only the SSH-side daemons move, and those are the ones the bug created. confstr is one libc FFI call in felis-transport, which already carries an audited #[allow(unsafe_code)] site for getpeereid (CLAUDE.md "Workspace policy"; felis-transport/Cargo.toml:28-37 already depends on libc for the same reason) — add it beside that one with a // SAFETY: comment.
  2. Linux: same shape, cheaper — when XDG_RUNTIME_DIR is unset, probe /run/user/<uid> before the TMPDIR fallback. Optional; it closes the same class of bug the issue mis-described.
  3. Observability (option C, read-only): doctor's daemon row also connect-probes the legacy path(s) (${TMPDIR:-/tmp}/felis.<uid>/daemon.sock when it differs from the resolved one) and reports "a second daemon is serving " as a warn row, reusing the probe serve already uses to avoid stealing a live socket (security-model.md:288-300). No exit-2, no automatic takeover: a live daemon with sessions must never be unlinked (same rule). felis-daemon serve logs the resolved dir at startup already; add the derivation source (confstr/TMPDIR/fallback) to that line.
  4. Docs: docs/reference/cli.md:602-612 (the default per platform, now stated), docs/how-to/attach-over-ssh.md:176-183 (delete the TMPDIR recipe, or keep it as "older builds"), docs/explanation/security-model.md "Daemon IPC" (record the decision: env-independent per-user runtime dir; rejected $HOME-rooted persistent dirs and the warn-only option; Revisit if macOS ever drops _CS_DARWIN_USER_TEMP_DIR), docs/explanation/architecture/ipc.md:427-428,456-457 (generalize "$XDG_RUNTIME_DIR" to "the per-user runtime dir"), docs/reference/terminal-identity.md if it states the path, CHANGELOG.md (macOS: "the daemon endpoint no longer depends on TMPDIR; an SSH-spawned daemon on the old /tmp/felis.<uid> path keeps running — drain it with felis --socket /tmp/felis.<uid>/daemon.sock sessions list then pkill"). skills/felis does not state the path (skills/felis/SKILL.md:310,374 only mention "non-default socket"), so no change unless the doctor row text is documented there.
  5. Tests: socket.rs unit tests (:95-106 cover the TMPDIR fallback) gain a cfg(target_os = "macos") test that resolution with TMPDIR unset equals resolution with it set to the confstr dir; a Linux test for the /run/user/<uid> probe. macOS has no CI runtime (install.md:145), so the acceptance criterion in the issue (same daemon status session list from felis --host mac and local felis) is verified by hand with the felis-macos-gui-debug skill and recorded in the PR.

Dependencies

  • None blocking. The carrier/grammar work (#23, #42) does not touch SocketPath::resolve. Land after the tag and before any macOS support claim (the aarch64-darwin row in install.md:145 flipping to "Supported" is the trigger).

Risk/effort

S–M. One new audited unsafe site in felis-transport; the migration risk (daemons already serving on /tmp/felis.<uid> from SSH relays) is handled by the doctor probe and the CHANGELOG drain note rather than by automatic takeover.

Labels

Keep priority/P2, post-v0.1.0. Add a note (or label, if one exists) "blocks macOS support claim" so it cannot be forgotten when install.md's support table changes. Correct the issue body's Linux fallback claim (~/.local/state${TMPDIR:-/tmp}/felis.<uid>, socket.rs:37-47).

Review amendments (round 3)

  • The Linux endpoint rule is frozen at v0.1.0; the /run/user/<uid> probe is withdrawn. Linux is the supported platform, and its default endpoint ($XDG_RUNTIME_DIR/felis, else ${TMPDIR:-/tmp}/felis.<uid>, socket.rs:28-47; workspace.md:235-239) is observable behavior inside #12's freeze boundary: changing it after the tag would make an upgraded client miss a running daemon and autospawn a second one. Record in the plan and in the #41 body that the Linux rule is frozen as-is for v0.1.0 (a one-line addition to the reference page's endpoint paragraph). The macOS change stays post-v0.1.0 and, if it ever needs a Linux counterpart, must probe the legacy path and never bind over a live socket.
## Triage plan (2026-09-03) Source-grounded triage against `main` at `69076d42`, reviewed through seven rounds of an independent reviewer (`pi` sol/luna) until it passed with no findings. The dependency order that supersedes the tracker's is posted on #12. Where a "Review amendments" section below conflicts with an earlier section, the amendment is the decision. ## Claim check The bug is real and reproducible from the source; one supporting claim about Linux is wrong. - Socket derivation: `crates/felis-transport/src/socket.rs:28-48`. On macOS `SocketPath::resolve` goes **unconditionally** to `tmpdir_fallback(uid, $TMPDIR)` (`:29-31`), which is `${TMPDIR:-/tmp}/felis.<uid>/daemon.sock` (`:39-47`). On Linux it first tries `directories::ProjectDirs::runtime_dir()` (i.e. `$XDG_RUNTIME_DIR/felis`) and then the **same** TMPDIR fallback (`:32-37`). - So the issue's statement that Linux "falls back to `~/.local/state` etc." is **wrong**: an SSH login without `XDG_RUNTIME_DIR` gets `/tmp/felis.<uid>` on Linux too. It rarely manifests because pam_systemd sets `XDG_RUNTIME_DIR` for SSH logins on systemd hosts, but the fix should not be macOS-only in its reasoning. - Resolution order: `crates/felis-client-core/src/local_socket.rs:25-33` (`--socket`, then `FELIS_SOCKET`, then the platform default), documented at `docs/reference/cli.md:602-612`. The remote side of `--host` is `felis-daemon relay`, which resolves `default_socket_path()` in **its own** (sshd-provided) environment (`crates/felis-daemon/src/main.rs:89-96`) and autospawns `felis-daemon serve --socket <that path>` (`relay.rs:103-117`). A GUI-launched daemon resolves against the launchd `TMPDIR`. Two paths, two daemons — confirmed. - Mitigation is doc-only: `docs/how-to/attach-over-ssh.md:176-183`. Confirmed. `doctor` dials only the resolved target (`crates/felis-cli/src/cli_doctor.rs:128-160`) and `DaemonStatus` (`connector.rs:683-690`) carries no endpoint, so a second daemon is invisible — confirmed. - The rationale for `0700` dir / `0600` socket / "pathname sockets under the user's runtime dir" is at `docs/explanation/security-model.md:267-290`; no macOS-specific placement rationale is recorded anywhere, so the current TMPDIR choice is an undocumented default rather than a decision. - The tracker comment on the issue already answered the "1.0 or never" framing: v0.1.0 claims only `x86_64-linux` (`docs/how-to/install.md:143-148`: `aarch64-darwin` "Nothing runs on macOS"), so the macOS default endpoint is not part of any compatibility promise the tag makes. ## Verdict **defer** (keep post-v0.1.0, P2) — with a hard gate the label set should carry: this **must land before the first release that claims macOS support**, because that release is the one after which moving the default orphans live sessions. Deferral past v0.1.0 costs nothing: the freeze boundary lists "documented environment variables", and `TMPDIR` is an OS variable felis merely consumes; `cli.md:602` documents the resolution *order*, not the macOS path. #12's "Contract freeze boundary" does not mention the endpoint default, and it should not be added. Recommend option A in a specific form, plus a slice of C for observability; reject B as the primary fix (a warning still leaves two daemons). ## Approach 1. **Derive the macOS runtime dir without the environment.** Use `confstr(_CS_DARWIN_USER_TEMP_DIR)` — the same per-user, mode-0700 directory launchd puts in `TMPDIR` (`getconf DARWIN_USER_TEMP_DIR` is its shell spelling), stable across GUI and SSH logins, and a runtime location rather than a persistent one (`~/Library/Application Support` is backed up/synced and is where `config.toml` already lives, `install.md:58`; sockets do not belong there). Order on macOS becomes `--socket` → `FELIS_SOCKET` → `confstr` dir → `$TMPDIR` → `/tmp`. This keeps the GUI-side path **identical** to today (launchd's `TMPDIR` *is* that directory), so no existing GUI session is orphaned; only the SSH-side daemons move, and those are the ones the bug created. `confstr` is one libc FFI call in `felis-transport`, which already carries an audited `#[allow(unsafe_code)]` site for `getpeereid` (`CLAUDE.md` "Workspace policy"; `felis-transport/Cargo.toml:28-37` already depends on `libc` for the same reason) — add it beside that one with a `// SAFETY:` comment. 2. **Linux**: same shape, cheaper — when `XDG_RUNTIME_DIR` is unset, probe `/run/user/<uid>` before the TMPDIR fallback. Optional; it closes the same class of bug the issue mis-described. 3. **Observability (option C, read-only)**: `doctor`'s `daemon` row also connect-probes the legacy path(s) (`${TMPDIR:-/tmp}/felis.<uid>/daemon.sock` when it differs from the resolved one) and reports "a second daemon is serving <path>" as a `warn` row, reusing the probe `serve` already uses to avoid stealing a live socket (`security-model.md:288-300`). No exit-2, no automatic takeover: a live daemon with sessions must never be unlinked (same rule). `felis-daemon serve` logs the resolved dir at startup already; add the derivation source (`confstr`/`TMPDIR`/`fallback`) to that line. 4. **Docs**: `docs/reference/cli.md:602-612` (the default per platform, now stated), `docs/how-to/attach-over-ssh.md:176-183` (delete the `TMPDIR` recipe, or keep it as "older builds"), `docs/explanation/security-model.md` "Daemon IPC" (record the decision: env-independent per-user runtime dir; rejected `$HOME`-rooted persistent dirs and the warn-only option; Revisit if macOS ever drops `_CS_DARWIN_USER_TEMP_DIR`), `docs/explanation/architecture/ipc.md:427-428,456-457` (generalize "`$XDG_RUNTIME_DIR`" to "the per-user runtime dir"), `docs/reference/terminal-identity.md` if it states the path, `CHANGELOG.md` (macOS: "the daemon endpoint no longer depends on `TMPDIR`; an SSH-spawned daemon on the old `/tmp/felis.<uid>` path keeps running — drain it with `felis --socket /tmp/felis.<uid>/daemon.sock sessions list` then `pkill`"). `skills/felis` does not state the path (`skills/felis/SKILL.md:310,374` only mention "non-default socket"), so no change unless the doctor row text is documented there. 5. **Tests**: `socket.rs` unit tests (`:95-106` cover the TMPDIR fallback) gain a `cfg(target_os = "macos")` test that resolution with `TMPDIR` unset equals resolution with it set to the confstr dir; a Linux test for the `/run/user/<uid>` probe. macOS has no CI runtime (`install.md:145`), so the acceptance criterion in the issue (same `daemon status` session list from `felis --host mac` and local `felis`) is verified by hand with the `felis-macos-gui-debug` skill and recorded in the PR. ## Dependencies - None blocking. The carrier/grammar work (#23, #42) does not touch `SocketPath::resolve`. Land after the tag and before any macOS support claim (the `aarch64-darwin` row in `install.md:145` flipping to "Supported" is the trigger). ## Risk/effort **S–M.** One new audited unsafe site in felis-transport; the migration risk (daemons already serving on `/tmp/felis.<uid>` from SSH relays) is handled by the doctor probe and the CHANGELOG drain note rather than by automatic takeover. ## Labels Keep `priority/P2`, post-v0.1.0. Add a note (or label, if one exists) "blocks macOS support claim" so it cannot be forgotten when `install.md`'s support table changes. Correct the issue body's Linux fallback claim (`~/.local/state` → `${TMPDIR:-/tmp}/felis.<uid>`, `socket.rs:37-47`). ## Review amendments (round 3) - **The Linux endpoint rule is frozen at v0.1.0; the `/run/user/<uid>` probe is withdrawn.** Linux is the supported platform, and its default endpoint (`$XDG_RUNTIME_DIR/felis`, else `${TMPDIR:-/tmp}/felis.<uid>`, `socket.rs:28-47`; `workspace.md:235-239`) is observable behavior inside #12's freeze boundary: changing it after the tag would make an upgraded client miss a running daemon and autospawn a second one. Record in the plan and in the #41 body that the Linux rule is frozen as-is for v0.1.0 (a one-line addition to the reference page's endpoint paragraph). The macOS change stays post-v0.1.0 and, if it ever needs a Linux counterpart, must probe the legacy path and never bind over a live socket.
Author
Owner

The macOS half of the endpoint topology landed in #281 (for #275), connect-only: felis-transport now derives confstr(_CS_DARWIN_USER_TEMP_DIR)/felis.<uid>/daemon.sock as the login manager's location, and both felis-daemon relay and felis doctor probe it when the resolved default is the environment-free /tmp/felis.<uid> fallback. Nothing binds there and the macOS default endpoint rule is untouched, so no GUI session moves.

That complements this issue rather than pre-empting it: moving the macOS default to the confstr directory is still #41's own decision, and the round-3 amendment's condition on any Linux counterpart ("must probe the legacy path and never bind over a live socket") is what #281 implements. The confstr call is the one audited #[allow(unsafe_code)] site with a // SAFETY: comment that the triage plan sanctioned; it is unit-tested under cfg(target_os = "macos") but was not hand-verified on a Mac in that PR.

The macOS half of the endpoint topology landed in #281 (for #275), connect-only: `felis-transport` now derives `confstr(_CS_DARWIN_USER_TEMP_DIR)/felis.<uid>/daemon.sock` as the login manager's location, and both `felis-daemon relay` and `felis doctor` probe it when the resolved default is the environment-free `/tmp/felis.<uid>` fallback. Nothing binds there and the macOS default endpoint rule is untouched, so no GUI session moves. That complements this issue rather than pre-empting it: moving the macOS *default* to the confstr directory is still #41's own decision, and the round-3 amendment's condition on any Linux counterpart ("must probe the legacy path and never bind over a live socket") is what #281 implements. The confstr call is the one audited `#[allow(unsafe_code)]` site with a `// SAFETY:` comment that the triage plan sanctioned; it is unit-tested under `cfg(target_os = "macos")` but was not hand-verified on a Mac in that PR.
Author
Owner

Resolved by #275 plan v3 (comment #275 (comment)), the macOS half of option A: an absent TMPDIR resolves to confstr(_CS_DARWIN_USER_TEMP_DIR)/felis.<uid>, the same directory launchd exports as the GUI session's TMPDIR, so an SSH login's relay reaches the GUI daemon without exporting anything. A set TMPDIR stays authoritative, so the GUI daemon does not move and a custom value is still honored. Option C's observability survives as the felis doctor daemon-sibling row (it reports a daemon an older build left on /tmp/felis.<uid>). The round-3 "frozen at v0.1.0" amendment is withdrawn: no tag exists and the derivation is now stated in #12's freeze list as of the #275 change. Closing when the reworked PR #281 merges.

Resolved by #275 plan v3 (comment https://git.natsukium.com/natsukium/felis/issues/275#issuecomment-2818), the macOS half of option A: an absent `TMPDIR` resolves to `confstr(_CS_DARWIN_USER_TEMP_DIR)/felis.<uid>`, the same directory launchd exports as the GUI session's `TMPDIR`, so an SSH login's relay reaches the GUI daemon without exporting anything. A set `TMPDIR` stays authoritative, so the GUI daemon does not move and a custom value is still honored. Option C's observability survives as the `felis doctor` `daemon-sibling` row (it reports a daemon an older build left on `/tmp/felis.<uid>`). The round-3 "frozen at v0.1.0" amendment is withdrawn: no tag exists and the derivation is now stated in #12's freeze list as of the #275 change. Closing when the reworked PR #281 merges.
Sign in to join this conversation.
No description provided.