Skip to content

feat(desktop): skip the privileged helper in non-tun proxy modes - #221

Merged
loss-and-quick merged 1 commit into
mainfrom
feat/elevation-gating
Jul 14, 2026
Merged

feat(desktop): skip the privileged helper in non-tun proxy modes#221
loss-and-quick merged 1 commit into
mainfrom
feat/elevation-gating

Conversation

@loss-and-quick

Copy link
Copy Markdown
Owner

Summary

Skip the privileged data-path helper when the saved proxy mode doesn't need it. With proxyMode = proxy-only / system / pac, the GUI now runs the data-path in-process and unprivileged: no pkexec prompt on Linux, no LocalSystem service install/connect (and thus no first-run UAC) on Windows. tun — the default, and the answer on any unreadable state — keeps today's helper-backed behaviour exactly.

Builds on #220 (the helper hands its runtime files and the run-dir inodes to the GUI user), which makes alternating privileged/unprivileged data-path owners over the same paths safe.

Mechanics:

  • Saved-mode read: saved_proxy_mode() reads settings.proxyMode out of <datadir>/app-state.json as a bare field — deliberately not the full AppState schema/migration, so a legacy or foreign document still answers sanely. Any failure (paths, missing file, corrupt JSON, absent key, unknown value) → Tun, i.e. a bad read can never silently drop the helper for a tun user.
  • Gate in build_platform: after the untouched KASUMI_SKIP_ELEVATION short-circuit and before the per-OS client split, so one check covers both Linux and Windows arms.
  • Honest failure on a live switch to tun: the gated platform carries a construction-time flag; start_data_path with mode == tun on it fails up-front with failed: tun mode needs an app restart (the privileged helper is not running) — before the connecting state blip and any tun bring-up — so the UI shows an actionable reason instead of a cryptic tun-creation error. The reverse direction needs nothing: a helper-backed session already serves every mode (the mode rides StartDataPath), so switching away from tun applies on the next start without a restart.
  • The startup OS-proxy sweep, boot_init dir creation, test cores, subscriptions and status all ride the in-process platform unchanged (the KASUMI_SKIP_ELEVATION path has long proven the shape).

Affected layer

  • frontend/ — React Web UI
  • crates/ · src-tauri/ — Rust core / backend / Tauri desktop
  • module/ — Android installable zip (thin launcher over the Rust daemon)
  • scripts/ — build / release helpers
  • CI / .github/
  • Docs only

Verification

Rust (crates/ · src-tauri/):

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace — one failure: net::tests::tcp_ping_fails_on_unreachable_host, the known environment flake (an active VPN tun on the dev machine captures the TEST-NET-1 connect); fails identically on main
  • No frontend/codegen changes

New tests: bare-field mode extraction (all four values; corrupt/absent/wrong-type/unknown → tun) and the gated refusal (tun → restart-required error + failed: service state; non-tun passes the gate and fails later on the missing core binary, proving mode-selectivity).

Checklist

  • Title is a scoped Conventional Commit; commits are logically split
  • No build artifacts committed (module/bin/<abi>/, geoip/geosite, built module/webroot/, src-tauri/gen/ — all gitignored on purpose)
  • Generated frontend/src/generated/ was regenerated from Rust, not hand-edited (untouched)
  • If user-visible strings changed: i18n/en.ts and every locale file updated (no user-visible strings changed)
  • Renames touching the project id were grepped in all case forms (kasumi-proxy, Kasumi Proxy, camelCase)

Notes for reviewers

  • The env-mutating tests in this crate now serialize on a shared env_test_guard() mutex (poison-recovering): they flip process-global KASUMI_* overrides, and the new integration test flaked once under full-workspace parallelism before the guard. Held only across the synchronous set→construct→remove window, dropped before any await.
  • Restart-required is the deliberate v1 for the non-tun → tun switch; a later change may bring the helper up on demand and swap the platform live (the ServiceHandle watch channel leaves that door open).
  • Windows reviewers: the gate moves the service-install trigger — a non-tun user never installs/starts the service at all. First switch to tun (after the app restart) installs it as before.
  • One unreproducible single-test failure was observed once in the desktop lib under full-workspace load during local verification (name not captured; 6 subsequent runs green, likely the network-dependent ping test on this VPN-flaky dev machine). Flagging for honesty; CI is the arbiter.

Only tun mode needs the privileged data-path (a tun device + OS routing
rewrite). Gate the startup helper on the saved proxy mode: a non-tun mode
(proxy-only/system/pac) runs the data-path in-process and unprivileged —
no pkexec prompt on Linux, no service install/connect (hence no UAC) on
Windows — while tun keeps today's helper-backed bring-up.

The saved mode is read as a bare `settings.proxyMode` field from
app-state.json, defaulting to tun on any failure so a bad read never drops
the helper for a tun user. The in-process platform is marked gated and
refuses a live switch to tun with a restart-required error before any tun
bring-up, so the UI shows an actionable `failed:<reason>`; the reverse
(a helper-backed session running a non-tun mode) already works.

Serialize the env-mutating tests behind a shared guard so the new gating
test doesn't race the existing path-resolution tests over process-global
KASUMI_* overrides.
@github-actions github-actions Bot added the backend Rust core/backend/desktop (crates/, src-tauri/) label Jul 14, 2026
@loss-and-quick
loss-and-quick merged commit a4b1c09 into main Jul 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Rust core/backend/desktop (crates/, src-tauri/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant