From 2f02e5661b74aa6bf44b9a1cefa224a772e17164 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Thu, 2 Oct 2025 09:51:42 +0000 Subject: [PATCH] enhance: Update BACKGROUND_DATA_FETCHING_PLAN.md to align with current implementation - Added Current Implementation Baseline section documenting existing functionality - Updated authentication examples to enhance existing DailyNotificationETagManager.java - Modified HTTP request implementation to extend existing DailyNotificationFetcher.java - Updated plugin interface to extend current DailyNotificationPlugin rather than replace - Corrected implementation phases to build upon existing infrastructure: * Phase 1: Extend core infrastructure (not rebuild) * Phase 2: Add activeDid integration to existing methods * Phase 3: Enhance existing background integration * Phase 4: Add TimeSafari-specific features - Updated Android examples to show enhancement of existing SQLite + SharedPreferences - Updated Web examples to enhance existing IndexedDB (no host delegation initially) - Changed status from 'implementation plan' to 'enhancement plan for existing implementation' - Aligned dependencies with existing plugin infrastructure rather than new requirements The plan now accurately reflects building upon our working plugin instead of rebuilding from scratch, providing a realistic enhancement roadmap. --- doc/BACKGROUND_DATA_FETCHING_PLAN.md | 225 ++++++++++++++------------- 1 file changed, 120 insertions(+), 105 deletions(-) diff --git a/doc/BACKGROUND_DATA_FETCHING_PLAN.md b/doc/BACKGROUND_DATA_FETCHING_PLAN.md index c3f9ac8..ac225b6 100644 --- a/doc/BACKGROUND_DATA_FETCHING_PLAN.md +++ b/doc/BACKGROUND_DATA_FETCHING_PLAN.md @@ -7,16 +7,34 @@ ## Overview -This document outlines the **complete implementation plan** for background data fetching in the Capacitor Daily Notification Plugin, replacing web push implementations with native platform solutions. This consolidated plan includes: - -- **Option A Architecture**: Host always provides activeDid approach -- **TimeSafari Integration**: PlatformServiceMixin coordination patterns -- **Cross-Platform Implementation**: Android/Electron, iOS, Web specifications -- **Database Access Patterns**: Clear separation between host and plugin storage -- **ActiveDid Change Management**: Event-based notification and cache invalidation -- **Security Requirements**: Data isolation and authentication patterns - -This document consolidates all previous analysis documents to provide a single source of truth for implementation. +This document outlines the **enhancement plan** for background data fetching in the Daily Notification Plugin to support TimeSafari integration with Option A architecture. This plan builds upon our existing implementation and adds: + +- **Option A Enhancement**: ActiveDid-aware authentication on existing infrastructure +- **TimeSafari Integration**: PlatformServiceMixin coordination with current plugin +- **Authentication Layer**: JWT/DID support over existing HTTP callback system +- **Database Enhancement**: Extend current storage with activeDid management +- **Event & Change Management**: Identity change detection on existing notification system +- **API Integration**: Endorser.ch endpoints through current ContentFetchConfig + +This document serves as the enhancement roadmap for adding TimeSafari capabilities to our existing, working plugin. + +## Current Implementation Baseline + +### ✅ Already Implemented & Working +- **Android Storage**: SharedPreferences + SQLite with migration (`DailyNotificationStorage.java`, `DailyNotificationDatabase.java`) +- **Web Storage**: IndexedDB with comprehensive service worker (`sw.ts`, `IndexedDBManager`) +- **Callback System**: HTTP/local callbacks with circuit breaker (`callback-registry.ts`) +- **Configuration**: Database path, TTL, retention settings (`ConfigureOptions`) +- **ETag Support**: Conditional HTTP requests (`DailyNotificationETagManager.java`) +- **Dual Scheduling**: Content fetch + user notification separation +- **Cross-Platform API**: Unified TypeScript interface (`DailyNotificationPlugin`) + +### ⚠️ Enhancement Required for TimeSafari +- **ActiveDid Integration**: Add activeDid-awareness to existing authentication +- **JWT Generation**: Enhance HTTP layer with DID-based tokens +- **Identity Change Detection**: Add event listeners to existing callback system +- **Endorser.ch APIs**: Extend `ContentFetchConfig` with TimeSafari endpoints +- **Platform Auth**: Add Android Keystore/iOS Keychain to existing storage ## Consolidated Architecture: Option A Platform Overview @@ -50,61 +68,64 @@ Daily Notification Plugin → Native Background Executor ### A. Background Execution Framework - **Use WorkManager** for reliable background HTTP requests -- **Replace axios** with native Android HTTP clients: - - OkHttp for synchronous requests - - Retrofit for type-safe API interfaces +- **Enhance** existing Native HTTP clients (already implemented): + - Extend `DailyNotificationETagManager.java` with JWT headers + - Add JWT authentication to `DailyNotificationFetcher.java` - **Handle Android-specific constraints**: Doze mode, app standby, battery optimization -### B. Authentication Implementation +### B. Authentication Enhancement - Extend Current Infrastructure + +**Goal**: Enhance existing `DailyNotificationETagManager.java` and `DailyNotificationFetcher.java` with JWT authentication ```kotlin -// JWT Generation in Android - Enhanced with DID support -class JWTHelper { - fun generateJWT(userDid: String, expiresInSeconds: Int): String { +// Enhance existing Android infrastructure with JWT authentication +class DailyNotificationJWTManager { + private val storage: DailyNotificationStorage + private val currentActiveDid: String? = null + + // Add JWT generation to existing fetcher + fun generateJWTForActiveDid(activeDid: String, expiresInSeconds: Int): String { val payload = mapOf( "exp" to (System.currentTimeMillis() / 1000 + expiresInSeconds), "iat" to (System.currentTimeMillis() / 1000), - "iss" to userDid, - // Include DID-specific claims for verification + "iss" to activeDid, "aud" to "timesafari.notifications", - "sub" to userDid + "sub" to activeDid ) - return signWithDID(payload, userDid) + return signWithDID(payload, activeDid) } - // Enhanced authentication with Passkey support - fun generateJWANT(userDid: String, biometricData: ByteArray): String { - val payload = mapOf( - "exp" to (System.currentTimeMillis() / 1000 + 3600), // 1 hour - "iat" to (System.currentTimeMillis() / 1000), - "iss" to userDid, - "aud" to "timesafari.notifications", - "sub" to userDid, - "auth_data" to android.util.Base64.encodeToString(biometricData, android.util.Base64.NO_WRAP) - ) - return signWithDIDPasskey(payload, userDid, biometricData) + // Enhance existing HTTP client with JWT headers + fun enhanceHttpClientWithJWT(connection: HttpURLConnection, activeDid: String) { + val jwt = generateJWTForActiveDid(activeDid, 60) + connection.setRequestProperty("Authorization", "Bearer $jwt") + connection.setRequestProperty("Content-Type", "application/json") } } -### C. HTTP Request Implementation +### C. HTTP Request Enhancement - Extend Existing Fetcher + +**Goal**: Enhance existing `DailyNotificationFetcher.java` with Endorser.ch API support ```kotlin -// Background HTTP Worker -class DataFetchWorker : CoroutineWorker { - suspend fun doWork(): Result { - val jwt = generateJWT(activeDid, 60) - val headers = mapOf( - "Authorization" to "Bearer $jwt", - "Content-Type" to "application/json" - ) +// Enhance existing DailyNotificationFetcher.java with TimeSafari APIs +class EnhancedDailyNotificationFetcher : DailyNotificationFetcher { + private val jwtManager: DailyNotificationJWTManager + + suspend fun fetchEndorserOffers(activeDid: String, afterId: String?): Result { + val connection = HttpURLConnection("$apiServer/api/v2/report/offers") - val offersResponse = httpClient.get("$apiServer/api/v2/report/offers") { - headers { headers.forEach { append(it.key, it.value) } } - parameter("recipientId", activeDid) // Use activeDid for recipient filtering - parameter("afterId", lastKnownOfferId) + // Add JWT authentication to existing connection + jwtManager.enhanceHttpClientWithJWT(connection, activeDid) + + // Add Endorser.ch specific parameters + connection.setRequestProperty("recipientDid", activeDid) + if (afterId != null) { + connection.setRequestProperty("afterId", afterId) } - return storeAndScheduleNotification(offersResponse.body()) + // Use existing storeAndScheduleNotification method + return fetchAndStoreContent(connection) } } ``` @@ -411,40 +432,34 @@ await plugin.configureDatabase({ const results = await plugin.executeBackgroundContentFetch(); ``` -#### **New Plugin Methods Required** +#### **Enhancement Required: Extend Current Plugin Interface** + +**Current Interface** (already implemented): +```typescript +interface DailyNotificationPlugin { + configure(options: ConfigureOptions): Promise; + scheduleContentFetch(config: ContentFetchConfig): Promise; + scheduleUserNotification(config: UserNotificationConfig): Promise; + // ... existing methods (see definitions.ts) +} +``` +**Enhancement Required** (add to existing interface): ```typescript -interface EnhancedDailyNotificationPlugin { - // Database configuration - Simplified Option A approach - configureDatabase(options: { - platform: 'android' | 'ios' | 'web' | 'electron'; - storageType: 'plugin-managed' | 'host-managed'; - dbPath?: string; - encryption?: boolean; +interface EnhancedDailyNotificationPlugin extends DailyNotificationPlugin { + // Enhanced configuration with activeDid support + configure(options: ConfigureOptions & { + activeDidIntegration?: { + platform: 'android' | 'ios' | 'web' | 'electron'; + storageType: 'plugin-managed' | 'host-managed'; + }; }): Promise; // Host-provided activeDid Management (Option A Implementation) setActiveDidFromHost(activeDid: string): Promise; - // Content fetch with database integration - fetchAndStoreContent(config: ContentFetchConfig): 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; - - // TimeSafari Integration Methods - initializeFromTimeSafari(): Promise; - listenForActiveDidChanges(): Promise; - // Critical: ActiveDid Change Handling onActiveDidChange(callback: (newActiveDid: string) => Promise): void; - clearCacheForNewIdentity(): Promise; refreshAuthenticationForNewIdentity(activeDid: string): Promise; } ``` @@ -579,38 +594,38 @@ GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={j ## Implementation Phases -### Phase 1: Core Infrastructure (Weeks 1-2) +### Phase 1: Extend Core Infrastructure (Building on Existing) -- Set up native HTTP clients for Android/iOS -- Implement basic JWT generation -- Create plugin configuration interfaces -- Set up basic error handling +- **Extend existing** Android `DailyNotificationFetcher.java` with JWT authentication +- **Enhance existing** iOS implementation (when added) with authentication layer +- **Add JWT generation** to existing `DailyNotificationETagManager.java` +- **Enhance current** `ConfigureOptions` with activeDid integration +- **Build on existing** error handling (circuit breaker already implemented) -### Phase 2: Host-Provided activeDid Integration & API Access (Weeks 3-4) +### Phase 2: ActiveDid Integration & TimeSafari API Enhancement -- Implement host-provided activeDid management (Option A approach) -- Add `setActiveDidFromHost()` method (no database access needed) -- Remove database sharing complexity - host always provides activeDid -- Integrate API endpoint calls with activeDid-based authentication -- Add response parsing and validation -- Implement platform-specific database integration: - - **Android/Electron**: Plugin-managed @capacitor-community/sqlite (no host database access) - - **Web**: Host-managed storage delegation (plugin doesn't access absurd-sql directly) - - **iOS**: Plugin-managed Core Data (no host database access) +- **Add** host-provided activeDid management to existing plugin interface +- **Extend** existing `configure()` method with activeDid options +- **Enhance** existing `ContentFetchConfig` with Endorser.ch API endpoints +- **Add** `setActiveDidFromHost()` and `onActiveDidChange()` to existing interface +- **Integrate** existing `callback-registry.ts` with activeDid-aware callbacks +- **Enhance** existing platform storage: + - **Android**: Extend existing SQLite with activeDid-aware JWT storage + - **Web**: Enhance existing IndexedDB with activeDid support (no host delegation needed initially) -### Phase 3: Background Integration (Weeks 5-6) +### Phase 3: Background Enhancement & TimeSafari Coordination -- Integrate with WorkManager/BGTaskScheduler -- Coordinate with notification scheduling -- Handle app lifecycle events -- Implement state synchronization +- **Enhance** existing WorkManager integration with activeDid-aware workers +- **Coordinate** existing notification scheduling with TimeSafari PlatformServiceMixin +- **Extend** existing app lifecycle handling with activeDid change detection +- **Enhance** existing state synchronization with identity management -### Phase 4: Advanced Features (Weeks 7-8) +### Phase 4: TimeSafari Integration & Advanced Features -- Add passkey authentication support -- Implement advanced caching strategies -- Optimize performance and memory usage -- Add comprehensive testing +- **Integrate** with TimeSafari's existing PlatformServiceMixin patterns +- **Add** Endorser.ch API endpoint support to existing `ContentFetchConfig` +- **Implement** DID-based authentication alongside existing callback system +- **Enhance** existing testing with TimeSafari-specific scenarios ## Success Criteria @@ -641,12 +656,12 @@ GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={j --- -**Status**: Host-provided activeDid implementation plan (Option A) - Ready for implementation -**Next Steps**: Begin Phase 1 implementation with Android HTTP client setup -**Dependencies**: Android Studio, Xcode, Capacitor CLI, existing plugin infrastructure, @capacitor-community/sqlite -**Option A Features**: -- **Simplified Architecture**: Host always provides activeDid, no database sharing -- **TimeSafari Integration**: PlatformServiceMixin coordination without database access -- **Cross-Platform**: Android/Electron plugin-managed SQLite, Web host-managed storage, iOS plugin-managed Core Data -- **Authentication**: DID-based JWT with host-provided activeDid -- **Background Tasks**: Event-based activeDid changes, clear separation of concerns +**Status**: Enhancement plan for existing implementation (Option A) - Ready for implementation +**Next Steps**: Begin Phase 1 - enhance existing Android HTTP infrastructure with JWT authentication +**Dependencies**: Existing plugin infrastructure, Android Studio, Capacitor CLI, TimeSafari PlatformServiceMixin +**Enhancement Approach**: +- **Build on Existing**: Leverage current SQLite, IndexedDB, callback system, and dual scheduling +- **Option A Integration**: Add activeDid management to existing configuration and HTTP layers +- **TimeSafari Enhancement**: Extend current ContentFetchConfig with Endorser.ch API endpoints +- **Authentication Layer**: Add JWT/DID authentication over existing HTTP infrastructure +- **Event Integration**: Enhance existing callback system with activeDid change detection