mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 22:47:14 +01:00
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWXTUM9dpnCS2wtFkx4
1.8 KiB
1.8 KiB
Encrypt crdt_sync payloads end to end
what
Firebase RTDB stores every crdt_sync record in plaintext, so Google can read all app data. Encrypt record payloads on the device before push and decrypt after pull, so RTDB stays a blind relay (the "ownership" meaning of local-first: hologram.page/blog/local-first-means-three-different-things).
open decisions (ask kuhy before coding)
- Key source: derived from the shared crdt-sync password (Argon2id) or a random key stored in the OS keystore and copied to new devices.
- Migration: re-encrypt existing logs in place, or new prefix + one-time copy.
- Scope: payload only (keep HLC/ids clear for merge) or whole record.
- diet_guard's
export_keysdocument (random data-export keys, synced as a keyring) sits in plaintext in RTDB, so Firebase can read them: it must move under E2E too, with its key source decided here first. - tutor uses its own RTDB client (
~/src/tutor/app/lib/sync/rtdb_client.dart): in or out of scope.
steps
- Add an encrypt/decrypt seam in
crdt_sync_dart/lib/src/remote_store.dart(push/pull), AEAD (XChaCha20-Poly1305), version byte per record. - Property test: decrypt(encrypt(r)) == r; merge result identical with and without encryption (see property-and-differential-tests skill).
- Read path accepts plaintext and v1 records during migration.
- Roll out app by app (todo first), bump pins, verify on the phone.
done
dart test in crdt_sync_dart passes, and
firebase database:get /<prefix> | grep -c '"title"' returns 0 for every
migrated app.
verify
Pixel 6a + desktop todo: edit on one, see it on the other; raw RTDB JSON shows only ciphertext.
read first
crdt_sync_dart/lib/src/sync.dart,log.dart,remote_store.dartcrdt_sync_flutter/lib/src/bootstrap.dart
REMOVE ME AFTER FINISH