2 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 7376ff91e0 feat(sync): Storage pane UI for encrypted settings sync (opt-in toggle + restore)
Wires the storage-credential sync (6f7f4196) into the profile Storage pane.

UI (components/profile-modal.html): a "Cross-device sync" card shown only when
storage is unlocked — an opt-in toggle ("Sync these settings to my Nostr account
(encrypted)"), a "Restore from my Nostr account" button, the public-relay /
key-compromise warning copy, and a status line.

Controller (ProfileStorageController):
- toggle on -> storageSyncService.enable() (encrypt + publish), with rollback +
  message if nothing is stored yet; toggle off -> disable() (wipe the note)
- restore -> pull() + re-render the pane so the restored connection shows
- after a successful Save, re-push the synced copy when sync is enabled

Also routes the core's relay READ through the subscription manager (injected
listEvents) instead of pool.list, satisfying lint:pool-access for the new file;
the facade supplies it via nostrClient.getSubscriptionManager().list.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 17:17:35 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0abb82b933 feat(sync): encrypted cross-login settings sync core (NIP-78, opt-in)
Shared core for the opt-in encrypted sync of bitvid settings (storage creds, NWC
wallet) recorded in todo #15. Publishes settings as NIP-78 app-data (kind 30078)
REPLACEABLE events, NIP-44-encrypted to the user's own key (NIP-04 fallback when
the signer lacks NIP-44).

js/nostr/encryptedSync.js — createEncryptedSyncManager(deps):
  - isAvailable(): signer present + can encrypt to self
  - push(dTag, payload): encrypt-to-self -> publish to WRITE relays, created_at
    forced strictly-newer so a replace actually wins
  - pull(dTag): read newest-per-d-tag from read relays -> decrypt (a stale device
    cannot clobber newer settings)
  - clear(dTag): publish a cleared marker so the wipe propagates (empty-
    replaceable-publish lesson)

Dependency-injected (pure) so it unit-tests without a live signer/relay. No UI
wiring yet — no behavior change. Storage pane wiring is the next increment.

Security: encryption hides contents but not that this pubkey stores bitvid
settings (public relays); anyone with the user's key can decrypt; NWC URIs are
spending secrets (caller must gate behind a warning); never log decrypted data.

tests/encrypted-sync.test.mjs — round-trip, no-cleartext-leak, newest-wins,
clear, NIP-04 fallback. Mutation-verified (newest-selection + encryption-bypass
both fail the suite).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 16:52:44 -04:00