The most foundational Block-2+ gap: the data model was built CRDT-ready
(HLC, tombstones, LWW, append-only Movement) and the import reconciler
proves the merge — but nothing replicated a device's inventory to your
OTHER devices. Only manual file backup/restore moved data between devices.
This lands the transport foundation in commons_core (seed-agnostic, on the
shared connection — the 'one connection, N interfaces' shape):
- SyncTransport: moves an opaque, encrypted snapshot blob between ONE
identity's own devices. The core carries bytes + does the crypto; the app
decides what the bytes are and how to merge them.
- NostrSyncTransport: NIP-78 app-data (kind 30078, addressable/replaceable
per device via the d-tag), content NIP-44-encrypted TO SELF, discovery
filtered to your own author key. Each device keeps one replaceable record.
Tests (MiniRelay, pure Dart): a snapshot replicates to the identity's other
device; the relay only ever sees ciphertext; another identity neither
receives nor could decrypt; re-push replaces; two devices keep their own.
Confirms the open-decisions §D.4 guarantee (sync leaks neither the key nor
plaintext). NEXT slice (app): a SyncService that serializes the inventory
(reusing ExportImportService), pushes on mutation, and runs the existing
idempotent importInventory on receive; a stable per-install device id;
wire sync into SocialSession.