todo-app/lib/sync
Krzysztof kuhy Rudnicki 3c6c071513 Let the desktop provision its sync account from the wrapper
The desktop app is a Flutter web build in a Chrome --app window, so
FlutterSecureStorage resolves to the web backend: AES-encrypted localStorage
keyed inside the browser profile. That left the sync account settable only by
typing it into the settings screen — nothing outside the page can write that
store (verified: `secret-tool` targets libsecret, which only a Linux build
would read, and a Dart CLI cannot even import flutter_secure_storage since it
is a Flutter plugin that fails to resolve on the VM).

So the account now arrives the same way the GitHub token already does: from
the wrapper, which owns the filesystem and serves the page. loadAccount()
falls back to GET /sync-account when the store is empty and persists the
result, so the route is consulted once per install rather than being
load-bearing forever.

The route reads ~/.config/crdt-sync/{firebase.json,password} — the same pair
the Python daemons already use — so there is one source of truth per machine
instead of a per-app copy.

Off unless CRDT_SYNC_SERVE_ACCOUNT is set, because it hands a credential with
database write access to anything that can reach the port. Verified both
ways against the running wrapper: 404 without the env var, 200 with it, and
the app serves normally either way. It answers 404 rather than 403 when
disabled, so a probe cannot tell the route exists.

clearAccount() now writes an opt-out marker that the fallback checks —
without it, Disconnect would delete the account and the next launch would
silently re-adopt it, making the button look broken.

252 tests, analyzer clean. Pinned to crdt_sync_dart-v0.8.0 for the shared
path/env-var constants and accountFromWrapper().

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177xwzcpfpWG2qca8Mr39q9
2026-08-09 21:39:16 +02:00
..
backlog_export_io.dart Cut the llm-design-spec template from 12 sections to 7 2026-07-26 22:03:35 +02:00
backlog_export_web.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
backlog_export.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
desktop_wrapper.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
firebase_backend.dart Let the desktop provision its sync account from the wrapper 2026-08-09 21:39:16 +02:00
github_device_auth.dart Switch to very_good_analysis, matching the rest of the Flutter ecosystem 2026-07-20 11:05:13 +02:00
local_backup_factory_io.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
local_backup_factory_web.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
local_backup_factory.dart Make the app compile and run for web, behind platform seams 2026-07-20 13:14:03 +02:00
local_backup.dart Switch to very_good_analysis, matching the rest of the Flutter ecosystem 2026-07-20 11:05:13 +02:00
notes_markdown.dart Switch to very_good_analysis, matching the rest of the Flutter ecosystem 2026-07-20 11:05:13 +02:00
run_sync.dart Sync through Firebase, mirroring to GitHub, and stop re-downloading peers 2026-08-04 23:36:24 +02:00
sync_service.dart Sync through Firebase, mirroring to GitHub, and stop re-downloading peers 2026-08-04 23:36:24 +02:00
sync_settings.dart Switch to very_good_analysis, matching the rest of the Flutter ecosystem 2026-07-20 11:05:13 +02:00
sync_state_factory_io.dart Sync through Firebase, mirroring to GitHub, and stop re-downloading peers 2026-08-04 23:36:24 +02:00
sync_state_factory_web.dart Sync through Firebase, mirroring to GitHub, and stop re-downloading peers 2026-08-04 23:36:24 +02:00
sync_state_factory.dart Sync through Firebase, mirroring to GitHub, and stop re-downloading peers 2026-08-04 23:36:24 +02:00