# ActiveDid Change Requirements **Author**: Matthew Raymer **Version**: 1.0.0 **Created**: 2025-10-02 12:00:00 UTC **Last Updated**: 2025-10-02 12:00:00 UTC ## Critical Requirement: Plugin Must Know When activeDid Changes **CONFIRMED**: The plugin **must** be notified when activeDid changes to maintain data integrity and security. ## Why This Is Critical ### **Security Implications** - **Authentication Isolation**: Each activeDid has different authentication tokens - **Data Privacy**: Cached content belongs to specific user identity - **Authorization**: API calls must use correct activeDid for proper authorization ### **Data Integrity Issues** - **Cache Pollution**: Wrong user's data could leak between identities - **Stale Authentication**: Old JWT tokens become invalid for new identity - **Background Tasks**: Tasks running with wrong identity context ### **User Experience Problems** ```typescript // PROBLEMATIC SCENARIO WITHOUT CHANGE NOTIFICATION: // 1. User A schedules notification for "my offers" // 2. User switches to User B // 3. Plugin doesn't know about change // 4. Plugin delivers User A's personal offer data to User B ❌ ``` ## Solution: Event-Based Change Notification ### **TimeSafari Host Application** ```typescript // In PlatformServiceMixin.ts - CRITICAL PATTERN async $updateActiveDid(newDid: string | null): Promise { // ... existing activeDid update logic ... // MUST notify Daily Notification Plugin await this.$notifyDailyNotificationService(newDid); } async $notifyDailyNotificationService(newActiveDid: string): Promise { const event = new CustomEvent('activeDidChanged', { detail: { activeDid: newActiveDid } }); document.dispatchEvent(event); } ``` ### **Plugin Side Implementation** ```typescript // In Daily Notification Plugin - MANDATORY LISTENING export class EnhancedDailyNotificationPlugin { private currentActiveDid: string | null = null; constructor() { this.setupActiveDidChangeListener(); } private setupActiveDidChangeListener(): void { document.addEventListener('activeDidChanged', (event: CustomEvent) => { this.handleActiveDidChange(event.detail.activeDid); }); } private async handleActiveDidChange(newActiveDid: string): Promise { if (newActiveDid !== this.currentActiveDid) { logger.info(`[Plugin] ActiveDid changing from ${this.currentActiveDid} to ${newActiveDid}`); // CRITICAL ACTIONS REQUIRED: await this.clearCacheForNewIdentity(); await this.refreshAuthenticationForNewIdentity(newActiveDid); await this.updateBackgroundTaskIdentity(newActiveDid); this.currentActiveDid = newActiveDid; } } async clearCacheForNewIdentity(): Promise { // Clear all cached content to prevent data leakage await this.clearStoredContent(); await this.clearAuthenticationTokens(); } async refreshAuthenticationForNewIdentity(activeDid: string): Promise { // Generate new JWT tokens with correct activeDid const newJwt = await this.generateJWT(activeDid); this.currentAuthToken = newJwt; } async updateBackgroundTaskIdentity(activeDid: string): Promise { // Update background tasks to use new identity await this.pauseBackgroundTasks(); await this.configureBackgroundTasksForIdentity(activeDid); await this.resumeBackgroundTasks(); } } ``` ## Implementation Requirements ### **Host Application Responsibilities** 1. **Event Dispatch**: Must dispatch `activeDidChanged` events 2. **Timing**: Dispatch immediately after updating active_identity table 3. **Reliability**: Event must reach all plugin listeners ### **Plugin Responsibilities** 1. **Event Listening**: Must listen for `activeDidChanged` events 2. **Cache Clearing**: Must clear all cached content for new identity 3. **Authentication Refresh**: Must generate new tokens with updated activeDid 4. **Background Task Update**: Must restart background tasks with new context 5. **Error Handling**: Must handle failures gracefully during identity transition ## Testing Requirements ### **Integration Tests** ```typescript describe('ActiveDid Change Handling', () => { it('should clear cache when activeDid changes', async () => { // Set up initial identity await plugin.setActiveDidFromHost('did:alice:123'); await plugin.cacheContentData({ /* Alice's data */ }); // Simulate identity change const event = new CustomEvent('activeDidChanged', { detail: { activeDid: 'did:bob:456' } }); document.dispatchEvent(event); // Verify cache is cleared expect(await plugin.getCachedContent()).toBeNull(); }); it('should refresh authentication tokens', async () => { // Set initial identity const aliceToken = await plugin.generateJWT('did:alice:123'); // Change identity document.dispatchEvent(new CustomEvent('activeDidChanged', { detail: { activeDid: 'did:bob:456' } })); // Verify new token with correct identity const bobToken = await plugin.getCurrentAuthToken(); expect(bobToken.payload.sub).toBe('did:bob:456'); }); it('should handle multiple rapid identity changes', async () => { // Test rapid switching between identities const identities = ['did:alice:123', 'did:bob:456', 'did:alice:123']; for (const identity of identities) { document.dispatchEvent(new CustomEvent('activeDidChanged', { detail: { activeDid: identity } })); await new Promise(resolve => setTimeout(resolve, 100)); // Brief pause } // Ensure plugin ends up in correct state expect(plugin.currentActiveDid).toBe('did:alice:123'); }); }); ``` ### **Edge Case Testing** - **Network Failure**: Identity changes during network failures - **Background Mode**: Identity changes when app is backgrounded - **Rapid Switches**: Multiple identity changes in quick succession - **Invalid activeDid**: Change to empty or invalid activeDid ## Platform-Specific Considerations ### **Android/Electron** - Plugin can detect activeDid changes in background via database polling - Backup mechanism if event-based notification fails ### **Web** - Event-based notification is primary mechanism - Fallback to periodic activeDid checking ### **iOS** - Background tasks can check activeDid changes - Event-based notification for foreground changes ## Performance Considerations ### **Change Detection Optimization** - Debounce rapid identity changes - Batch cache clearing operations - Minimize background task restarts ### **Resource Cleanup** - Clear authentication tokens immediately - Clean up cached content efficiently - Avoid memory leaks during transitions --- **Status**: Critical requirement documented - Implementation required **Next Steps**: Add activeDid change listeners to plugin implementation **Security Impact**: HIGH - Prevents data leakage between user identities