daemon: scrub stale keymap-command origin variables from every base #226

Merged
natsukium merged 1 commit from daemon/origin-env into main 2026-10-21 22:33:33 +09:00
Owner

The keymap-command origin variables (FELIS_ORIGIN_SESSION_ID, FELIS_HOST, FELIS_CWD, and the viewport anchors) were only ever added, never removed. A felis window launched from a run command therefore kept that chord's values in its own environment and passed them on to its later chords and new sessions. A local window opened from a --host window kept reporting the remote host, so a script that branches on FELIS_HOST dialed the wrong daemon.

The daemon now removes them in apply_env_policy, next to the denylist. Every create passes through that function whatever its base: the client's snapshot, the relay carrier's environment, or the daemon's own birth environment. That covers a systemd-run hand-off and the fallback used when a snapshot is over its caps. Unlike the denylist, these keys are not reserved, so SpawnArgs.env still sets the current chord's values after the scrub.

felis-client-core exposes the full set as ORIGIN_ENV_KEYS, and a daemon test keeps the two lists equal. No wire or config change; this is a patch-release fix.

Closes #223.

Verification

  • New tests:
    • each base source (request snapshot, relay) loses all six stale values;
    • explicit SpawnArgs.env values for all six arrive exactly;
    • a stale inherited value under the birth base is replaced by the current explicit one;
    • the six are not reserved;
    • the client and daemon lists match.
  • just check minus the test step passes (fmt, lint, portable, prose, skills, docs links, deny, publish dry run, proto-compat, tool tests), and so does just check-windows.
  • cargo nextest run --workspace --all-features shows three failures, none from this change:
    • the felis-render-wgpu row_cache golden failures reproduce on clean main;
    • cli_bridge::tests::a_daemon_write_failure_fails_and_clears_the_link hangs on clean main too;
    • an_idle_notification_subscriber_does_not_block_the_upgrade timed out under full-suite load but passes on its own.
The keymap-command origin variables (`FELIS_ORIGIN_SESSION_ID`, `FELIS_HOST`, `FELIS_CWD`, and the viewport anchors) were only ever added, never removed. A felis window launched from a `run` command therefore kept that chord's values in its own environment and passed them on to its later chords and new sessions. A local window opened from a `--host` window kept reporting the remote host, so a script that branches on `FELIS_HOST` dialed the wrong daemon. The daemon now removes them in `apply_env_policy`, next to the denylist. Every create passes through that function whatever its base: the client's snapshot, the relay carrier's environment, or the daemon's own birth environment. That covers a `systemd-run` hand-off and the fallback used when a snapshot is over its caps. Unlike the denylist, these keys are not reserved, so `SpawnArgs.env` still sets the current chord's values after the scrub. `felis-client-core` exposes the full set as `ORIGIN_ENV_KEYS`, and a daemon test keeps the two lists equal. No wire or config change; this is a patch-release fix. Closes #223. ## Verification - New tests: - each base source (request snapshot, relay) loses all six stale values; - explicit `SpawnArgs.env` values for all six arrive exactly; - a stale inherited value under the birth base is replaced by the current explicit one; - the six are not reserved; - the client and daemon lists match. - `just check` minus the test step passes (fmt, lint, portable, prose, skills, docs links, deny, publish dry run, proto-compat, tool tests), and so does `just check-windows`. - `cargo nextest run --workspace --all-features` shows three failures, none from this change: - the `felis-render-wgpu` row_cache golden failures reproduce on clean `main`; - `cli_bridge::tests::a_daemon_write_failure_fails_and_clears_the_link` hangs on clean `main` too; - `an_idle_notification_subscriber_does_not_block_the_upgrade` timed out under full-suite load but passes on its own.
daemon: scrub stale keymap-command origin variables from every base
All checks were successful
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 11s
windows / detect relevant changes (pull_request) Successful in 10s
darwin / darwin docs-only no-op (pull_request) Has been skipped
windows / windows docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m14s
windows / cargo nextest (Windows) (pull_request) Successful in 2m25s
windows / frontend smoke (Windows) (pull_request) Successful in 38s
bench / instruction-count regression gate (pull_request) Successful in 5m38s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 20m17s
pr / nix flake check (pull_request) Successful in 5m19s
pr / cargo build / clippy / test / deny (pull_request) Successful in 5m40s
pr / wire schema is compatible with the base (pull_request) Successful in 19s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 3m49s
windows / cargo clippy (Windows cross) (pull_request) Successful in 56s
fce752591d
The client exports FELIS_ORIGIN_SESSION_ID, FELIS_HOST, FELIS_CWD and
the viewport anchors to a keymap command, adding only the values the
current origin has. Nothing removed an inherited copy, so a felis
window launched from such a command kept that chord's values in its
own environment and handed them to its later chords and new sessions:
a local window opened from a --host window went on reporting the
remote host, and a script branching on FELIS_HOST dialed the wrong
daemon.

The daemon now removes them in apply_env_policy next to the denylist,
which every create passes through whatever its base (the client's
snapshot, the relay carrier's environment, or the daemon's own birth
environment, including a systemd-run hand-off and the fallback when a
snapshot is over its caps). Unlike the denylist they are not reserved:
the chord that spawns a command sets the current values through
SpawnArgs.env, which applies after the scrub. Scrubbing only in the
client's capture and in the daemon auto-spawn was rejected because the
relay base and a manager-started daemon bypass both.

felis-client-core exposes the full set as ORIGIN_ENV_KEYS, and a
daemon test keeps the two lists equal, since the daemon reaches
client-core only as a dev-dependency.

Assisted-by: Claude Code
natsukium scheduled this pull request to auto merge when all checks succeed 2026-10-21 21:53:06 +09:00
natsukium deleted branch daemon/origin-env 2026-10-21 22:33:33 +09:00
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis!226
No description provided.