# Future Sync Strategy: Keeping Local and Public Clones in Sync ## Current State (v1) - Sharing creates a **ONE-TIME COPY** from local to public - Copies diverge independently after sharing - No automatic sync between local and public versions - Local diagrams are browser-only (IndexedDB via PouchDB) - Public diagrams sync with server via express-pouchdb ### URL Scheme | Route | Sync | Access | Status | |-------|------|--------|--------| | `/db/local/:id` | None | Browser-only | Implemented | | `/db/public/:id` | Yes | Anyone | Implemented | | `/db/private/:id` | Yes | Authorized users | Route only (no auth) | ## Future Options ### Option 1: Manual Push/Pull (Recommended for v2) Add explicit user-triggered sync between local and public copies. **Features:** - "Push to Public" button - sends local changes to public copy - "Pull from Public" button - gets public changes into local - Track `lastSyncedAt` timestamp - Show indicator when copies have diverged - Conflict resolution: Last write wins (simple) or user choice (advanced) **Pros:** - User stays in control - Clear mental model - Simple to implement incrementally **Cons:** - Manual effort required - Risk of forgetting to sync ### Option 2: Automatic Background Sync Continuous bidirectional sync between local and public copies. **Features:** - Real-time sync like Google Docs - Works across devices - Offline-first with automatic merge **Pros:** - Seamless experience - Always up to date **Cons:** - Complex conflict resolution (may need CRDTs) - Higher performance overhead - Harder to reason about state ### Option 3: Fork/Branch Model One-way relationship: local is "draft", public is "published". **Features:** - Push only (local → public) - No pull mechanism - Public is the "source of truth" once published **Pros:** - Clear mental model - No merge conflicts - Simple implementation **Cons:** - Cannot incorporate public changes back to local - Multiple people can't collaborate on draft ## Recommended Implementation (v2) Implement **Option 1 (Manual Push/Pull)** as it provides the best balance of user control and simplicity. ### Data Model Changes Add to diagram directory entry: ```typescript interface DiagramEntry { _id: string; name: string; description: string; storageType: 'local' | 'public' | 'private'; createdAt: string; // New fields for sync tracking publicCopyId?: string; // ID of the public clone (if shared) lastPushedAt?: string; // When changes were last pushed to public lastPulledAt?: string; // When public changes were last pulled publicVersion?: number; // Version number of public copy at last sync } ``` ### API Endpoints ```typescript // Push local changes to public POST /api/sync/push Body: { localDbName: string, publicDbName: string } Response: { success: boolean, documentsUpdated: number } // Pull public changes to local POST /api/sync/pull Body: { localDbName: string, publicDbName: string } Response: { success: boolean, documentsUpdated: number } // Check if copies have diverged GET /api/sync/status?local={localDbName}&public={publicDbName} Response: { diverged: boolean, localChanges: number, publicChanges: number, lastSyncedAt: string } ``` ### UI Components 1. **Sync Status Indicator** - Shows in header when viewing a local diagram that has a public copy - Green check: In sync - Orange dot: Changes pending - Red warning: Conflicts detected 2. **Push/Pull Buttons** - In hamburger menu under "Share" section - "Push to Public" - shows confirmation with change count - "Pull from Public" - shows confirmation with change count 3. **Divergence Warning Badge** - Shows on diagram card in Manage Diagrams modal - Indicates when local and public have diverged 4. **Conflict Resolution Dialog** - Shows when both local and public have changes to same entity - Options: Keep Local, Keep Public, Keep Both (creates duplicate) ### Implementation Phases **Phase 1: Tracking** - Add `publicCopyId` when sharing local → public - Track sharing relationship in directory **Phase 2: Push** - Implement push from local to public - Overwrite public with local changes - Update `lastPushedAt` timestamp **Phase 3: Pull** - Implement pull from public to local - Merge public changes into local - Update `lastPulledAt` timestamp **Phase 4: Status** - Implement divergence detection - Add UI indicators - Show sync status in Manage Diagrams **Phase 5: Conflict Resolution** - Detect entity-level conflicts - Show resolution dialog - Allow user to choose resolution strategy ## Migration Notes Existing diagrams without `storageType` are treated as `public` for backwards compatibility. When such diagrams are loaded, the UI should work correctly but sync tracking features won't be available until the diagram metadata is updated. ## Security Considerations - Push/pull operations should validate that the user has access to both databases - Public databases remain world-readable/writable - Private database sync will require authentication tokens - Rate limiting should be applied to sync operations