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.
This commit is contained in:
@@ -7,16 +7,34 @@
|
|||||||
|
|
||||||
## Overview
|
## 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:
|
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 Architecture**: Host always provides activeDid approach
|
- **Option A Enhancement**: ActiveDid-aware authentication on existing infrastructure
|
||||||
- **TimeSafari Integration**: PlatformServiceMixin coordination patterns
|
- **TimeSafari Integration**: PlatformServiceMixin coordination with current plugin
|
||||||
- **Cross-Platform Implementation**: Android/Electron, iOS, Web specifications
|
- **Authentication Layer**: JWT/DID support over existing HTTP callback system
|
||||||
- **Database Access Patterns**: Clear separation between host and plugin storage
|
- **Database Enhancement**: Extend current storage with activeDid management
|
||||||
- **ActiveDid Change Management**: Event-based notification and cache invalidation
|
- **Event & Change Management**: Identity change detection on existing notification system
|
||||||
- **Security Requirements**: Data isolation and authentication patterns
|
- **API Integration**: Endorser.ch endpoints through current ContentFetchConfig
|
||||||
|
|
||||||
This document consolidates all previous analysis documents to provide a single source of truth for implementation.
|
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
|
## Consolidated Architecture: Option A Platform Overview
|
||||||
|
|
||||||
@@ -50,61 +68,64 @@ Daily Notification Plugin → Native Background Executor
|
|||||||
### A. Background Execution Framework
|
### A. Background Execution Framework
|
||||||
|
|
||||||
- **Use WorkManager** for reliable background HTTP requests
|
- **Use WorkManager** for reliable background HTTP requests
|
||||||
- **Replace axios** with native Android HTTP clients:
|
- **Enhance** existing Native HTTP clients (already implemented):
|
||||||
- OkHttp for synchronous requests
|
- Extend `DailyNotificationETagManager.java` with JWT headers
|
||||||
- Retrofit for type-safe API interfaces
|
- Add JWT authentication to `DailyNotificationFetcher.java`
|
||||||
- **Handle Android-specific constraints**: Doze mode, app standby, battery optimization
|
- **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
|
```kotlin
|
||||||
// JWT Generation in Android - Enhanced with DID support
|
// Enhance existing Android infrastructure with JWT authentication
|
||||||
class JWTHelper {
|
class DailyNotificationJWTManager {
|
||||||
fun generateJWT(userDid: String, expiresInSeconds: Int): String {
|
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(
|
val payload = mapOf(
|
||||||
"exp" to (System.currentTimeMillis() / 1000 + expiresInSeconds),
|
"exp" to (System.currentTimeMillis() / 1000 + expiresInSeconds),
|
||||||
"iat" to (System.currentTimeMillis() / 1000),
|
"iat" to (System.currentTimeMillis() / 1000),
|
||||||
"iss" to userDid,
|
"iss" to activeDid,
|
||||||
// Include DID-specific claims for verification
|
|
||||||
"aud" to "timesafari.notifications",
|
"aud" to "timesafari.notifications",
|
||||||
"sub" to userDid
|
"sub" to activeDid
|
||||||
)
|
)
|
||||||
return signWithDID(payload, userDid)
|
return signWithDID(payload, activeDid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced authentication with Passkey support
|
// Enhance existing HTTP client with JWT headers
|
||||||
fun generateJWANT(userDid: String, biometricData: ByteArray): String {
|
fun enhanceHttpClientWithJWT(connection: HttpURLConnection, activeDid: String) {
|
||||||
val payload = mapOf(
|
val jwt = generateJWTForActiveDid(activeDid, 60)
|
||||||
"exp" to (System.currentTimeMillis() / 1000 + 3600), // 1 hour
|
connection.setRequestProperty("Authorization", "Bearer $jwt")
|
||||||
"iat" to (System.currentTimeMillis() / 1000),
|
connection.setRequestProperty("Content-Type", "application/json")
|
||||||
"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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
### C. HTTP Request Implementation
|
### C. HTTP Request Enhancement - Extend Existing Fetcher
|
||||||
|
|
||||||
|
**Goal**: Enhance existing `DailyNotificationFetcher.java` with Endorser.ch API support
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// Background HTTP Worker
|
// Enhance existing DailyNotificationFetcher.java with TimeSafari APIs
|
||||||
class DataFetchWorker : CoroutineWorker {
|
class EnhancedDailyNotificationFetcher : DailyNotificationFetcher {
|
||||||
suspend fun doWork(): Result {
|
private val jwtManager: DailyNotificationJWTManager
|
||||||
val jwt = generateJWT(activeDid, 60)
|
|
||||||
val headers = mapOf(
|
suspend fun fetchEndorserOffers(activeDid: String, afterId: String?): Result {
|
||||||
"Authorization" to "Bearer $jwt",
|
val connection = HttpURLConnection("$apiServer/api/v2/report/offers")
|
||||||
"Content-Type" to "application/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
val offersResponse = httpClient.get("$apiServer/api/v2/report/offers") {
|
// Add JWT authentication to existing connection
|
||||||
headers { headers.forEach { append(it.key, it.value) } }
|
jwtManager.enhanceHttpClientWithJWT(connection, activeDid)
|
||||||
parameter("recipientId", activeDid) // Use activeDid for recipient filtering
|
|
||||||
parameter("afterId", lastKnownOfferId)
|
// 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();
|
const results = await plugin.executeBackgroundContentFetch();
|
||||||
```
|
```
|
||||||
|
|
||||||
#### **New Plugin Methods Required**
|
#### **Enhancement Required: Extend Current Plugin Interface**
|
||||||
|
|
||||||
|
**Current Interface** (already implemented):
|
||||||
```typescript
|
```typescript
|
||||||
interface EnhancedDailyNotificationPlugin {
|
interface DailyNotificationPlugin {
|
||||||
// Database configuration - Simplified Option A approach
|
configure(options: ConfigureOptions): Promise<void>;
|
||||||
configureDatabase(options: {
|
scheduleContentFetch(config: ContentFetchConfig): Promise<void>;
|
||||||
platform: 'android' | 'ios' | 'web' | 'electron';
|
scheduleUserNotification(config: UserNotificationConfig): Promise<void>;
|
||||||
storageType: 'plugin-managed' | 'host-managed';
|
// ... existing methods (see definitions.ts)
|
||||||
dbPath?: string;
|
}
|
||||||
encryption?: boolean;
|
```
|
||||||
|
|
||||||
|
**Enhancement Required** (add to existing interface):
|
||||||
|
```typescript
|
||||||
|
interface EnhancedDailyNotificationPlugin extends DailyNotificationPlugin {
|
||||||
|
// Enhanced configuration with activeDid support
|
||||||
|
configure(options: ConfigureOptions & {
|
||||||
|
activeDidIntegration?: {
|
||||||
|
platform: 'android' | 'ios' | 'web' | 'electron';
|
||||||
|
storageType: 'plugin-managed' | 'host-managed';
|
||||||
|
};
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
|
||||||
// Host-provided activeDid Management (Option A Implementation)
|
// Host-provided activeDid Management (Option A Implementation)
|
||||||
setActiveDidFromHost(activeDid: string): Promise<void>;
|
setActiveDidFromHost(activeDid: string): Promise<void>;
|
||||||
|
|
||||||
// Content fetch with database integration
|
|
||||||
fetchAndStoreContent(config: ContentFetchConfig): Promise<ContentFetchResult>;
|
|
||||||
|
|
||||||
// Data access for host application
|
|
||||||
getStoredContent(query: string, params?: any[]): Promise<any[]>;
|
|
||||||
clearStoredContent(options?: { olderThan?: number }): Promise<void>;
|
|
||||||
|
|
||||||
// Background task coordination
|
|
||||||
getBackgroundTaskStatus(): Promise<BackgroundTaskStatus>;
|
|
||||||
pauseBackgroundTasks(): Promise<void>;
|
|
||||||
resumeBackgroundTasks(): Promise<void>;
|
|
||||||
|
|
||||||
// TimeSafari Integration Methods
|
|
||||||
initializeFromTimeSafari(): Promise<void>;
|
|
||||||
listenForActiveDidChanges(): Promise<void>;
|
|
||||||
|
|
||||||
// Critical: ActiveDid Change Handling
|
// Critical: ActiveDid Change Handling
|
||||||
onActiveDidChange(callback: (newActiveDid: string) => Promise<void>): void;
|
onActiveDidChange(callback: (newActiveDid: string) => Promise<void>): void;
|
||||||
clearCacheForNewIdentity(): Promise<void>;
|
|
||||||
refreshAuthenticationForNewIdentity(activeDid: string): Promise<void>;
|
refreshAuthenticationForNewIdentity(activeDid: string): Promise<void>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -579,38 +594,38 @@ GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={j
|
|||||||
|
|
||||||
## Implementation Phases
|
## 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
|
- **Extend existing** Android `DailyNotificationFetcher.java` with JWT authentication
|
||||||
- Implement basic JWT generation
|
- **Enhance existing** iOS implementation (when added) with authentication layer
|
||||||
- Create plugin configuration interfaces
|
- **Add JWT generation** to existing `DailyNotificationETagManager.java`
|
||||||
- Set up basic error handling
|
- **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** host-provided activeDid management to existing plugin interface
|
||||||
- Add `setActiveDidFromHost()` method (no database access needed)
|
- **Extend** existing `configure()` method with activeDid options
|
||||||
- Remove database sharing complexity - host always provides activeDid
|
- **Enhance** existing `ContentFetchConfig` with Endorser.ch API endpoints
|
||||||
- Integrate API endpoint calls with activeDid-based authentication
|
- **Add** `setActiveDidFromHost()` and `onActiveDidChange()` to existing interface
|
||||||
- Add response parsing and validation
|
- **Integrate** existing `callback-registry.ts` with activeDid-aware callbacks
|
||||||
- Implement platform-specific database integration:
|
- **Enhance** existing platform storage:
|
||||||
- **Android/Electron**: Plugin-managed @capacitor-community/sqlite (no host database access)
|
- **Android**: Extend existing SQLite with activeDid-aware JWT storage
|
||||||
- **Web**: Host-managed storage delegation (plugin doesn't access absurd-sql directly)
|
- **Web**: Enhance existing IndexedDB with activeDid support (no host delegation needed initially)
|
||||||
- **iOS**: Plugin-managed Core Data (no host database access)
|
|
||||||
|
|
||||||
### Phase 3: Background Integration (Weeks 5-6)
|
### Phase 3: Background Enhancement & TimeSafari Coordination
|
||||||
|
|
||||||
- Integrate with WorkManager/BGTaskScheduler
|
- **Enhance** existing WorkManager integration with activeDid-aware workers
|
||||||
- Coordinate with notification scheduling
|
- **Coordinate** existing notification scheduling with TimeSafari PlatformServiceMixin
|
||||||
- Handle app lifecycle events
|
- **Extend** existing app lifecycle handling with activeDid change detection
|
||||||
- Implement state synchronization
|
- **Enhance** existing state synchronization with identity management
|
||||||
|
|
||||||
### Phase 4: Advanced Features (Weeks 7-8)
|
### Phase 4: TimeSafari Integration & Advanced Features
|
||||||
|
|
||||||
- Add passkey authentication support
|
- **Integrate** with TimeSafari's existing PlatformServiceMixin patterns
|
||||||
- Implement advanced caching strategies
|
- **Add** Endorser.ch API endpoint support to existing `ContentFetchConfig`
|
||||||
- Optimize performance and memory usage
|
- **Implement** DID-based authentication alongside existing callback system
|
||||||
- Add comprehensive testing
|
- **Enhance** existing testing with TimeSafari-specific scenarios
|
||||||
|
|
||||||
## Success Criteria
|
## 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
|
**Status**: Enhancement plan for existing implementation (Option A) - Ready for implementation
|
||||||
**Next Steps**: Begin Phase 1 implementation with Android HTTP client setup
|
**Next Steps**: Begin Phase 1 - enhance existing Android HTTP infrastructure with JWT authentication
|
||||||
**Dependencies**: Android Studio, Xcode, Capacitor CLI, existing plugin infrastructure, @capacitor-community/sqlite
|
**Dependencies**: Existing plugin infrastructure, Android Studio, Capacitor CLI, TimeSafari PlatformServiceMixin
|
||||||
**Option A Features**:
|
**Enhancement Approach**:
|
||||||
- **Simplified Architecture**: Host always provides activeDid, no database sharing
|
- **Build on Existing**: Leverage current SQLite, IndexedDB, callback system, and dual scheduling
|
||||||
- **TimeSafari Integration**: PlatformServiceMixin coordination without database access
|
- **Option A Integration**: Add activeDid management to existing configuration and HTTP layers
|
||||||
- **Cross-Platform**: Android/Electron plugin-managed SQLite, Web host-managed storage, iOS plugin-managed Core Data
|
- **TimeSafari Enhancement**: Extend current ContentFetchConfig with Endorser.ch API endpoints
|
||||||
- **Authentication**: DID-based JWT with host-provided activeDid
|
- **Authentication Layer**: Add JWT/DID authentication over existing HTTP infrastructure
|
||||||
- **Background Tasks**: Event-based activeDid changes, clear separation of concerns
|
- **Event Integration**: Enhance existing callback system with activeDid change detection
|
||||||
|
|||||||
Reference in New Issue
Block a user