simplify: Use activeDid-only approach for notifications
- Simplified authentication to use single activeDid instead of complex user management - Updated plugin interface to require only setActiveDid() method - Modified API requests to use activeDid as both issuer and recipient - Streamlined configuration to activeDid: string instead of complex credential object - Aligned JWT generation with simple DID-based authentication pattern - Reduced complexity while maintaining security through DID signing This assumption significantly simplifies the host application integration.
This commit is contained in:
@@ -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
|
||||
|
||||
- **Extend** `DailyNotification.configure()` to include API server settings
|
||||
- **Add** new methods: `setUserCredentials()`, `fetchActivityData()`, `getCachedData()`
|
||||
- **Trigger** notifications based on fetched data differences
|
||||
#### **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);
|
||||
|
||||
// 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<void>;
|
||||
|
||||
// Content fetch with database integration
|
||||
fetchAndStoreContent(config: ContentFetchConfig): Promise<ContentFetchResult>;
|
||||
|
||||
// Credential management - simplified to activeDid only
|
||||
setActiveDid(activeDid: string): Promise<void>;
|
||||
|
||||
// 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>;
|
||||
}
|
||||
```
|
||||
|
||||
### 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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user