13 Commits
Author SHA1 Message Date
ZacharyZhang-NY 4e460a51d7 fix(sync): keep sync owner first-claim-wins on Windows 2026-07-10 12:16:15 -04:00
ZacharyZhang-NY 73f52cdcb1 fix(sync): bound response reads to the snapshot wire limit 2026-07-10 11:21:10 -04:00
ZacharyZhang-NY c5c622f1b8 fix(tests): read complete requests in the snapshot conflict server 2026-07-10 10:48:41 -04:00
ZacharyZhang-NY 3be13ca295 fix(sync): bind browser data to one account owner 2026-07-10 10:46:52 -04:00
ZacharyZhang-NY 46eac43326 fix(auth): reconcile expired desktop sessions 2026-07-10 09:46:55 -04:00
ZacharyZhang-NY 2f346abaea fix(auth): revoke desktop sessions safely 2026-07-10 08:57:00 -04:00
ZacharyZhang-NY 94afa23a69 fix(auth): store bearer tokens in native credentials 2026-07-10 07:57:44 -04:00
ZacharyZhang-NY 540b901fd6 fix(sync): secure encrypted snapshot lifecycle 2026-07-10 06:24:53 -04:00
ZacharyZhang-NY 556c5ff624 fix(sync): enforce private profile boundaries 2026-07-10 03:02:10 -04:00
ZacharyZhang-NY d076dad356 Fix shell regressions and reset Servo embedding direction 2026-05-16 11:23:41 -04:00
ZacharyZhang-NY 40ab6b4874 feat(sync): round trip cloud snapshots 2026-05-16 00:01:28 -04:00
ZacharyZhang-NY 74b3de54ed Add email + OTP sign-in flow for cloud sync
Replace the "drop a session token in a file" workflow with a real
Chrome-style email login. The Cloudflare worker already had Better
Auth's `email-otp` plugin wired into `SEND_EMAIL`; this commit
builds the renderer-side counterpart.

Worker side:
- Move the OTP sender from `auth@elydora.com` to `browser@elydora.com`
  (wrangler.toml `allowed_sender_addresses` + better_auth.ts
  `EMAIL_OTP_FROM_ADDRESS`). Worker must be redeployed to pick this up.

Client side (`ely_sync_client::email_otp`):
- `send_email_otp(config, email)` POSTs `/api/auth/email-otp/send-verification-otp`
  with `{ email, type: "sign-in" }`.
- `verify_email_otp(config, email, otp)` POSTs `/api/auth/sign-in/email-otp`,
  reads the Better Auth session token from the JSON body's `token` field
  with the `Set-Cookie: better-auth.session_token=…` header as the
  documented fallback channel, and returns it as a `BearerToken`.

Shell side (`shell/auth.rs` + `shell/internal_pages/sync.rs`):
- New `AuthFlowPhase` (Idle / SendingCode / AwaitingOtp / Verifying /
  Error) tracks the in-flight form. Two off-thread workers run the
  HTTP exchanges so the GPUI render loop never blocks.
- Successful verify saves the bearer via `SyncEngine::install_bearer`
  and triggers an immediate snapshot upload, so the user is signed in
  + initial-synced in one click.
- Sync settings page replaces the bare "Sync now" button row with an
  account card: when SignedOut → email field + Send code → OTP field
  + Verify / Resend; when signed in → an account chip + Sign out.
- `trigger_cloud_sync_upload` no longer takes a `Context` param so
  the post-auth path can fire it from the inbox-drain pass without
  needing a window context.
2026-05-15 21:32:50 -04:00
ZacharyZhang-NY 7366a0dffe Add ely_sync_client crate
Build the Rust counterpart to `ely-browser-cloud`: a Bearer-token
authenticated HTTP client with the JSON wire types for the worker's
device + snapshot routes.

What lands:
- `BearerToken` + `BearerTokenStore` so Better Auth sessions persist
  per profile data dir with atomic rename writes.
- `DeviceIdentity` (UUIDv7 + Ed25519-shaped public key, persisted
  alongside the token so the worker keeps the same `device_id` across
  restarts).
- `SyncApiClient` with `register_device`, `list_devices`,
  `upload_snapshot`, and `download_snapshot` over `ureq`, mapping the
  worker's strict error envelopes onto typed `SyncClientError`s.
- `SnapshotPayload` enforces the worker's 10 MiB / SHA-256-hash
  contract before the wire encode, so callers fail fast.

Out of scope for this commit: the BrowserCore integration that swaps
snapshots in and out, and the in-app Better Auth + device-approval UX.
Those land in subsequent commits — `cloudflare/src/api_controls.ts`
rejects sync from devices that aren't already approved, so first-use
also requires a one-shot D1 approval until that path exists in the UI.
2026-05-15 17:05:10 -04:00