diff --git a/doc/BACKGROUND_DATA_FETCHING_PLAN.md b/doc/BACKGROUND_DATA_FETCHING_PLAN.md index 0d39114..758301f 100644 --- a/doc/BACKGROUND_DATA_FETCHING_PLAN.md +++ b/doc/BACKGROUND_DATA_FETCHING_PLAN.md @@ -3,7 +3,7 @@ **Author**: Matthew Raymer **Version**: 1.0.0 **Created**: 2025-10-02 07:47:04 UTC -**Last Updated**: 2025-10-02 10:15:00 UTC +**Last Updated**: 2025-10-02 10:45:00 UTC ## Overview @@ -70,7 +70,7 @@ class JWTHelper { // Background HTTP Worker class DataFetchWorker : CoroutineWorker { suspend fun doWork(): Result { - val jwt = generateJWT(userDid, 60) + val jwt = generateJWT(activeDid, 60) val headers = mapOf( "Authorization" to "Bearer $jwt", "Content-Type" to "application/json" @@ -78,7 +78,7 @@ class DataFetchWorker : CoroutineWorker { val offersResponse = httpClient.get("$apiServer/api/v2/report/offers") { headers { headers.forEach { append(it.key, it.value) } } - parameter("recipientDid", userDid) + parameter("recipientId", activeDid) // Use activeDid for recipient filtering parameter("afterId", lastKnownOfferId) } @@ -118,7 +118,7 @@ class JWTHelper { // Background HTTP Task class DataFetchTask { func fetchData() async { - let jwt = generateJWT(userDid: userDid, expiresInSeconds: 60) + let jwt = generateJWT(userDid: activeDid, expiresInSeconds: 60) var request = URLRequest(url: apiURL) request.setValue("Bearer \(jwt)", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") @@ -173,7 +173,7 @@ interface PluginConfig { jwtExpirationSeconds: number; requestTimeoutMs: number; retryAttempts: number; - userDid: string; + activeDid: string; // Simplified to single active DID lastKnownOfferId?: string; lastKnownPlanId?: string; } @@ -203,11 +203,22 @@ interface PluginConfig { ### Data Persistence -- **Android Room database** for caching API responses -- **iOS Core Data** for persistent storage -- **Web IndexedDB** for web platform caching -- **TTL enforcement** for cached data freshness -- **SQLite integration** via @capacitor-community/sqlite for unified storage across platforms +#### **Platform-Specific Storage Architecture** + +**Android/Electron Platforms:** +- **@capacitor-community/sqlite** plugin integration for native SQLite access +- **Shared plugin database** - Plugin manages its own SQLite database instance +- **Direct SQL execution** via plugin's `dbExec()` methods for complex queries +- **Background worker integration** for database operations during content fetch + +**Web Platform:** +- **absurd-sql** for SQLite support in browser (managed by host application) +- **Plugin delegation pattern** - Plugin provides SQL queries, host executes them +- **IndexedDB fallback** for basic caching when SQLite unavailable + +**iOS Platform:** +- **Core Data integration** via native Swift implementation +- **Background task compatibility** with iOS background refresh constraints ### State Synchronization @@ -243,11 +254,78 @@ Based on TimeSafari's optimization patterns: ## Integration Points -### Existing Plugin APIs +### Enhanced Plugin Interface for Host Application Integration + +#### **Database Integration Patterns** + +**Android/Electron: Plugin-Managed SQLite** +```typescript +// Plugin handles database operations directly +await plugin.configure({ + dbPath: 'daily_notifications.db', + storage: 'shared' +}); + +// Plugin provides database access methods +const results = await plugin.executeContentFetch(config); +await plugin.cacheContentData(results); + +// Host application accesses cached data via plugin +const cachedData = await plugin.getContentCache(); +``` + +**Web: Host-Managed Database** +```typescript +// Host application manages absurd-sql database +import { openDatabase } from 'absurd-sql'; + +const db = await openDatabase('daily_notifications.db'); + +// Plugin provides SQL queries, host executes them +const query = await plugin.getContentFetchQuery(apiEndpoint, credentials); +const results = await db.exec(query); -- **Extend** `DailyNotification.configure()` to include API server settings -- **Add** new methods: `setUserCredentials()`, `fetchActivityData()`, `getCachedData()` -- **Trigger** notifications based on fetched data differences +// Plugin receives results for processing +await plugin.processContentData(results); +``` + +**iOS: Hybrid Approach** +```typescript +// Plugin manages Core Data operations on background thread +await plugin.scheduleContentFetch(config); + +// Host application accesses stored data via plugin APIs +const notificationData = await plugin.getLastNotification(); +const cachedContent = await plugin.getContentHistory(); +``` + +#### **New Plugin Methods Required** + +```typescript +interface EnhancedDailyNotificationPlugin { + // Database configuration + configureDatabase(options: { + storageType: 'plugin-managed' | 'host-managed'; + dbPath?: string; + encryption?: boolean; + }): Promise; + + // Content fetch with database integration + fetchAndStoreContent(config: ContentFetchConfig): Promise; + + // Credential management - simplified to activeDid only + setActiveDid(activeDid: string): Promise; + + // Data access for host application + getStoredContent(query: string, params?: any[]): Promise; + clearStoredContent(options?: { olderThan?: number }): Promise; + + // Background task coordination + getBackgroundTaskStatus(): Promise; + pauseBackgroundTasks(): Promise; + resumeBackgroundTasks(): Promise; +} +``` ### Background Scheduling @@ -343,8 +421,9 @@ GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={j ### Token Generation -- Accept user DID as input -- Generate appropriate authentication token based on user's credential type +- Accept activeDid as input +- Generate JWT authentication token using DID signing +- Include activeDid as both issuer (`iss`) and subject (`sub`) - Return token for immediate use or caching ### Request Execution @@ -374,7 +453,11 @@ GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={j - Implement DID-based authentication - Integrate API endpoint calls - Add response parsing and validation -- Implement basic caching +- Implement platform-specific database integration: + - **Android/Electron**: Direct @capacitor-community/sqlite integration + - **Web**: Plugin delegation pattern with absurd-sql coordination + - **iOS**: Core Data background thread integration +- Implement simplified activeDid-based authentication and API calls ### Phase 3: Background Integration (Weeks 5-6)