Context
SyncCoordinator currently hardcodes the mapping of "when this changes, mark that domain dirty":
settings.onProfileChanged = { store?.markDirty(.profile) }
driversRepo.onDriversChanged = { source in
guard source == .local else { return }
store?.markDirty(.followedDrivers)
}
This is protocol semantics — "profile name changes → Kind 0 sync needed" — that the SDK should own. The app shouldn't be thinking about which Nostr event kinds correspond to which domain changes.
What needs doing
- Create
SyncDomainTracker (or extend RoadflareSyncStateStore) in the SDK
- Move change-tracking callback setup into SDK:
tracker.wireCallbacks(settings:, drivers:, ...)
- The SDK defines the mapping: settings changes → profile dirty, driver changes → followedDrivers dirty, etc.
- Simplify app-layer
SyncCoordinator to call tracker.wireCallbacks() during setup
- Keep
performStartupSync() and flushPendingSyncPublishes() in SyncCoordinator as-is (correct app-layer orchestration)
Why this matters
Pattern reference
SyncDomainResolver already owns the resolution logic in the SDK. SyncDomainTracker would own the detection side, completing the SDK's ownership of the sync lifecycle.
Context
SyncCoordinator currently hardcodes the mapping of "when this changes, mark that domain dirty":
This is protocol semantics — "profile name changes → Kind 0 sync needed" — that the SDK should own. The app shouldn't be thinking about which Nostr event kinds correspond to which domain changes.
What needs doing
SyncDomainTracker(or extendRoadflareSyncStateStore) in the SDKtracker.wireCallbacks(settings:, drivers:, ...)SyncCoordinatorto calltracker.wireCallbacks()during setupperformStartupSync()andflushPendingSyncPublishes()in SyncCoordinator as-is (correct app-layer orchestration)Why this matters
Pattern reference
SyncDomainResolveralready owns the resolution logic in the SDK.SyncDomainTrackerwould own the detection side, completing the SDK's ownership of the sync lifecycle.