You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

13 KiB

Background Data Fetching Implementation Plan

Author: Matthew Raymer
Version: 1.0.0
Created: 2025-10-02 07:47:04 UTC
Last Updated: 2025-10-02 10:15:00 UTC

Overview

This document outlines the implementation plan for background data fetching in the Capacitor Daily Notification Plugin, replacing web push implementations with native platform solutions. The plan covers Android, iOS, and cross-platform considerations for API data fetching with authentication.

Platform Architecture Overview

JavaScript Layer → Native Bridge → Native Background Executor
                          ↓
                    HTTP Client + Auth
                          ↓
                   API Server Response
                          ↓
                   Parse & Cache Data
                          ↓
                   Trigger Notifications

Android Implementation Strategy

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
  • Handle Android-specific constraints: Doze mode, app standby, battery optimization

B. Authentication Implementation

// JWT Generation in Android - Enhanced with DID support
class JWTHelper {
    fun generateJWT(userDid: 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
            "aud" to "timesafari.notifications",
            "sub" to userDid
        )
        return signWithDID(payload, userDid)
    }
    
    // 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)
    }
}

### C. HTTP Request Implementation

```kotlin
// Background HTTP Worker
class DataFetchWorker : CoroutineWorker {
    suspend fun doWork(): Result {
        val jwt = generateJWT(userDid, 60)
        val headers = mapOf(
            "Authorization" to "Bearer $jwt",
            "Content-Type" to "application/json"
        )
        
        val offersResponse = httpClient.get("$apiServer/api/v2/report/offers") {
            headers { headers.forEach { append(it.key, it.value) } }
            parameter("recipientDid", userDid)
            parameter("afterId", lastKnownOfferId)
        }
        
        return storeAndScheduleNotification(offersResponse.body())
    }
}

iOS Implementation Strategy

A. Background Execution Framework

  • Use BGTaskScheduler for background HTTP requests
  • Replace axios with native iOS HTTP clients:
    • URLSession for HTTP requests
    • Combine framework for async/await patterns

B. Authentication Implementation

// JWT Generation in iOS
class JWTHelper {
    func generateJWT(userDid: String, expiresInSeconds: Int) -> String {
        let payload: [String: Any] = [
            "exp": Int(Date().timeIntervalSince1970) + expiresInSeconds,
            "iat": Int(Date().timeIntervalSince1970),
            "iss": userDid
        ]
        return signWithDID(payload, userDid)
    }
}

C. HTTP Request Implementation

// Background HTTP Task
class DataFetchTask {
    func fetchData() async {
        let jwt = generateJWT(userDid: userDid, expiresInSeconds: 60)
        var request = URLRequest(url: apiURL)
        request.setValue("Bearer \(jwt)", forHTTPHeaderField: "Authorization")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        do {
            let (data, _) = try await URLSession.shared.data(for: request)
            let offersResponse = try JSONDecoder().decode(OffersResponse.self, from: data)
            await scheduleNotification(with: offersResponse.data)
        } catch {
            // Handle errors
        }
    }
}

Data Models & Type Safety

Shared TypeScript Interfaces

// Definitions for native bridge
interface OffersResponse {
    data: OfferSummaryRecord[];
    hitLimit: boolean;
}

interface OfferSummaryRecord {
    jwtId: string;
    handleId: string;
    issuedAt: string;
    offeredByDid: string;
    recipientDid: string;
    unit: string;
    amount: number;
    // ... other fields
}

Native Implementations

  • Kotlin sealed classes for type-safe responses
  • Swift Codable structs for JSON parsing
  • Shared error handling patterns

Configuration Management

Plugin Configuration

interface PluginConfig {
    apiServer: string;
    jwtExpirationSeconds: number;
    requestTimeoutMs: number;
    retryAttempts: number;
    userDid: string;
    lastKnownOfferId?: string;
    lastKnownPlanId?: string;
}

Platform-Specific Settings

  • Android: Manage API keys in AndroidManifest.xml, use SharedPreferences for runtime config
  • iOS: Use Info.plist for static config, UserDefaults for runtime settings

Error Handling & Resilience

Network Error Handling

  • Connectivity checks before making requests
  • Exponential backoff for retry scenarios
  • Circuit breaker pattern for API failures
  • Graceful degradation when offline

Authentication Error Handling

  • Token refresh mechanisms
  • Fallback to anonymous requests when authentication fails
  • Secure credential storage using platform keychains

Cache & State Management

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

State Synchronization

  • JavaScript → Native configuration updates
  • Native → JavaScript status reporting
  • Cross-platform state consistency
  • Background ↔ Foreground state synchronization
  • Database logging for audit trails and debugging

Enhanced Caching Strategy

Based on TimeSafari's optimization patterns:

  • Batch-oriented processing for API requests to reduce overhead
  • Intelligent batching with configurable timing (max 100ms wait, max 10 items)
  • Memory-optimized caching with automatic cleanup (keep last 1000 log entries)
  • Request deduplication to prevent redundant API calls
  • Performance monitoring with operation timing and metrics collection

Performance Optimizations

Request Optimization

  • Deduplication of identical requests
  • Batch requests when possible
  • Intelligent polling based on user activity

Memory Management

  • Background memory limits enforcement
  • Cache cleanup on memory pressure
  • Resource lifecycle management

Integration Points

Existing Plugin APIs

  • Extend DailyNotification.configure() to include API server settings
  • Add new methods: setUserCredentials(), fetchActivityData(), getCachedData()
  • Trigger notifications based on fetched data differences

Background Scheduling

  • Integrate with existing WorkManager/BGTaskScheduler
  • Coordinate API fetch timing with notification schedules
  • Handle app lifecycle events (background/foreground)

Migration & Testing Strategy

Gradual Migration

  1. Phase 1: Implement basic HTTP + JWT authentication
  2. Phase 2: Add caching and state management
  3. Phase 3: Integrate with notification scheduling
  4. Phase 4: Add passkey authentication support

Testing Approach

  • Unit tests for JWT generation and HTTP clients
  • Integration tests for API endpoint interactions
  • Background testing on real devices (doze mode, app backgrounding)
  • Authentication testing with actual DID credentials

API Endpoints to Support

Offers to User Endpoint

GET {apiServer}/api/v2/report/offers?recipientDid={userDid}&afterId={jwtId}&beforeId={jwtId}

Response Structure:

{
  "data": Array<OfferSummaryRecord>,
  "hitLimit": boolean
}

Offers to User Projects Endpoint

GET {apiServer}/api/v2/report/offersToPlansOwnedByMe?afterId={jwtId}&beforeId={jwtId}

Response Structure:

{
  "data": Array<OfferToPlanSummaryRecord>,
  "hitLimit": boolean
}

Authentication Implementation Strategy

Option 1: Simple DID Authentication (Basic)

  • Generate traditional JWT using DID signing
  • Short-lived tokens (60 seconds)
  • Suitable for basic notification data fetching
  • Use did-jwt library for token generation and verification
  • Based on TimeSafari's existing JWT implementation patterns

Option 2: Enhanced Passkey Authentication (Advanced)

  • Leverage device biometrics/security keys
  • Longer-lived tokens with automatic refresh
  • Support for cached authentication state
  • Better user experience for frequent polling
  • Integrate with SimpleWebAuthn for cross-platform biometric support
  • Support JWANT tokens (JWT + WebAuthn) for enhanced security

Platform-Specific Considerations

Android Considerations

  • Use OkHttp or native Android HTTP clients
  • Handle certificate pinning if required
  • Support Android Keystore for secure key storage
  • Handle biometric prompt integration for passkeys

iOS Considerations

  • Use URLSession for HTTP requests
  • Support iOS Keychain for authentication tokens
  • Handle Face ID/Touch ID integration for passkeys
  • Support certificate pinning if required
  • Use BGTaskScheduler for reliable background execution
  • Handle iOS-specific background refresh restrictions
  • Support Core Data for notification metadata persistence

Data Flow Integration Points

Token Generation

  • Accept user DID as input
  • Generate appropriate authentication token based on user's credential type
  • Return token for immediate use or caching

Request Execution

  • Construct full API URLs with query parameters
  • Apply authentication headers
  • Execute HTTP requests with proper error handling
  • Return structured response data

Caching Strategy

  • Support token caching with expiration management
  • Implement request deduplication for same endpoints
  • Support cache invalidation for authentication failures

Implementation Phases

Phase 1: Core Infrastructure (Weeks 1-2)

  • Set up native HTTP clients for Android/iOS
  • Implement basic JWT generation
  • Create plugin configuration interfaces
  • Set up basic error handling

Phase 2: Authentication & API Integration (Weeks 3-4)

  • Implement DID-based authentication
  • Integrate API endpoint calls
  • Add response parsing and validation
  • Implement basic caching

Phase 3: Background Integration (Weeks 5-6)

  • Integrate with WorkManager/BGTaskScheduler
  • Coordinate with notification scheduling
  • Handle app lifecycle events
  • Implement state synchronization

Phase 4: Advanced Features (Weeks 7-8)

  • Add passkey authentication support
  • Implement advanced caching strategies
  • Optimize performance and memory usage
  • Add comprehensive testing

Success Criteria

  • Functional Requirements: API data fetching works reliably in background
  • Performance Requirements: Requests complete within 30 seconds
  • Security Requirements: Secure credential storage and token management
  • Reliability Requirements: Handles network failures and offline scenarios
  • Integration Requirements: Seamless integration with existing plugin APIs
  • Testing Requirements: Comprehensive test coverage for all platforms
  • Authentication Requirements: Support both DID-based JWT and Passkey JWANT tokens
  • Optimization Requirements: Implement batch processing with sub-100ms delays
  • Logging Requirements: Structured logging with database persistence for debugging
  • Cross-Platform Requirements: Unified SQLite/IndexedDB storage across platforms

Risks & Mitigation

Technical Risks

  • Background execution limits: Mitigated by using platform-specific background task systems
  • Authentication complexity: Mitigated by implementing gradual migration path
  • Cross-platform consistency: Mitigated by shared interfaces and careful API design

Timeline Risks

  • Platform-specific complexity: Mitigated by prioritizing Android first, then iOS
  • Testing complexity: Mitigated by automated testing and CI/CD integration
  • Integration challenges: Mitigated by maintaining backward compatibility

Status: Enhanced planning document - 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, @simplewebauthn packages
Enhanced Features: DID authentication, batch processing, structured logging, cross-platform storage optimization