4 Commits
Author SHA1 Message Date
Vincent Rozenberg 2e0c498fc9 Capture XHR-driven logins and offer to save password
Google, Microsoft, Okta and most modern login pages never fire a DOM
submit event — they POST via fetch/XHR and manipulate the DOM directly.
The old approach (submit listener) missed every one of them.

Three triggers now cover the common outcomes after a successful login:

  A. MutationObserver — password field removed from DOM.  Primary path.
     Most SPAs tear down the login form on success.

  B. History API interception (pushState / replaceState / popstate) —
     URL changes before the DOM settles.  100 ms grace period, then
     checks whether the field is still present before firing.

  C. Traditional form submit — kept for regressions (non-SPA sites).
     Clears pwCapture so Trigger A cannot double-fire.

Failed-login heuristic: if the password field is still in the DOM when a
trigger fires, the credential is not offered.  Avoids false positives on
wrong-password attempts.

`filling` flag prevents the capture loop from running while __workAppFill
is programmatically writing into fields.
2026-09-03 13:53:30 +02:00
Vincent Rozenberg 647c08c5b8 Fix fill-password: wrong host key, and silent failure
Two bugs made 'Fill saved password' do nothing:

1. HOST MISMATCH. Saving used location.hostname at submit time (e.g.
   accounts.google.com); filling derived the host from the app's
   configured URL (mail.google.com). The Keychain lookup always found
   nothing for any service with a separate auth domain. Fixed by storing
   the save-time hostname in App.saved_host and reading it back at fill
   time, falling back to default_scope for entries saved before this.

2. SILENT FAILURE. Every error path in the fillpw sentinel called only
   eprintln!, which is invisible to the user. A feature that fails silently
   is indistinguishable from one that is not wired up. Fixed by emitting a
   fill-error event; the shell shows it as a toast in the nav column, which
   is left of the stage and therefore always above native views.
2026-09-03 13:35:26 +02:00
Vincent Rozenberg 25e04c33df Ignore .claude/settings.local.json — machine-local permission allowlist, not project state 2026-09-03 12:46:25 +02:00
Vincent Rozenberg 76f2aa5928 Pin Rust toolchain to stable so tauri-cli never panics on a fresh machine
On a machine where rustup has no default toolchain, tauri-cli calls
`cargo metadata` without specifying one and panics in its metadata thread
with no useful error — just an abort. The file lives at the project root
(not src-tauri/) because tauri-cli invokes cargo from there; rustup walks
up from the CWD, so the root copy is the one that gets picked up.

Also notes this in FORK.md so a future forker knows what they would hit
and why the file must exist.
2026-09-03 12:44:10 +02:00