Commit Graph

6 Commits

Author SHA1 Message Date
Jeff Emmett 46c2a0b035 feat: layered local-first data architecture — encrypted backup, relay persistence, at-rest encryption
Implement the 4-layer data model (device → encrypted backup → shared sync → federated):

- Extract shared encryption-utils from community-store (deriveSpaceKey, AES-256-GCM, rSEN format)
- Encrypt module docs at rest when space has meta.encrypted === true
- Fix relay mode persistence: relay-backup/relay-restore wire protocol + .automerge.enc blob storage
- Add backup store + REST API (PUT/GET/DELETE /api/backup/:space/:docId) with JWT auth
- Add client BackupSyncManager with delta-only push, full restore, auto-backup
- Wire backup stubs in encryptid-bridge to BackupSyncManager
- Add rspace-backups Docker volume
- Create docs/DATA-ARCHITECTURE.md design doc with threat model and data flow diagrams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:09:07 -08:00
Jeff Emmett 22db2f439f feat: client-side encryption wiring + space scoping UI (Phase 5+6)
Phase 5 — EncryptID → DocCrypto bridge:
- Add EncryptedDocBridge connecting WebAuthn PRF to document encryption
- Add per-doc relay mode to SyncServer (encrypted spaces bypass participant mode)
- Wire encryption toggle to syncServer.setRelayOnly() on PATCH /:slug/encryption
- Restore relay mode for encrypted spaces on server startup
- Initialize DocBridge from PRF on login, clear on sign-out (both login-button + identity)
- Use bridge helpers for encrypted backup toggle in My Account

Phase 6 — Space scoping UI:
- Add "Modules" tab to Edit Space modal (enable/disable modules, scope toggles, encryption)
- Auto-filter app switcher by space's enabledModules via renderShell()
- Show "G" badge on global-scoped modules in app switcher
- Show lock icon in header for encrypted spaces
- Add getSpaceShellMeta() helper for auto-populating shell options

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:50:16 -08:00
Jeff Emmett 6a7f21dc19 feat: rNotes local-first pilot migration (Phase 2)
Migrate rNotes from PostgreSQL to Automerge local-first stack with
dual-write support. Reads go Automerge-first with PG fallback; writes
go to both backends during the migration window.

- Add Automerge schemas for NotebookDoc (schemas.ts)
- Add lifecycle hooks (onInit, onSpaceCreate) to rnotes module
- Dual-write all 8 API routes (notebooks + notes CRUD)
- Add NotesLocalFirstClient wrapping DocSyncManager + EncryptedDocStore
- Enhance migration runner with --dry-run, --module, --verify flags
- Add listDocs() to SyncServer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:51:31 -08:00
Jeff Emmett e3fc578465 feat: run PG→Automerge migration — 19 docs, 292 rows, 0 errors
Added run-migration.ts script and getDocIds() method on SyncServer.
All 11 module adapters ran successfully against live demo data.
Docs persisted to /data/docs/, backups to /data/docs-backup/.
Idempotent: re-runs skip existing docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 06:10:51 +00:00
Jeff Emmett 0fb4135ac6 feat: wire DocSyncManager into rSpace WebSocket server
Protocol multiplexing on existing /ws/{slug} endpoint:
- Messages with docId (subscribe/unsubscribe/sync/awareness) → SyncServer
- Messages without docId → legacy canvas handlers (unchanged)

New files: doc-persistence.ts (debounced Automerge save/load),
sync-instance.ts (SyncServer singleton with participant mode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 05:19:21 +00:00
Jeff Emmett 2d5103c7d6 Add 7-layer local-first data infrastructure
Crypto (PRF/HKDF/AES-256-GCM per-doc keys), Document (schema + manager),
Storage (encrypted IndexedDB), Sync (multi-doc WebSocket client + server),
Compute (local/server-delegated transforms), Query (views + search),
and Memory Card interchange format. 2919 lines across 10 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:12:06 +00:00