fix(desktop): first-run setup no longer requires input - #43
Merged
Conversation
…allback
Tauri commands return Result<T, String> on the Rust side, so a failed
command rejects invoke() with a plain string, not an Error instance.
Every call site's catch (err) { err instanceof Error ? err.message :
fallback } pattern — SetupScreen's first-run wizard, and both error
paths in DatabaseSettings — was therefore always taking the generic
fallback ("Setup failed.", "Connection failed", "Failed to switch
database") and silently discarding the actual reason Rust returned
(e.g. "A valid email is required.", a keychain failure, a bad
connection string).
Fixed once at the IPC boundary in invokeTauri() rather than patching
each catch site: normalize whatever invoke() rejects with into a real
Error, so err.message downstream is always the genuine message.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The wizard required an email and let you edit the database path before finishing setup — every validation failure (bad email, keychain error, a copied-DB refusal) surfaced as an opaque error with no field to even retry from, since the previous commit's swallowed-error bug hid what actually went wrong. Setup now completes automatically on first launch: email defaults to local@foxschema.app (the same placeholder the web edition's single-user mode already uses) and the database stays on its default SQLite location. No form, no required input — just a brief "Securing this install…" moment, or a real error message with a Retry button if something genuinely fails (e.g. a copied database refused by enforce_install_binding). Since email is no longer entered at setup, added a way to set a real one afterward: Settings → Security now has an editable "Change" action backed by a new update_email Tauri command. It re-stores the SAME key material under the new email's keychain account (the DEK itself never changes, so already-encrypted data keeps decrypting) and best-effort removes the old account — no sidecar respawn needed, since nothing about the metadata DB changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A user hit a bare "Setup failed." on the desktop app's first-run wizard with no further detail, then — once diagnosable — a genuine setup failure that turned out to be two separate real bugs, both found by actually running the fixed app end-to-end.
1. The error-swallowing bug. Tauri commands return
Result<T, String>on the Rust side, so a failed command rejectsinvoke()with a plain string, not a JSError. Every call site'scatch (err) { err instanceof Error ? err.message : fallback }—SetupScreen, both error paths inDatabaseSettings— always took the generic fallback and hid whatever Rust actually returned. Fixed once at the IPC boundary ininvokeTauri()(apiBase.ts).2. First-run wizard needs no input. Previously required a real email (bound to the encryption key) and let you edit the database path before finishing. Now it completes automatically: email defaults to
local@foxschema.app(same placeholder the web edition's single-user mode already uses), database stays on its default SQLite location, no form — just a brief "Securing this install…" moment, or a real error + Retry button if something fails.3. New "Change email" in Settings → Security, since it's no longer set at setup time. New
update_emailTauri command re-stores the same key material under the new email's keychain account — no re-encryption, no sidecar respawn.4. Two real bugs found by actually running the above, both hidden by bug #1 until now:
SetupScreen's auto-attempt effect only guarded against a straysetStateafter unmount — it didn't stopcompleteSetup()from firing twice under React 18 StrictMode's dev-mode double-invoke, racing two sidecar subprocesses against the same SQLite file ("database is locked"). Fixed with a ref that survives the mount/unmount/remount cycle (the standard StrictMode-safe pattern for effects with real side effects).enforce_install_binding's JSON parse usedstdout.lines().last(), but the captured stdout can carry more than one trailing newline undertauri_plugin_shell's capture (not reproducible via a direct shell invocation of the identical command) — making.lines().last()return an empty line instead of the JSON, always failing regardless of whether the check actually succeeded. Fixed by trimming the whole capture before splitting.enforce_install_binding's failure paths — this check's output went nowhere on failure before, which is exactly why bug was invisible.Test plan
cargo check(Rust) andcd apps/web && npx tsc --noEmit— both clean.npx vitest run— 221 passed, 2 skipped.invokeTaurinormalizes a plain-string rejection into a realError(mockedwindow.__TAURI__.core.invoke).SetupScreenend-to-end in-browser (error/Retry states) and, separately, ran the actual desktop app (npm run dev) through several clean first-runs — reproduced both bug feat: E2E test suite, SQL generator fixes, security automation, versioning #4 issues live via added diagnostic logging, fixed each, and confirmed a completely clean first run:setup_complete: true, sidecar API listening, no errors.EmailSettingsChange → edit → Save flow end-to-end in-browser (mocked Tauri +/api/app-info).