fix(tauri): forward deep-link URLs on Linux before CEF preflight exits secondary#2458
Conversation
…s secondary On Linux, OAuth callbacks launch a second binary with the URL in argv. That secondary hits cef_preflight::check_default_cache() and exits(1) before Builder::setup() runs, silently dropping the URL. Adds deep_link_ipc.rs (Linux-only): the primary binds a Unix domain socket at $XDG_RUNTIME_DIR/com.openhuman.app-deeplink.sock before the CEF preflight check. A secondary instance that finds openhuman:// URLs in argv connects, writes them, and exits(0) — never reaching the preflight. On setup(), drain_pending_urls emits deep-link://new-url events to the app handle for each queued URL. This mirrors the Windows pre-CEF named-mutex guard (lib.rs:2092-2128) for the Linux case. Closes tinyhumansai#2359
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughIntroduces a Linux-only Unix socket-based IPC mechanism to forward ChangesLinux OAuth deep-link forwarding
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src-tauri/src/deep_link_ipc.rs`:
- Around line 115-117: The debug logs currently print full deep-link URLs (which
may include secrets); add a helper function named redact_url_for_log(url: &str)
-> String that parses the URL and strips query and fragment (falling back to
"<invalid deep link>"), then use that helper wherever URLs are logged: replace
direct uses in the pending_queue() lock block (the log! call that prints url),
and the other logging sites referenced (around the handlers at the locations you
noted) to log redact_url_for_log(&url) instead of the raw url string; ensure the
pushed value into the pending queue remains the original url (only redact for
logging).
- Around line 141-145: The unconditional std::fs::remove_file(&path) before
binding can delete a live socket from another instance; change bind_and_listen()
to first attempt UnixListener::bind(&path) and only if that fails due to
"address in use" try to probe the existing socket with
UnixStream::connect(&path) (or equivalent) to determine if a server is alive; if
connect succeeds, return a suitable ForwardResult/err indicating another
instance is active, and if connect fails (stale socket), then unlink the file
and retry UnixListener::bind(&path). Ensure you specifically update the code
paths around bind_and_listen(), UnixListener::bind, and the remove_file usage to
perform bind-first, probe-with-UnixStream::connect, then remove_file+retry only
when confirmed stale.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a326d97f-8d4d-4690-8171-0d2a4f862a63
📒 Files selected for processing (2)
app/src-tauri/src/deep_link_ipc.rsapp/src-tauri/src/lib.rs
Address CodeRabbit review on PR tinyhumansai#2458: 1. Add `redact_url_for_log()` helper that strips query string and fragment before logging deep-link URLs. OAuth callbacks carry tokens in the query string; logging the raw URL persists secrets in log files and crash reports. 2. Change `bind_and_listen()` from unconditional remove-then-bind to a bind-first approach: attempt bind, then on AddrInUse probe the existing socket with `UnixStream::connect` to distinguish a live primary (leave it alone, return None) from a stale socket after a crash (safe to remove and retry bind). Prevents a concurrent secondary from deleting a live primary's socket file.
M3gA-Mind
left a comment
There was a problem hiding this comment.
Both CodeRabbit items addressed in commit f4bebd6:
- Added
redact_url_for_log()helper that strips query/fragment before logging — OAuth tokens no longer appear in log output. - Changed
bind_and_listen()to bind-first: probes the existing socket withUnixStream::connectto distinguish live primary (skip) from stale socket after crash (remove+retry).
|
@graycyrus This Linux deep-link forwarding fix is also green and mergeable. It covers the Linux side of OAuth/deep-link delivery before CEF preflight exits a secondary instance (#2359). CodeRabbit approved/no actionable comments; please review/merge when you can. |
# Conflicts: # app/src-tauri/src/lib.rs
The `settings.mcpServer.*` and `settings.developerMenu.mcpServer.*` keys
at lines 526-547 in de-5.ts duplicate the earlier block at 211-235,
causing `tsc --noEmit` to fail with TS1117 ("object literal cannot have
multiple properties with the same name") and blocking the Type Check
and E2E Appium jobs on every open PR.
This is the same shape as tinyhumansai#2495 ("remove duplicate German keys
unblocking main's Type Check"); a fresh duplicate slipped in during a
later i18n batch.
Removes only the duplicate block; the earlier (more idiomatic German:
"Verfügbare Werkzeuge" vs "Verfügbare Tools") definitions are retained.
Summary
app/src-tauri/src/deep_link_ipc.rs— Linux-only (#[cfg(target_os = "linux")]) Unix domain socket-based pre-CEF deep-link forwarder.$XDG_RUNTIME_DIR/com.openhuman.app-deeplink.sock(fallback:/tmp/com_openhuman_app_deeplink_{uid}.sock) BEFOREcef_preflight::check_default_cache(). Queues any arriving URLs untilsetup()runs.exit(0)— never reaching the CEF preflight.drain_pending_urls(called insetup()after deep-link plugin registration) drains the queue and installs a live handler that emitsdeep-link://new-urlevents to theAppHandlefor all future arrivals.Problem
On Linux,
openhuman://OAuth callbacks launch a secondOpenHumanbinary with the URL asargv[1]. The secondary hitscef_preflight::check_default_cache()atlib.rs:2155which detects the CEF cache lock held by the primary and callsstd::process::exit(1)— beforeBuilder::build()orBuilder::setup()runs. Thetauri-plugin-single-instanceD-Bus forwarding andtauri-plugin-deep-linkregistration both live insetup(), so they never execute. The OAuth URL is silently dropped.Windows already has a fix: the pre-CEF named-mutex guard at
lib.rs:2092-2128detects secondaries and forwards URLs before any CEF init. This PR applies the equivalent pattern to Linux using Unix domain sockets.Solution
The fix inserts a guard at
lib.rslines 2152–2167 (between the Windows mutex guard and the CEF preflight). On Linux:Submission Checklist
deep_link_ipc.rs(socket_path_uses_xdg_runtime_dir,socket_path_fallback_has_uid,extract_deep_link_urls_filters_correctly,round_trip_bind_connect_forward,no_primary_returns_appropriate_result)cargo checkcleannix(already a dep withuserfeature),url(already a dep),tempfile(already in dev-deps)Closes #2359Impact
#[cfg(target_os = "linux")].openhuman://via Apple Events to the already-running process (RunEvent::Opened) — no secondary binary is launched, so no CEF race exists.Related
AI Authored PR Metadata
Linear Issue
Commit & Branch
Validation Run
pnpm --filter openhuman-app format:check— N/A (no frontend changes)pnpm typecheck— N/A (no frontend changes)cargo test --manifest-path app/src-tauri/Cargo.toml -- deep_link_ipc— gated to Linux, not compiled on macOS CIcargo fmt --manifest-path app/src-tauri/Cargo.toml --all -- --checkpasses;cargo check --manifest-path app/src-tauri/Cargo.tomlcleanValidation Blocked
command:cargo test --manifest-path app/src-tauri/Cargo.toml -- deep_link_ipcerror:All tests are#[cfg(target_os = "linux")]— not compiled on macOS dev machineimpact:Tests will run in CI on Linux. The socket round-trip logic has been code-reviewed; it follows the same pattern as the proven Windows mutex guard.Behavior Changes
openhuman://deep-link callbacks on Linux reach the running app and complete OAuthParity Contract
Duplicate / Superseded PR Handling
Summary by CodeRabbit
Release Notes