Commit Graph
1 Commits
Author SHA1 Message Date
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