Skip to content

Phase 5: Offline Support & PWA Integration #196

@kevalyq

Description

@kevalyq

🎯 Goal

Integrate secret management with PWA infrastructure: IndexedDB caching, offline sync queue, background sync, and conflict resolution.


🔗 Parent Epic

Part of: #191 (Secret Management Frontend)


📋 Tasks

IndexedDB Secret Store

  • Create stores/secretStore.ts using Dexie.js
  • Define secret schema (id, title, username, encrypted fields, timestamps)
  • Implement saveSecret(secret) function
  • Implement getSecret(id) function
  • Implement listSecrets() function
  • Implement deleteSecret(id) function
  • Add indexing for search/filter
  • Add expiration tracking

Offline Sync Queue

  • Integrate with existing fileQueue.ts (from PWA epic)
  • Add secret operations to queue (create, update, delete)
  • Implement queue processing
  • Add exponential backoff retry logic
  • Store pending operations in IndexedDB

Service Worker Integration

  • Extend sw.ts with secret API caching
  • Add NetworkFirst strategy for secret list
  • Add StaleWhileRevalidate for secret details
  • Implement background sync for secret operations
  • Add sync event listeners

Offline Indicators

  • Create OfflineSecretBadge.tsx component
  • Show "Offline" badge on cached secrets
  • Show "Syncing..." badge on pending operations
  • Show "Conflict" badge on sync errors
  • Display last sync timestamp

Conflict Resolution

  • Implement conflict detection (version mismatch)
  • Create ConflictResolutionDialog.tsx component
  • Show local vs remote changes
  • Allow user to choose: Keep Local / Keep Remote / Merge
  • Implement Last-Write-Wins (LWW) strategy as default

Sync Status UI

  • Add sync status indicator to secret list header
  • Show pending operation count
  • Add "Sync Now" button
  • Display sync errors with retry button

Tests

  • Unit tests for secretStore.ts (≥80% coverage)
  • Unit tests for sync queue logic
  • Unit tests for conflict detection
  • Integration test: Create secret offline → Sync when online
  • Integration test: Edit secret offline → Conflict resolution
  • Integration test: Delete secret offline → Sync when online

🎨 UI Mockup

Offline Secret Card

┌──────────────────────────────────┐
│ 🔒 Gmail Account     📴 Offline  │
│ user@email.com                   │
│ #work #email                     │
│ 📎 2  👥 3                       │
└──────────────────────────────────┘

Sync Status Indicator

┌─────────────────────────────────────────────────────────┐
│ Secrets                  ⏳ 3 pending  [Sync Now]  [+]  │
├─────────────────────────────────────────────────────────┤
│ Last synced: 2 minutes ago                              │
└─────────────────────────────────────────────────────────┘

Conflict Resolution Dialog

┌─────────────────────────────────────────────────────────┐
│ 🔀 Conflict Detected                             [✕]    │
├─────────────────────────────────────────────────────────┤
│ The secret "Gmail Account" was modified both offline    │
│ and on the server. Choose which version to keep:        │
│                                                         │
│ Local Version (Your Changes)                            │
│ ├─ Title: Gmail Account                                │
│ ├─ Username: user@example.com                          │
│ ├─ Password: ••••••••• (changed)                       │
│ └─ Modified: 5 minutes ago                             │
│                                                         │
│ Remote Version (Server)                                │
│ ├─ Title: Gmail Account                                │
│ ├─ Username: user@example.com                          │
│ ├─ Password: ••••••••• (different)                     │
│ └─ Modified: 2 minutes ago                             │
│                                                         │
│         [Keep Local] [Keep Remote] [Merge]             │
└─────────────────────────────────────────────────────────┘

🔗 API Endpoints (Backend)

All existing secret endpoints remain the same. This phase adds offline support:

// Standard sync flow:
// 1. User creates/edits secret offline → saved to IndexedDB
// 2. Operation added to sync queue
// 3. When online, queue processes: POST/PATCH to backend API
// 4. On success, update IndexedDB with server response
// 5. On conflict (409), show resolution dialog

✅ Acceptance Criteria

  • Secrets cached in IndexedDB
  • Create/Edit/Delete works offline
  • Offline operations queue correctly
  • Background sync processes queue when online
  • Offline badges show on cached secrets
  • Sync status indicator updates in real-time
  • Conflict detection works correctly
  • Conflict resolution dialog shows differences
  • User can choose conflict resolution strategy
  • All tests pass (≥80% coverage)
  • Works fully offline after first load
  • No data loss during offline operations

🔒 Security Notes

  • ⚠️ Encrypted data stored in IndexedDB (consider browser security)
  • ⚠️ Clear sensitive data after sync
  • ⚠️ Handle auth token expiration during offline period
  • ⚠️ Re-authenticate before syncing if token expired
  • ⚠️ Never expose passwords in conflict resolution UI

📊 Estimated Effort

Size: ~600-700 LOC (excluding tests)
Time: 5-6 days
PR Count: 1 PR


🔗 Dependencies


🔗 Blocks

Nothing - This is the final phase of Epic #191


Type: Sub-Issue of #191
Priority: High
Estimated Effort: L (5-6 days)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    💡 Ideas

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions