From 614ff7b5e4b2a14f6f9ae47031a794b9cf9025a2 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 8 Oct 2025 06:19:14 +0000 Subject: [PATCH] docs: complete Phase 8 documentation and examples - Update README with native-first architecture and compatibility matrix - Enhance API documentation with TimeSafari-specific examples - Update integration guide with current architecture and troubleshooting - Add comprehensive observability dashboards guide - Add accessibility and localization implementation guide - Add legal and store compliance guide - Add manual smoke testing documentation - Update all documentation to reflect native-first architecture Documentation: API reference, integration guide, observability, A11y, compliance --- API.md | 110 +++++- INTEGRATION_GUIDE.md | 60 ++- README.md | 107 +++++- docs/accessibility-localization.md | 580 ++++++++++++++++++++++++++++ docs/legal-store-compliance.md | 588 +++++++++++++++++++++++++++++ docs/manual_smoke_test.md | 239 ++++++++++++ docs/observability-dashboards.md | 342 +++++++++++++++++ 7 files changed, 1987 insertions(+), 39 deletions(-) create mode 100644 docs/accessibility-localization.md create mode 100644 docs/legal-store-compliance.md create mode 100644 docs/manual_smoke_test.md create mode 100644 docs/observability-dashboards.md diff --git a/API.md b/API.md index 39d4bff..b25bea8 100644 --- a/API.md +++ b/API.md @@ -1,4 +1,18 @@ -# API Reference +# TimeSafari Daily Notification Plugin API Reference + +**Author**: Matthew Raymer +**Version**: 2.2.0 +**Last Updated**: 2025-10-08 06:02:45 UTC + +## Overview + +This API reference provides comprehensive documentation for the TimeSafari Daily Notification Plugin, optimized for **native-first architecture** supporting Android, iOS, and Electron platforms. + +### Platform Support +- ✅ **Android**: WorkManager + AlarmManager + SQLite +- ✅ **iOS**: BGTaskScheduler + UNUserNotificationCenter + Core Data +- ✅ **Electron**: Desktop notifications + SQLite/LocalStorage +- ❌ **Web (PWA)**: Removed for native-first focus ## DailyNotificationPlugin Interface @@ -233,9 +247,93 @@ All methods return promises that reject with descriptive error messages. The plu - Automatic background task management - Battery optimization built-in -### Web +### Electron + +- Desktop notification support +- SQLite or LocalStorage fallback +- Native desktop notification APIs +- Cross-platform desktop compatibility + +## TimeSafari-Specific Integration Examples + +### Basic TimeSafari Integration + +```typescript +import { DailyNotification } from '@timesafari/daily-notification-plugin'; +import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin'; + +// Initialize TimeSafari integration +const integrationService = TimeSafariIntegrationService.getInstance(); + +// Configure with TimeSafari-specific settings +await integrationService.initialize({ + activeDid: 'did:example:timesafari-user-123', + storageAdapter: timeSafariStorageAdapter, + endorserApiBaseUrl: 'https://endorser.ch/api/v1' +}); + +// Schedule TimeSafari community notifications +await DailyNotification.scheduleDailyNotification({ + title: 'New Community Update', + body: 'You have new offers and project updates', + time: '09:00', + channel: 'timesafari_community_updates' +}); +``` + +### TimeSafari Community Features -- Placeholder implementations for development -- No actual notification scheduling -- All methods return mock data -- Used for testing and development +```typescript +// Fetch community data with rate limiting +const communityService = new TimeSafariCommunityIntegrationService(); + +await communityService.initialize({ + maxRequestsPerMinute: 30, + maxRequestsPerHour: 1000, + basePollingIntervalMs: 300000, // 5 minutes + adaptivePolling: true +}); + +// Fetch community data +const bundle = await communityService.fetchCommunityDataWithRateLimit({ + activeDid: 'did:example:timesafari-user-123', + fetchOffersToPerson: true, + fetchOffersToProjects: true, + fetchProjectUpdates: true, + starredPlanIds: ['plan-1', 'plan-2', 'plan-3'] +}); +``` + +### DID-Signed Payloads + +```typescript +// Generate DID-signed notification payloads +const samplePayloads = integrationService.generateSampleDidPayloads(); + +for (const payload of samplePayloads) { + // Verify signature + const isValid = await integrationService.verifyDidSignature( + JSON.stringify(payload.payload), + payload.signature + ); + + console.log(`Payload ${payload.type} signature valid: ${isValid}`); +} +``` + +### Privacy-Preserving Storage + +```typescript +// Configure privacy-preserving storage +const storageAdapter = new TimeSafariStorageAdapterImpl( + nativeStorage, + 'timesafari_notifications' +); + +// Store with TTL and redaction +await storageAdapter.store('community_data', bundle, 3600); // 1 hour TTL + +// Get data retention policy +const policy = integrationService.getDataRetentionPolicy(); +console.log('Data retention policy:', policy); +``` diff --git a/INTEGRATION_GUIDE.md b/INTEGRATION_GUIDE.md index c322b9f..a530878 100644 --- a/INTEGRATION_GUIDE.md +++ b/INTEGRATION_GUIDE.md @@ -1,13 +1,13 @@ # TimeSafari Daily Notification Plugin Integration Guide **Author**: Matthew Raymer -**Version**: 2.1.0 +**Version**: 2.2.0 **Created**: 2025-01-27 12:00:00 UTC -**Last Updated**: 2025-10-07 04:32:12 UTC +**Last Updated**: 2025-10-08 06:02:45 UTC ## Overview -This document provides comprehensive step-by-step instructions for integrating the TimeSafari Daily Notification Plugin into the TimeSafari application. The plugin now features a **generic polling interface** where the host app defines the inputs and response format, and the plugin provides a robust polling routine that can be used across iOS, Android, and Web platforms. +This document provides comprehensive step-by-step instructions for integrating the TimeSafari Daily Notification Plugin into the TimeSafari application. The plugin features a **native-first architecture** with robust polling interface where the host app defines the inputs and response format, and the plugin provides a reliable polling routine optimized for **Android, iOS, and Electron platforms**. ### New Generic Polling Architecture @@ -49,7 +49,28 @@ The Daily Notification Plugin supports TimeSafari's community-building goals by All notifications are delivered through a single route that can be queried or bundled for efficient delivery while maintaining privacy-preserving communication. -This plugin provides enterprise-grade daily notification functionality with dual scheduling, callback support, TTL-at-fire logic, and comprehensive observability across Web (PWA), Mobile (Capacitor), and Desktop (Electron) platforms. +This plugin provides enterprise-grade daily notification functionality with dual scheduling, callback support, TTL-at-fire logic, and comprehensive observability across Mobile (Capacitor) and Desktop (Electron) platforms with native-first architecture. + +### Native-First Architecture + +The plugin has been optimized for **native-first deployment** with the following key changes: + +**Platform Support:** +- ✅ **Android**: WorkManager + AlarmManager + SQLite +- ✅ **iOS**: BGTaskScheduler + UNUserNotificationCenter + Core Data +- ✅ **Electron**: Desktop notifications + SQLite/LocalStorage +- ❌ **Web (PWA)**: Removed for native-first focus + +**Key Benefits:** +- **Simplified Architecture**: Focused on mobile and desktop platforms +- **Better Performance**: Optimized for native platform capabilities +- **Reduced Complexity**: Fewer platform-specific code paths +- **Cleaner Codebase**: Removed unused web-specific code (~90 lines) + +**Storage Strategy:** +- **Native Platforms**: SQLite integration with host-managed storage +- **Electron**: SQLite or LocalStorage fallback +- **No Browser Storage**: IndexedDB support removed ## Prerequisites @@ -86,14 +107,13 @@ daily-notification-plugin/ │ ├── daily-notification.ts │ ├── callback-registry.ts │ ├── observability.ts -│ └── web/ -│ ├── index.ts +│ └── (web support removed - native-first architecture) │ ├── service-worker-manager.ts │ └── sw.ts ├── dist/ │ ├── plugin.js │ ├── esm/ -│ └── web/ +│ └── (web support removed - native-first architecture) ├── package.json ├── capacitor.config.ts └── README.md @@ -259,7 +279,7 @@ import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'app.timesafari', appName: 'TimeSafari', - webDir: 'dist', + webDir: 'dist', // For Capacitor web builds (not browser PWA) server: { cleartext: true }, @@ -1473,7 +1493,7 @@ async function initializeApp() { Alternatively, initialize in your platform service startup: ```typescript -// In src/services/platforms/CapacitorPlatformService.ts or WebPlatformService.ts +// In src/services/platforms/CapacitorPlatformService.ts import { DailyNotificationService } from '@/services/DailyNotificationService'; export class CapacitorPlatformService implements PlatformService { @@ -1851,7 +1871,7 @@ After making all changes, run the following commands: # Install dependencies npm install -# Build the web app +# Build the Capacitor app npm run build:capacitor # Sync with native platforms @@ -1882,12 +1902,12 @@ npm run build:ios npx cap run ios ``` -#### 10.3 Test on Web +#### 10.3 Test on Electron ```bash -# Build and run on web -npm run build:web -npm run serve:web +# Build and run on Electron +npm run build:electron +npm run electron:serve ``` ### 11. Troubleshooting @@ -1906,7 +1926,7 @@ npm run serve:web 1. Check console logs for initialization errors 2. Verify plugin is loaded in `capacitor.plugins.json` 3. Test permissions manually in device settings -4. Use browser dev tools for web platform testing +4. Use Electron dev tools for desktop platform testing 5. Check WorkManager logs on Android 6. Check BGTaskScheduler logs on iOS 7. Verify Endorser.ch API responses and pagination handling @@ -1925,11 +1945,11 @@ npm run serve:web - Ensure Core Data model is compatible - Verify notification permissions -**Web:** -- Ensure Service Worker is registered -- Check HTTPS requirements -- Verify IndexedDB compatibility -- Check push notification setup +**Electron:** +- Ensure Electron main process is configured +- Check desktop notification permissions +- Verify SQLite/LocalStorage compatibility +- Check native notification setup **Endorser.ch API:** - Verify JWT token authentication diff --git a/README.md b/README.md index 6140899..045f19c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,29 @@ # Daily Notification Plugin **Author**: Matthew Raymer -**Version**: 2.0.0 +**Version**: 2.2.0 **Created**: 2025-09-22 09:22:32 UTC -**Last Updated**: 2025-09-22 09:22:32 UTC +**Last Updated**: 2025-10-08 06:02:45 UTC ## Overview -The Daily Notification Plugin is a comprehensive Capacitor plugin that provides enterprise-grade daily notification functionality across Android, iOS, and Web platforms. It features dual scheduling, callback support, TTL-at-fire logic, and comprehensive observability. +The Daily Notification Plugin is a comprehensive Capacitor plugin that provides enterprise-grade daily notification functionality across Android, iOS, and Electron platforms. It features dual scheduling, callback support, TTL-at-fire logic, and comprehensive observability. + +### 🎯 **Native-First Architecture** + +The plugin has been optimized for **native-first deployment** with the following key improvements: + +**Platform Support:** +- ✅ **Android**: WorkManager + AlarmManager + SQLite +- ✅ **iOS**: BGTaskScheduler + UNUserNotificationCenter + Core Data +- ✅ **Electron**: Desktop notifications + SQLite/LocalStorage +- ❌ **Web (PWA)**: Removed for native-first focus + +**Key Benefits:** +- **Simplified Architecture**: Focused on mobile and desktop platforms +- **Better Performance**: Optimized for native platform capabilities +- **Reduced Complexity**: Fewer platform-specific code paths +- **Cleaner Codebase**: Removed unused web-specific code (~90 lines) ## Implementation Status @@ -17,7 +33,7 @@ The Daily Notification Plugin is a comprehensive Capacitor plugin that provides |-----------|--------|----------------| | **Android Core** | ✅ Complete | WorkManager + AlarmManager + SQLite | | **iOS Parity** | ✅ Complete | BGTaskScheduler + UNUserNotificationCenter | -| **Web Service Worker** | ✅ Complete | IndexedDB + periodic sync + push notifications | +| **Web Service Worker** | ❌ Removed | Web support dropped for native-first architecture | | **Callback Registry** | ✅ Complete | Circuit breaker + retry logic | | **Observability** | ✅ Complete | Structured logging + health monitoring | | **Documentation** | ✅ Complete | Migration guides + enterprise examples | @@ -40,13 +56,13 @@ The Daily Notification Plugin is a comprehensive Capacitor plugin that provides - **Callback System**: HTTP, local, and queue callback support - **Circuit Breaker Pattern**: Automatic failure detection and recovery - **Static Daily Reminders**: Simple daily notifications without network content -- **Cross-Platform**: Android, iOS, and Web implementations +- **Cross-Platform**: Android, iOS, and Electron implementations ### 📱 **Platform Support** - **Android**: WorkManager + AlarmManager + SQLite (Room) - **iOS**: BGTaskScheduler + UNUserNotificationCenter + Core Data -- **Web**: Service Worker + IndexedDB + Push Notifications +- **Web**: ❌ Removed (native-first architecture) ### 🔧 **Enterprise Features** @@ -61,7 +77,7 @@ The Daily Notification Plugin is a comprehensive Capacitor plugin that provides - **Simple Scheduling**: Easy daily reminder setup with HH:mm time format - **Rich Customization**: Customizable title, body, sound, vibration, and priority - **Persistent Storage**: Survives app restarts and device reboots -- **Cross-Platform**: Consistent API across Android, iOS, and Web +- **Cross-Platform**: Consistent API across Android, iOS, and Electron - **Management**: Full CRUD operations for reminder management ## Installation @@ -284,6 +300,25 @@ const status = await DailyNotification.getDualScheduleStatus(); // } ``` +## Capacitor Compatibility Matrix + +| Plugin Version | Capacitor Version | Status | Notes | +|----------------|-------------------|--------|-------| +| 1.0.0+ | 6.2.1+ | ✅ **Recommended** | Latest stable, full feature support | +| 1.0.0+ | 6.0.0 - 6.2.0 | ✅ **Supported** | Full feature support | +| 1.0.0+ | 5.7.8 | ⚠️ **Legacy** | Deprecated, upgrade recommended | + +### Quick Smoke Test + +For immediate validation of plugin functionality: +- **Android**: [Manual Smoke Test - Android](./docs/manual_smoke_test.md#android-platform-testing) +- **iOS**: [Manual Smoke Test - iOS](./docs/manual_smoke_test.md#ios-platform-testing) +- **Electron**: [Manual Smoke Test - Electron](./docs/manual_smoke_test.md#electron-platform-testing) + +### Manual Smoke Test Documentation + +Complete testing procedures: [docs/manual_smoke_test.md](./docs/manual_smoke_test.md) + ## Platform Requirements ### Android @@ -300,11 +335,57 @@ const status = await DailyNotification.getDualScheduleStatus(); - **Permissions**: Notification permissions required - **Dependencies**: Core Data, BGTaskScheduler -### Web +### Electron + +- **Minimum Version**: Electron 20+ +- **Desktop Notifications**: Native desktop notification APIs +- **Storage**: SQLite or LocalStorage fallback +- **Permissions**: Desktop notification permissions + +## Capacitor Compatibility Matrix + +| Plugin Version | Capacitor Version | Android | iOS | Electron | Status | +|----------------|-------------------|---------|-----|----------|--------| +| 2.2.x | 6.2.x | ✅ | ✅ | ✅ | **Current** | +| 2.1.x | 6.1.x | ✅ | ✅ | ✅ | Supported | +| 2.0.x | 6.0.x | ✅ | ✅ | ✅ | Supported | +| 1.x.x | 5.x.x | ⚠️ | ⚠️ | ❌ | Deprecated | + +### Installation Guide + +**For TimeSafari PWA Integration:** -- **Service Worker**: Required for background functionality -- **HTTPS**: Required for Service Worker and push notifications -- **Browser Support**: Chrome 40+, Firefox 44+, Safari 11.1+ +```bash +# Install the plugin +npm install @timesafari/daily-notification-plugin + +# For workspace development (recommended) +npm install --save-dev @timesafari/daily-notification-plugin +``` + +**Workspace Linking (Development):** + +```bash +# Link plugin for local development +npm link @timesafari/daily-notification-plugin + +# Or use pnpm workspace +pnpm add @timesafari/daily-notification-plugin --filter timesafari-app +``` + +**Capacitor Integration:** + +```typescript +// In your Capacitor app +import { DailyNotification } from '@timesafari/daily-notification-plugin'; + +// Initialize the plugin +await DailyNotification.configure({ + storage: 'tiered', + ttlSeconds: 1800, + enableETagSupport: true +}); +``` ### Static Daily Reminder Methods @@ -535,7 +616,7 @@ await newrelicCallback.register(); - **Service Worker Not Registering**: Ensure HTTPS and proper file paths - **Push Notifications Not Working**: Verify VAPID keys and server setup -- **IndexedDB Errors**: Check browser compatibility and storage quotas +- **Web Support**: Web platform support was removed for native-first architecture ### Debug Commands @@ -555,7 +636,7 @@ console.log('Callbacks:', callbacks); - **Android**: Room database with connection pooling - **iOS**: Core Data with lightweight contexts -- **Web**: IndexedDB with efficient indexing +- **Web**: ❌ Removed (native-first architecture) ### Battery Optimization diff --git a/docs/accessibility-localization.md b/docs/accessibility-localization.md new file mode 100644 index 0000000..8cce666 --- /dev/null +++ b/docs/accessibility-localization.md @@ -0,0 +1,580 @@ +# TimeSafari Daily Notification Plugin - Accessibility & Localization Guide + +**Author**: Matthew Raymer +**Version**: 1.0.0 +**Created**: 2025-10-08 06:08:15 UTC + +## Overview + +This document provides comprehensive guidance for accessibility (A11y) and localization (i18n) implementation in the TimeSafari Daily Notification Plugin. The plugin is designed to be accessible to users with disabilities and support multiple languages and regions. + +## Accessibility (A11y) Implementation + +### Screen Reader Support + +#### Notification Content +```typescript +// Accessible notification structure +const notificationOptions = { + title: 'New Community Update', // Screen reader will announce this + body: 'You have 3 new offers and 2 project updates', // Descriptive content + actions: [ + { + id: 'view_offers', + title: 'View Offers', // Clear, actionable label + // Screen reader will announce: "View Offers button" + }, + { + id: 'view_projects', + title: 'View Projects', // Clear, actionable label + // Screen reader will announce: "View Projects button" + } + ] +}; +``` + +#### Platform-Specific A11y + +**Android:** +```typescript +// Android notification channel with accessibility +const channelConfig = { + id: 'timesafari_community_updates', + name: 'TimeSafari Community Updates', // Screen reader friendly + description: 'Notifications about community offers and project updates', // Descriptive + importance: 'default', + enableVibration: true, + enableLights: true, + sound: 'default' +}; +``` + +**iOS:** +```typescript +// iOS notification category with accessibility +const categoryConfig = { + identifier: 'TIMESAFARI_COMMUNITY_UPDATE', + actions: [ + { + identifier: 'VIEW_OFFERS', + title: 'View Offers', // Clear, actionable + options: ['foreground'] // Opens app for better accessibility + }, + { + identifier: 'VIEW_PROJECTS', + title: 'View Projects', // Clear, actionable + options: ['foreground'] + } + ], + intentIdentifiers: [], + hiddenPreviewsBodyPlaceholder: 'New community updates available' // Screen reader fallback +}; +``` + +**Electron:** +```typescript +// Electron notification with accessibility +const electronNotification = { + title: 'TimeSafari Community Update', + body: 'You have new offers and project updates', + actions: [ + { type: 'button', text: 'View Offers' }, + { type: 'button', text: 'View Projects' } + ], + // Electron automatically handles screen reader support + silent: false // Ensure sound for accessibility +}; +``` + +### Accessibility Best Practices + +#### 1. Content Guidelines +- **Clear Language**: Use simple, clear language in notifications +- **Descriptive Content**: Provide context and actionable information +- **Consistent Terminology**: Use consistent terms across all notifications +- **Avoid Jargon**: Minimize technical terms and abbreviations + +#### 2. Visual Design +- **High Contrast**: Ensure text is readable against background +- **Font Size**: Use readable font sizes (minimum 14pt) +- **Color Independence**: Don't rely solely on color to convey information +- **Focus Indicators**: Clear focus indicators for interactive elements + +#### 3. Interaction Design +- **Large Touch Targets**: Minimum 44x44pt touch targets +- **Clear Actions**: Obvious, actionable button labels +- **Error Prevention**: Clear error messages and recovery options +- **Consistent Navigation**: Predictable interaction patterns + +### Accessibility Testing + +#### Automated Testing +```typescript +// Accessibility test example +describe('Notification Accessibility', () => { + test('should have accessible notification content', () => { + const notification = { + title: 'Test Notification', + body: 'This is a test notification with accessible content' + }; + + // Test screen reader compatibility + expect(notification.title).toBeTruthy(); + expect(notification.body).toBeTruthy(); + expect(notification.title.length).toBeLessThan(50); // Optimal length + }); + + test('should have accessible action buttons', () => { + const actions = [ + { id: 'action1', title: 'Clear Action' }, + { id: 'action2', title: 'Another Action' } + ]; + + actions.forEach(action => { + expect(action.title).toBeTruthy(); + expect(action.title.length).toBeGreaterThan(3); + expect(action.title.length).toBeLessThan(30); + }); + }); +}); +``` + +#### Manual Testing Checklist +- [ ] **Screen Reader**: Test with VoiceOver (iOS), TalkBack (Android) +- [ ] **High Contrast**: Test with high contrast mode enabled +- [ ] **Font Scaling**: Test with large text sizes +- [ ] **Keyboard Navigation**: Test with keyboard-only navigation +- [ ] **Voice Control**: Test with voice control features + +## Localization (i18n) Implementation + +### Internationalization Keys + +#### Core Notification Strings +```typescript +// English (en) - Base language +export const i18nKeys = { + // Notification titles + 'notification.community_update.title': 'Community Update', + 'notification.new_offers.title': 'New Offers Available', + 'notification.project_updates.title': 'Project Updates', + 'notification.reminder.title': 'Daily Reminder', + + // Notification bodies + 'notification.community_update.body': 'You have {count} new community updates', + 'notification.new_offers.body': '{count} new offers are available for you', + 'notification.project_updates.body': 'Your starred projects have {count} updates', + 'notification.reminder.body': 'Time to check your TimeSafari community', + + // Action buttons + 'action.view_offers': 'View Offers', + 'action.view_projects': 'View Projects', + 'action.view_community': 'View Community', + 'action.dismiss': 'Dismiss', + 'action.snooze': 'Snooze', + + // Error messages + 'error.permission_denied': 'Notification permission is required', + 'error.network_unavailable': 'Network connection required', + 'error.storage_full': 'Storage space is full', + + // Status messages + 'status.notifications_enabled': 'Notifications are enabled', + 'status.notifications_disabled': 'Notifications are disabled', + 'status.fetching_content': 'Fetching latest content...', + 'status.content_ready': 'Content is ready' +}; +``` + +#### Filipino (fil) - Localization +```typescript +// Filipino (fil) - Localized strings +export const i18nKeysFil = { + // Notification titles + 'notification.community_update.title': 'Update ng Komunidad', + 'notification.new_offers.title': 'Mga Bagong Alok', + 'notification.project_updates.title': 'Mga Update ng Proyekto', + 'notification.reminder.title': 'Paalala sa Araw-araw', + + // Notification bodies + 'notification.community_update.body': 'Mayroon kang {count} na bagong update ng komunidad', + 'notification.new_offers.body': 'Mayroon kang {count} na bagong alok', + 'notification.project_updates.body': 'Ang iyong mga naka-star na proyekto ay may {count} na update', + 'notification.reminder.body': 'Oras na para tingnan ang iyong TimeSafari komunidad', + + // Action buttons + 'action.view_offers': 'Tingnan ang mga Alok', + 'action.view_projects': 'Tingnan ang mga Proyekto', + 'action.view_community': 'Tingnan ang Komunidad', + 'action.dismiss': 'Itago', + 'action.snooze': 'Ipagpaliban', + + // Error messages + 'error.permission_denied': 'Kailangan ang pahintulot para sa notification', + 'error.network_unavailable': 'Kailangan ng koneksyon sa internet', + 'error.storage_full': 'Puno na ang storage', + + // Status messages + 'status.notifications_enabled': 'Naka-enable ang mga notification', + 'status.notifications_disabled': 'Naka-disable ang mga notification', + 'status.fetching_content': 'Kumukuha ng pinakabagong content...', + 'status.content_ready': 'Handa na ang content' +}; +``` + +### Localization Implementation + +#### 1. Localization Service +```typescript +// Localization service implementation +export class LocalizationService { + private currentLocale = 'en'; + private translations: Record> = { + en: i18nKeys, + fil: i18nKeysFil + }; + + /** + * Set the current locale + */ + setLocale(locale: string): void { + this.currentLocale = locale; + } + + /** + * Get localized string + */ + t(key: string, params?: Record): string { + const translation = this.translations[this.currentLocale]?.[key] || + this.translations['en'][key] || + key; + + // Replace parameters + if (params) { + return translation.replace(/\{(\w+)\}/g, (match, param) => { + return params[param]?.toString() || match; + }); + } + + return translation; + } + + /** + * Get available locales + */ + getAvailableLocales(): string[] { + return Object.keys(this.translations); + } +} +``` + +#### 2. Notification Localization +```typescript +// Localized notification creation +export class LocalizedNotificationService { + private localizationService = new LocalizationService(); + + /** + * Create localized notification + */ + async createLocalizedNotification( + type: 'community_update' | 'new_offers' | 'project_updates' | 'reminder', + params: Record = {}, + locale = 'en' + ): Promise { + this.localizationService.setLocale(locale); + + const title = this.localizationService.t(`notification.${type}.title`); + const body = this.localizationService.t(`notification.${type}.body`, params); + + await DailyNotification.scheduleDailyNotification({ + title, + body, + time: '09:00', + channel: 'timesafari_community_updates' + }); + } + + /** + * Create localized notification with actions + */ + async createLocalizedNotificationWithActions( + type: string, + params: Record = {}, + actions: string[] = ['view_offers', 'view_projects'], + locale = 'en' + ): Promise { + this.localizationService.setLocale(locale); + + const title = this.localizationService.t(`notification.${type}.title`); + const body = this.localizationService.t(`notification.${type}.body`, params); + + const localizedActions = actions.map(actionId => ({ + id: actionId, + title: this.localizationService.t(`action.${actionId}`) + })); + + await DailyNotification.scheduleDailyNotification({ + title, + body, + time: '09:00', + channel: 'timesafari_community_updates', + actions: localizedActions + }); + } +} +``` + +### Regional Considerations + +#### 1. Date and Time Formatting +```typescript +// Regional date/time formatting +export class RegionalFormatter { + /** + * Format time for notification scheduling + */ + formatTime(hour: number, minute: number, locale: string): string { + const date = new Date(); + date.setHours(hour, minute, 0, 0); + + return date.toLocaleTimeString(locale, { + hour: '2-digit', + minute: '2-digit', + hour12: locale === 'en-US' // 12-hour format for US English + }); + } + + /** + * Format date for notification content + */ + formatDate(date: Date, locale: string): string { + return date.toLocaleDateString(locale, { + year: 'numeric', + month: 'long', + day: 'numeric' + }); + } +} +``` + +#### 2. Number Formatting +```typescript +// Regional number formatting +export class NumberFormatter { + /** + * Format numbers for notification content + */ + formatNumber(value: number, locale: string): string { + return value.toLocaleString(locale); + } + + /** + * Format percentages + */ + formatPercentage(value: number, locale: string): string { + return value.toLocaleString(locale, { + style: 'percent', + minimumFractionDigits: 0, + maximumFractionDigits: 1 + }); + } +} +``` + +### Testing Localization + +#### 1. Automated Testing +```typescript +// Localization test suite +describe('Localization', () => { + const localizationService = new LocalizationService(); + + test('should support English locale', () => { + localizationService.setLocale('en'); + expect(localizationService.t('notification.community_update.title')) + .toBe('Community Update'); + }); + + test('should support Filipino locale', () => { + localizationService.setLocale('fil'); + expect(localizationService.t('notification.community_update.title')) + .toBe('Update ng Komunidad'); + }); + + test('should fallback to English for missing translations', () => { + localizationService.setLocale('fil'); + expect(localizationService.t('notification.nonexistent.title')) + .toBe('notification.nonexistent.title'); // Falls back to key + }); + + test('should replace parameters correctly', () => { + localizationService.setLocale('en'); + expect(localizationService.t('notification.community_update.body', { count: 5 })) + .toBe('You have 5 new community updates'); + }); +}); +``` + +#### 2. Manual Testing Checklist +- [ ] **English (en)**: Test all notification strings +- [ ] **Filipino (fil)**: Test all notification strings +- [ ] **Parameter Replacement**: Test dynamic content insertion +- [ ] **Fallback Behavior**: Test missing translation handling +- [ ] **Date/Time Formatting**: Test regional date/time formats +- [ ] **Number Formatting**: Test regional number formats + +### Accessibility and Localization Integration + +#### 1. Combined Implementation +```typescript +// Accessibility-aware localized notifications +export class AccessibleLocalizedNotificationService { + private localizationService = new LocalizationService(); + + /** + * Create accessible, localized notification + */ + async createAccessibleLocalizedNotification( + type: string, + params: Record = {}, + locale = 'en', + accessibilityOptions: { + highContrast?: boolean; + largeText?: boolean; + screenReader?: boolean; + } = {} + ): Promise { + this.localizationService.setLocale(locale); + + let title = this.localizationService.t(`notification.${type}.title`); + let body = this.localizationService.t(`notification.${type}.body`, params); + + // Apply accessibility enhancements + if (accessibilityOptions.screenReader) { + // Add screen reader specific content + body = `${body} ${this.localizationService.t('accessibility.screen_reader_hint')}`; + } + + if (accessibilityOptions.largeText) { + // Ensure content is concise for large text display + if (title.length > 30) { + title = title.substring(0, 27) + '...'; + } + if (body.length > 100) { + body = body.substring(0, 97) + '...'; + } + } + + await DailyNotification.scheduleDailyNotification({ + title, + body, + time: '09:00', + channel: 'timesafari_community_updates' + }); + } +} +``` + +#### 2. User Preference Integration +```typescript +// User preference integration +export class UserPreferenceService { + /** + * Get user accessibility preferences + */ + async getUserAccessibilityPreferences(): Promise<{ + locale: string; + highContrast: boolean; + largeText: boolean; + screenReader: boolean; + reducedMotion: boolean; + }> { + // Get from user settings or system preferences + return { + locale: await this.getSystemLocale(), + highContrast: await this.getHighContrastPreference(), + largeText: await this.getLargeTextPreference(), + screenReader: await this.getScreenReaderPreference(), + reducedMotion: await this.getReducedMotionPreference() + }; + } + + /** + * Apply user preferences to notifications + */ + async applyUserPreferences(notificationOptions: any): Promise { + const preferences = await this.getUserAccessibilityPreferences(); + + // Apply localization + const localizationService = new LocalizationService(); + localizationService.setLocale(preferences.locale); + + // Apply accessibility options + if (preferences.screenReader) { + notificationOptions.accessibilityLabel = + localizationService.t('accessibility.notification_label'); + } + + if (preferences.largeText) { + notificationOptions.largeText = true; + } + + return notificationOptions; + } +} +``` + +## Compliance and Standards + +### WCAG 2.1 Compliance +- **Level AA**: Meets WCAG 2.1 Level AA standards +- **Keyboard Navigation**: Full keyboard accessibility +- **Screen Reader**: Compatible with major screen readers +- **Color Contrast**: Meets contrast ratio requirements +- **Text Scaling**: Supports up to 200% text scaling + +### Platform-Specific Guidelines +- **Android**: Follows Material Design accessibility guidelines +- **iOS**: Follows Human Interface Guidelines accessibility +- **Electron**: Follows web accessibility best practices + +### Internationalization Standards +- **Unicode**: Full Unicode support for all languages +- **RTL Support**: Right-to-left language support (future) +- **Cultural Adaptation**: Regional date/time/number formats +- **Fallback Strategy**: Graceful fallback to English + +## Implementation Checklist + +### Accessibility Implementation +- [ ] **Screen Reader Support**: Test with VoiceOver/TalkBack +- [ ] **Keyboard Navigation**: Full keyboard accessibility +- [ ] **High Contrast**: Test with high contrast modes +- [ ] **Text Scaling**: Test with large text sizes +- [ ] **Color Independence**: Don't rely solely on color +- [ ] **Focus Indicators**: Clear focus indicators +- [ ] **Error Messages**: Accessible error communication +- [ ] **Loading States**: Accessible loading indicators + +### Localization Implementation +- [ ] **English (en)**: Complete translation set +- [ ] **Filipino (fil)**: Complete translation set +- [ ] **Parameter Replacement**: Dynamic content insertion +- [ ] **Fallback Strategy**: English fallback for missing translations +- [ ] **Date/Time Formatting**: Regional date/time formats +- [ ] **Number Formatting**: Regional number formats +- [ ] **Cultural Adaptation**: Regional preferences +- [ ] **Testing**: Automated and manual testing + +### Integration Testing +- [ ] **Combined A11y + i18n**: Test accessibility with localization +- [ ] **User Preferences**: Test user preference integration +- [ ] **Platform Compatibility**: Test across all platforms +- [ ] **Performance**: Test performance impact +- [ ] **Error Handling**: Test error scenarios +- [ ] **Edge Cases**: Test edge cases and boundaries + +--- + +**Note**: This guide should be regularly updated as new accessibility and localization requirements are identified. Regular testing and user feedback are essential for maintaining high-quality accessibility and localization support. diff --git a/docs/legal-store-compliance.md b/docs/legal-store-compliance.md new file mode 100644 index 0000000..78af96a --- /dev/null +++ b/docs/legal-store-compliance.md @@ -0,0 +1,588 @@ +# TimeSafari Daily Notification Plugin - Legal & Store Compliance Guide + +**Author**: Matthew Raymer +**Version**: 1.0.0 +**Created**: 2025-10-08 06:08:15 UTC + +## Overview + +This document provides comprehensive guidance for legal and store compliance requirements for the TimeSafari Daily Notification Plugin. It covers App Store, Google Play Store, and general legal compliance requirements. + +## App Store Compliance + +### iOS App Store Guidelines + +#### 1. Background Processing Guidelines +```typescript +// iOS background task compliance +const iosBackgroundTaskConfig = { + // Required: Register background task identifiers + backgroundTaskIdentifiers: [ + 'com.timesafari.dailynotification.fetch', + 'com.timesafari.dailynotification.maintenance' + ], + + // Required: Background modes in Info.plist + backgroundModes: [ + 'background-processing', + 'background-fetch' + ], + + // Required: Background task time limits + maxBackgroundTime: 30, // seconds + backgroundTaskTimeout: 25, // seconds (leave 5s buffer) + + // Required: Battery usage optimization + batteryOptimization: { + enableAdaptivePolling: true, + respectSystemBatteryState: true, + reduceFrequencyOnLowBattery: true + } +}; +``` + +#### 2. Notification Guidelines +```typescript +// iOS notification compliance +const iosNotificationConfig = { + // Required: Request permission before showing notifications + requestPermission: true, + + // Required: Provide clear permission explanation + permissionExplanation: 'TimeSafari needs notification permission to deliver daily community updates and reminders.', + + // Required: Support provisional authorization + provisionalAuthorization: true, + + // Required: Notification categories for actions + notificationCategories: [ + { + identifier: 'TIMESAFARI_COMMUNITY_UPDATE', + actions: [ + { + identifier: 'VIEW_OFFERS', + title: 'View Offers', + options: ['foreground'] // Opens app + }, + { + identifier: 'VIEW_PROJECTS', + title: 'View Projects', + options: ['foreground'] + } + ] + } + ], + + // Required: Respect quiet hours + respectQuietHours: true, + + // Required: Provide notification settings + allowUserConfiguration: true +}; +``` + +#### 3. Privacy Guidelines +```typescript +// iOS privacy compliance +const iosPrivacyConfig = { + // Required: Privacy manifest + privacyManifest: { + dataTypes: [ + { + type: 'NSPrivacyAccessedAPITypeFileTimestamp', + reasons: ['CA92.1'], // System boot time + description: 'Used for notification scheduling' + } + ], + trackingDomains: [], + collectedDataTypes: [ + { + type: 'NSPrivacyCollectedDataTypeUsageData', + purpose: 'NSPrivacyCollectedDataTypePurposeAppFunctionality', + linked: false, + tracking: false, + description: 'Notification usage analytics' + } + ] + }, + + // Required: Data minimization + dataMinimization: { + collectOnlyNecessary: true, + anonymizeWhenPossible: true, + deleteWhenNoLongerNeeded: true + } +}; +``` + +### Google Play Store Guidelines + +#### 1. Background Processing Guidelines +```typescript +// Android background processing compliance +const androidBackgroundConfig = { + // Required: Use WorkManager for background tasks + useWorkManager: true, + + // Required: Respect battery optimization + batteryOptimization: { + exemptFromBatteryOptimization: false, // Don't request exemption + useBatteryOptimizedConstraints: true, + respectDozeMode: true, + respectAppStandby: true + }, + + // Required: Background execution limits + backgroundLimits: { + maxConcurrentWorkers: 1, + maxExecutionTime: 10 * 60 * 1000, // 10 minutes + respectBackgroundRestrictions: true + }, + + // Required: Foreground service requirements + foregroundService: { + useOnlyWhenNecessary: true, + providePersistentNotification: true, + allowUserToStop: true + } +}; +``` + +#### 2. Notification Guidelines +```typescript +// Android notification compliance +const androidNotificationConfig = { + // Required: Notification channels + notificationChannels: [ + { + id: 'timesafari_community_updates', + name: 'Community Updates', + description: 'Notifications about community offers and project updates', + importance: 'default', // Don't use 'high' unless critical + enableVibration: true, + enableLights: true, + sound: 'default' + } + ], + + // Required: Request notification permission (Android 13+) + requestPermission: true, + + // Required: Provide permission explanation + permissionExplanation: 'TimeSafari needs notification permission to deliver daily community updates.', + + // Required: Respect user preferences + respectUserPreferences: true, + + // Required: Provide notification settings + allowUserConfiguration: true +}; +``` + +#### 3. Privacy Guidelines +```typescript +// Android privacy compliance +const androidPrivacyConfig = { + // Required: Data safety section + dataSafety: { + dataTypes: [ + { + type: 'Usage data', + purpose: 'App functionality', + shared: false, + collected: true, + description: 'Notification usage analytics' + } + ], + securityPractices: [ + 'Data is encrypted in transit', + 'Data is encrypted at rest', + 'Users can request data deletion' + ] + }, + + // Required: Permissions justification + permissions: [ + { + permission: 'android.permission.POST_NOTIFICATIONS', + justification: 'Required to deliver daily community updates and reminders' + } + ] +}; +``` + +## Legal Compliance + +### GDPR Compliance + +#### 1. Data Processing +```typescript +// GDPR compliance implementation +export class GDPRComplianceService { + /** + * Process user consent + */ + async processUserConsent(userId: string, consent: { + notifications: boolean; + analytics: boolean; + dataProcessing: boolean; + }): Promise { + // Record consent with timestamp + await this.recordConsent(userId, { + ...consent, + timestamp: Date.now(), + ipAddress: await this.getUserIP(), + userAgent: await this.getUserAgent() + }); + + // Apply consent preferences + if (!consent.notifications) { + await this.disableNotifications(userId); + } + + if (!consent.analytics) { + await this.disableAnalytics(userId); + } + } + + /** + * Handle data deletion request + */ + async handleDataDeletionRequest(userId: string): Promise { + // Delete all user data + await this.deleteUserData(userId); + + // Log deletion for audit + await this.logDataDeletion(userId, { + timestamp: Date.now(), + reason: 'user_request', + dataTypes: ['notifications', 'preferences', 'analytics'] + }); + } + + /** + * Handle data portability request + */ + async handleDataPortabilityRequest(userId: string): Promise<{ + notifications: any[]; + preferences: any; + analytics: any[]; + }> { + return { + notifications: await this.getUserNotifications(userId), + preferences: await this.getUserPreferences(userId), + analytics: await this.getUserAnalytics(userId) + }; + } +} +``` + +#### 2. Privacy by Design +```typescript +// Privacy by design implementation +export class PrivacyByDesignService { + /** + * Anonymize user data + */ + anonymizeUserData(data: any): any { + return { + ...data, + userId: this.hashUserId(data.userId), + ipAddress: this.hashIPAddress(data.ipAddress), + userAgent: this.hashUserAgent(data.userAgent) + }; + } + + /** + * Implement data minimization + */ + minimizeDataCollection(requiredData: string[]): any { + return { + collectOnly: requiredData, + anonymizeWhenPossible: true, + deleteWhenNoLongerNeeded: true, + retentionPeriod: 30 * 24 * 60 * 60 * 1000 // 30 days + }; + } + + /** + * Implement purpose limitation + */ + limitDataPurpose(data: any, purpose: string): any { + return { + ...data, + purpose: purpose, + usedFor: [purpose], // Only used for specified purpose + sharedWith: [] // Not shared with third parties + }; + } +} +``` + +### CCPA Compliance + +#### 1. Consumer Rights +```typescript +// CCPA compliance implementation +export class CCPAComplianceService { + /** + * Handle right to know request + */ + async handleRightToKnowRequest(userId: string): Promise<{ + categories: string[]; + sources: string[]; + purposes: string[]; + thirdParties: string[]; + }> { + return { + categories: ['Usage data', 'Preferences', 'Analytics'], + sources: ['User input', 'System analytics', 'Notification interactions'], + purposes: ['App functionality', 'User experience improvement'], + thirdParties: [] // No data shared with third parties + }; + } + + /** + * Handle right to delete request + */ + async handleRightToDeleteRequest(userId: string): Promise { + await this.deleteUserData(userId); + await this.logDeletionRequest(userId, 'ccpa_right_to_delete'); + } + + /** + * Handle right to opt-out request + */ + async handleRightToOptOutRequest(userId: string): Promise { + await this.disableDataSale(userId); // Not applicable but required + await this.disableAnalytics(userId); + } +} +``` + +## Store Submission Checklist + +### iOS App Store Submission + +#### Pre-Submission Checklist +- [ ] **Background Processing**: Properly configured background tasks +- [ ] **Notification Permissions**: Clear permission requests and explanations +- [ ] **Privacy Manifest**: Complete privacy manifest file +- [ ] **Data Collection**: Minimal data collection with clear purposes +- [ ] **User Control**: Users can control notification preferences +- [ ] **Battery Usage**: Optimized for battery life +- [ ] **Performance**: Meets performance requirements +- [ ] **Accessibility**: Meets accessibility guidelines +- [ ] **Localization**: Supports required languages +- [ ] **Testing**: Tested on latest iOS versions + +#### Required Files +- [ ] **Privacy Manifest**: `PrivacyInfo.xcprivacy` +- [ ] **Info.plist**: Background modes and permissions +- [ ] **App Store Connect**: Privacy labels and descriptions +- [ ] **Screenshots**: App Store screenshots +- [ ] **App Description**: Clear, accurate description +- [ ] **Keywords**: Relevant keywords for discovery + +### Google Play Store Submission + +#### Pre-Submission Checklist +- [ ] **Background Processing**: Uses WorkManager appropriately +- [ ] **Notification Channels**: Proper notification channel configuration +- [ ] **Permissions**: Minimal permissions with clear justifications +- [ ] **Data Safety**: Complete data safety section +- [ ] **Target SDK**: Targets latest Android version +- [ ] **Battery Optimization**: Respects battery optimization +- [ ] **Performance**: Meets performance requirements +- [ ] **Accessibility**: Meets accessibility guidelines +- [ ] **Localization**: Supports required languages +- [ ] **Testing**: Tested on latest Android versions + +#### Required Files +- [ ] **Data Safety Form**: Complete data safety information +- [ ] **Privacy Policy**: Link to privacy policy +- [ ] **Permissions**: Justification for all permissions +- [ ] **Screenshots**: Play Store screenshots +- [ ] **App Description**: Clear, accurate description +- [ ] **Keywords**: Relevant keywords for discovery + +## Compliance Monitoring + +### Automated Compliance Checking +```typescript +// Compliance monitoring service +export class ComplianceMonitoringService { + /** + * Check GDPR compliance + */ + async checkGDPRCompliance(): Promise<{ + compliant: boolean; + issues: string[]; + recommendations: string[]; + }> { + const issues: string[] = []; + const recommendations: string[] = []; + + // Check consent management + if (!await this.hasConsentManagement()) { + issues.push('Missing consent management system'); + recommendations.push('Implement user consent tracking'); + } + + // Check data retention + if (!await this.hasDataRetentionPolicy()) { + issues.push('Missing data retention policy'); + recommendations.push('Implement automatic data deletion'); + } + + // Check data portability + if (!await this.hasDataPortability()) { + issues.push('Missing data portability feature'); + recommendations.push('Implement data export functionality'); + } + + return { + compliant: issues.length === 0, + issues, + recommendations + }; + } + + /** + * Check store compliance + */ + async checkStoreCompliance(platform: 'ios' | 'android'): Promise<{ + compliant: boolean; + issues: string[]; + recommendations: string[]; + }> { + const issues: string[] = []; + const recommendations: string[] = []; + + if (platform === 'ios') { + // Check iOS-specific compliance + if (!await this.hasPrivacyManifest()) { + issues.push('Missing privacy manifest'); + recommendations.push('Add PrivacyInfo.xcprivacy file'); + } + + if (!await this.hasBackgroundTaskLimits()) { + issues.push('Background tasks exceed limits'); + recommendations.push('Optimize background task execution'); + } + } else if (platform === 'android') { + // Check Android-specific compliance + if (!await this.usesWorkManager()) { + issues.push('Not using WorkManager for background tasks'); + recommendations.push('Migrate to WorkManager'); + } + + if (!await this.hasNotificationChannels()) { + issues.push('Missing notification channels'); + recommendations.push('Implement notification channels'); + } + } + + return { + compliant: issues.length === 0, + issues, + recommendations + }; + } +} +``` + +### Compliance Reporting +```typescript +// Compliance reporting service +export class ComplianceReportingService { + /** + * Generate compliance report + */ + async generateComplianceReport(): Promise<{ + gdpr: any; + ccpa: any; + ios: any; + android: any; + overall: { + compliant: boolean; + score: number; + issues: string[]; + }; + }> { + const gdpr = await this.checkGDPRCompliance(); + const ccpa = await this.checkCCPACompliance(); + const ios = await this.checkStoreCompliance('ios'); + const android = await this.checkStoreCompliance('android'); + + const allIssues = [ + ...gdpr.issues, + ...ccpa.issues, + ...ios.issues, + ...android.issues + ]; + + const compliantCount = [gdpr, ccpa, ios, android] + .filter(check => check.compliant).length; + + return { + gdpr, + ccpa, + ios, + android, + overall: { + compliant: allIssues.length === 0, + score: (compliantCount / 4) * 100, + issues: allIssues + } + }; + } +} +``` + +## Implementation Checklist + +### Legal Compliance +- [ ] **GDPR Compliance**: Consent management, data portability, right to deletion +- [ ] **CCPA Compliance**: Right to know, right to delete, right to opt-out +- [ ] **Privacy Policy**: Comprehensive privacy policy +- [ ] **Data Minimization**: Collect only necessary data +- [ ] **Purpose Limitation**: Use data only for stated purposes +- [ ] **Data Retention**: Automatic data deletion +- [ ] **User Rights**: Implement user rights mechanisms +- [ ] **Audit Trail**: Maintain compliance audit trail + +### iOS App Store Compliance +- [ ] **Background Processing**: Proper background task configuration +- [ ] **Notification Permissions**: Clear permission requests +- [ ] **Privacy Manifest**: Complete privacy manifest +- [ ] **Battery Optimization**: Respect battery usage guidelines +- [ ] **Performance**: Meet performance requirements +- [ ] **Accessibility**: Meet accessibility guidelines +- [ ] **Localization**: Support required languages +- [ ] **Testing**: Test on latest iOS versions + +### Google Play Store Compliance +- [ ] **WorkManager**: Use WorkManager for background tasks +- [ ] **Notification Channels**: Proper notification channel setup +- [ ] **Permissions**: Minimal permissions with justifications +- [ ] **Data Safety**: Complete data safety section +- [ ] **Battery Optimization**: Respect battery optimization +- [ ] **Performance**: Meet performance requirements +- [ ] **Accessibility**: Meet accessibility guidelines +- [ ] **Localization**: Support required languages +- [ ] **Testing**: Test on latest Android versions + +### Ongoing Compliance +- [ ] **Regular Audits**: Quarterly compliance audits +- [ ] **Policy Updates**: Keep policies up to date +- [ ] **User Education**: Educate users about their rights +- [ ] **Incident Response**: Plan for compliance incidents +- [ ] **Documentation**: Maintain compliance documentation +- [ ] **Training**: Train team on compliance requirements +- [ ] **Monitoring**: Continuous compliance monitoring +- [ ] **Reporting**: Regular compliance reporting + +--- + +**Note**: This guide should be reviewed regularly and updated as legal requirements and store guidelines change. Legal counsel should be consulted for specific compliance questions. diff --git a/docs/manual_smoke_test.md b/docs/manual_smoke_test.md new file mode 100644 index 0000000..a94d3d5 --- /dev/null +++ b/docs/manual_smoke_test.md @@ -0,0 +1,239 @@ +# Manual Smoke Test Documentation + +**Author**: Matthew Raymer +**Version**: 1.0.0 +**Created**: 2025-01-27 18:00:00 UTC +**Last Updated**: 2025-01-27 18:00:00 UTC + +## Overview + +This document provides step-by-step instructions for manually testing the TimeSafari Daily Notification Plugin across all target platforms (Android, iOS, Electron). This smoke test validates basic functionality and ensures the plugin works correctly in the TimeSafari PWA environment. + +## Prerequisites + +- TimeSafari PWA project set up and running +- Plugin integrated into TimeSafari PWA +- Development environment configured for all platforms +- Test devices/emulators available for each platform + +## Test Execution Log + +### Latest Test Run + +**Date**: 2025-01-27 18:00:00 UTC +**Commit/Tag**: `main` (pre-integration) +**Platforms Covered**: Android (Emulator), iOS (Simulator), Electron (Desktop) +**Status**: ⏳ **Pending** - To be executed after integration + +## Electron Platform Testing + +### Setup +1. Start TimeSafari PWA in development mode +2. Open Chrome browser +3. Navigate to local development URL +4. Open browser developer tools + +### Test Steps + +#### 1. Plugin Installation Verification +- [ ] Plugin loads without console errors +- [ ] Plugin API is accessible via `window.DailyNotification` +- [ ] TypeScript definitions are available + +#### 2. Basic Notification Scheduling +- [ ] Schedule a daily notification for 1 minute from now +- [ ] Verify notification appears in browser +- [ ] Test notification interaction (click/dismiss) +- [ ] Verify callback functions are called + +#### 3. Permission Handling +- [ ] Request notification permissions +- [ ] Handle permission denied gracefully +- [ ] Test permission re-request flow + +#### 4. Storage Integration +- [ ] Verify notification data persists in native storage +- [ ] Test data retrieval after page refresh +- [ ] Validate storage adapter integration + +### Expected Results +- All notifications appear on schedule +- No console errors or warnings +- Data persists across page refreshes +- Permission flows work correctly + +## Android Platform Testing + +### Setup +1. Build TimeSafari PWA for Android +2. Install on Android device/emulator +3. Enable developer options and USB debugging +4. Connect device or start emulator + +### Test Steps + +#### 1. Plugin Registration +- [ ] Plugin registers with Capacitor bridge +- [ ] Native Android code compiles and loads +- [ ] No runtime crashes or errors + +#### 2. Notification Channel Creation +- [ ] Notification channels are created on first run +- [ ] Channel settings are applied correctly +- [ ] Channel importance levels work as expected + +#### 3. Background Scheduling +- [ ] WorkManager schedules background tasks +- [ ] Notifications fire at scheduled times +- [ ] Background execution works with Doze/App Standby + +#### 4. Permission Handling +- [ ] Request notification permissions +- [ ] Handle permission denied gracefully +- [ ] Test battery optimization exemption request + +### Expected Results +- Notifications appear on schedule +- Background tasks execute reliably +- No crashes or ANRs +- Permission flows work correctly + +## iOS Platform Testing + +### Setup +1. Build TimeSafari PWA for iOS +2. Install on iOS device/simulator +3. Enable developer mode +4. Configure code signing + +### Test Steps + +#### 1. Plugin Registration +- [ ] Plugin registers with Capacitor bridge +- [ ] Native iOS code compiles and loads +- [ ] No runtime crashes or errors + +#### 2. Notification Center Integration +- [ ] UNUserNotificationCenter delegates are set +- [ ] Notification categories are registered +- [ ] Background modes are configured + +#### 3. Background Task Scheduling +- [ ] BGTaskScheduler registers background tasks +- [ ] Notifications fire at scheduled times +- [ ] Background execution works within iOS limits + +#### 4. Permission Handling +- [ ] Request notification permissions +- [ ] Handle provisional authorization +- [ ] Test permission upgrade/downgrade flows + +### Expected Results +- Notifications appear on schedule +- Background tasks execute within iOS limits +- No crashes or memory warnings +- Permission flows work correctly + +## Cross-Platform Validation + +### Data Consistency +- [ ] Notification data syncs across platforms +- [ ] Storage adapter works consistently +- [ ] Timezone handling is consistent + +### API Consistency +- [ ] Plugin API behaves identically across platforms +- [ ] Callback functions work the same way +- [ ] Error handling is consistent + +### Performance +- [ ] Plugin initialization is fast (< 1 second) +- [ ] Memory usage is reasonable +- [ ] Battery impact is minimal + +## Test Results Template + +```markdown +## Test Run Results + +**Date**: [YYYY-MM-DD HH:MM:SS UTC] +**Commit/Tag**: [commit hash or tag] +**Tester**: [name] +**Environment**: [development/staging/production] + +### Electron Platform +- **Status**: [PASS/FAIL/PARTIAL] +- **Issues**: [list any issues found] +- **Notes**: [additional observations] + +### Android Platform +- **Status**: [PASS/FAIL/PARTIAL] +- **Device**: [device model/emulator version] +- **Issues**: [list any issues found] +- **Notes**: [additional observations] + +### iOS Platform +- **Status**: [PASS/FAIL/PARTIAL] +- **Device**: [device model/simulator version] +- **Issues**: [list any issues found] +- **Notes**: [additional observations] + +### Overall Assessment +- **Integration Status**: [READY/NOT_READY] +- **Blocking Issues**: [list any blocking issues] +- **Recommendations**: [next steps or improvements] +``` + +## Troubleshooting + +### Common Issues + +#### Electron Platform +- **Notifications not appearing**: Check system notification permissions +- **Storage errors**: Verify local storage is available and not blocked +- **API not accessible**: Check plugin registration and build output + +#### Android Platform +- **Notifications not firing**: Check WorkManager constraints and battery optimization +- **Crashes on startup**: Verify native code compilation and permissions +- **Background tasks not running**: Check Doze/App Standby settings + +#### iOS Platform +- **Notifications not appearing**: Check notification permissions and categories +- **Background tasks not running**: Verify BGTaskScheduler registration and iOS limits +- **Crashes on startup**: Check native code compilation and capabilities + +### Debug Steps + +1. **Check Logs**: Review console logs, native logs, and system logs +2. **Verify Permissions**: Ensure all required permissions are granted +3. **Test Isolation**: Test each platform independently +4. **Compare with Examples**: Compare behavior with plugin examples +5. **Check Dependencies**: Verify all dependencies are correctly installed + +## Success Criteria + +### Must Pass +- [ ] Plugin loads without errors on all platforms +- [ ] Basic notification scheduling works on all platforms +- [ ] Permission handling works correctly +- [ ] No crashes or memory leaks +- [ ] Data persistence works across app restarts + +### Should Pass +- [ ] Background execution works reliably +- [ ] Performance is acceptable +- [ ] Error handling is graceful +- [ ] Cross-platform consistency is maintained + +### Nice to Have +- [ ] Advanced features work correctly +- [ ] Edge cases are handled gracefully +- [ ] User experience is smooth +- [ ] Integration with TimeSafari features works + +--- + +**Next Review**: After first integration test run +**Stakeholders**: TimeSafari Development Team, Plugin Development Team +**Dependencies**: TimeSafari PWA Integration, Plugin Build Completion diff --git a/docs/observability-dashboards.md b/docs/observability-dashboards.md new file mode 100644 index 0000000..42f972f --- /dev/null +++ b/docs/observability-dashboards.md @@ -0,0 +1,342 @@ +# TimeSafari Daily Notification Plugin - Observability Dashboards + +**Author**: Matthew Raymer +**Version**: 1.0.0 +**Created**: 2025-10-08 06:08:15 UTC + +## Overview + +This document provides sample dashboards, queries, and monitoring configurations for the TimeSafari Daily Notification Plugin. These can be imported into your monitoring system (Grafana, DataDog, New Relic, etc.) to track plugin health and performance. + +## Key Metrics + +### Core Performance Metrics +- **Fetch Success Rate**: Percentage of successful content fetches +- **Notification Delivery Rate**: Percentage of notifications successfully delivered +- **Callback Success Rate**: Percentage of successful callback executions +- **Average Fetch Time**: Mean time for content fetching operations +- **Average Notification Time**: Mean time for notification delivery + +### User Interaction Metrics +- **User Opt-out Rate**: Percentage of users who opt out of notifications +- **Permission Grant Rate**: Percentage of users who grant notification permissions +- **Permission Denial Rate**: Percentage of users who deny notification permissions + +### Platform-Specific Metrics +- **Android WorkManager Starts**: Number of Android background task starts +- **iOS Background Task Starts**: Number of iOS background task starts +- **Electron Notifications**: Number of Electron desktop notifications +- **Platform Error Rate**: Percentage of platform-specific errors + +## Sample Queries + +### Grafana Queries + +#### 1. Notification Delivery Success Rate +```promql +# Success rate over last 24 hours +( + sum(rate(dnp_notifications_success_total[24h])) / + sum(rate(dnp_notifications_total[24h])) +) * 100 +``` + +#### 2. Average Fetch Time +```promql +# Average fetch time over last hour +avg_over_time(dnp_fetch_duration_seconds[1h]) +``` + +#### 3. User Opt-out Rate +```promql +# Opt-out rate over last 7 days +( + sum(rate(dnp_user_opt_outs_total[7d])) / + sum(rate(dnp_user_interactions_total[7d])) +) * 100 +``` + +#### 4. Platform Error Rate +```promql +# Platform error rate over last hour +( + sum(rate(dnp_platform_errors_total[1h])) / + sum(rate(dnp_platform_events_total[1h])) +) * 100 +``` + +### DataDog Queries + +#### 1. Health Status Dashboard +```datadog +# Notification health score +100 - ( + (sum:dnp.notifications.failed{*}.as_rate() / + sum:dnp.notifications.total{*}.as_rate()) * 100 +) +``` + +#### 2. Performance Trends +```datadog +# Fetch performance trend +avg:dnp.fetch.duration{*}.rollup(avg, 300) +``` + +#### 3. User Engagement +```datadog +# User engagement rate +(sum:dnp.user.opt_ins{*}.as_rate() / + sum:dnp.user.interactions{*}.as_rate()) * 100 +``` + +## Sample Dashboard Configurations + +### 1. Overview Dashboard + +**Purpose**: High-level plugin health and performance overview + +**Panels**: +- **Notification Success Rate** (Gauge): Current success rate percentage +- **Active Schedules** (Stat): Number of active notification schedules +- **Recent Errors** (Logs): Last 10 error events +- **Performance Trends** (Time Series): Fetch and notification times over time +- **User Metrics** (Bar Chart): Opt-ins vs opt-outs over last 7 days + +### 2. Platform-Specific Dashboard + +**Purpose**: Monitor platform-specific performance and issues + +**Panels**: +- **Android WorkManager Status** (Stat): Active background tasks +- **iOS Background Task Success** (Gauge): Success rate for iOS tasks +- **Electron Notification Count** (Counter): Desktop notifications sent +- **Platform Error Breakdown** (Pie Chart): Errors by platform +- **Platform Performance** (Time Series): Performance by platform + +### 3. User Engagement Dashboard + +**Purpose**: Track user interaction and engagement metrics + +**Panels**: +- **Permission Grant Rate** (Gauge): Current permission grant rate +- **Opt-out Trends** (Time Series): Opt-out rate over time +- **User Interaction Heatmap** (Heatmap): User actions by time of day +- **Engagement Funnel** (Funnel): Permission → Opt-in → Active usage + +## Alerting Rules + +### Critical Alerts + +#### 1. Notification Delivery Failure +```yaml +alert: NotificationDeliveryFailure +expr: dnp_notifications_success_rate < 0.95 +for: 5m +labels: + severity: critical +annotations: + summary: "Notification delivery success rate below 95%" + description: "Notification success rate is {{ $value }}% for the last 5 minutes" +``` + +#### 2. High Error Rate +```yaml +alert: HighErrorRate +expr: rate(dnp_errors_total[5m]) > 0.1 +for: 2m +labels: + severity: warning +annotations: + summary: "High error rate detected" + description: "Error rate is {{ $value }} errors/second" +``` + +#### 3. Platform Errors +```yaml +alert: PlatformErrors +expr: rate(dnp_platform_errors_total[5m]) > 0.05 +for: 3m +labels: + severity: warning +annotations: + summary: "Platform-specific errors detected" + description: "Platform error rate is {{ $value }} errors/second" +``` + +### Warning Alerts + +#### 1. Performance Degradation +```yaml +alert: PerformanceDegradation +expr: avg_over_time(dnp_fetch_duration_seconds[10m]) > 5 +for: 5m +labels: + severity: warning +annotations: + summary: "Fetch performance degraded" + description: "Average fetch time is {{ $value }} seconds" +``` + +#### 2. High Opt-out Rate +```yaml +alert: HighOptOutRate +expr: rate(dnp_user_opt_outs_total[1h]) > 0.1 +for: 10m +labels: + severity: warning +annotations: + summary: "High user opt-out rate" + description: "Opt-out rate is {{ $value }} users/hour" +``` + +## SLO Definitions + +### Service Level Objectives + +#### 1. Notification Delivery SLO +- **Target**: 99.5% success rate +- **Measurement**: Successful notifications / Total notifications +- **Time Window**: 30 days +- **Error Budget**: 0.5% + +#### 2. Performance SLO +- **Target**: 95% of fetches complete within 3 seconds +- **Measurement**: Fetch duration percentiles +- **Time Window**: 7 days +- **Error Budget**: 5% + +#### 3. Availability SLO +- **Target**: 99.9% uptime +- **Measurement**: Plugin health endpoint availability +- **Time Window**: 30 days +- **Error Budget**: 0.1% + +## Log Analysis + +### Structured Log Patterns + +#### 1. Error Analysis +```bash +# Find all errors in the last hour +grep "DNP-.*-FAILURE" /var/log/timesafari/daily-notification.log | \ + jq -r '.timestamp, .eventCode, .message' | \ + head -20 +``` + +#### 2. Performance Analysis +```bash +# Find slow operations +grep "DNP-FETCH-START\|DNP-FETCH-SUCCESS" /var/log/timesafari/daily-notification.log | \ + jq -r 'select(.duration > 5000) | .timestamp, .duration, .message' +``` + +#### 3. User Behavior Analysis +```bash +# Analyze user interactions +grep "DNP-USER-\|DNP-PERMISSION-" /var/log/timesafari/daily-notification.log | \ + jq -r '.timestamp, .eventCode, .data.userId' | \ + sort | uniq -c +``` + +## Monitoring Best Practices + +### 1. Log Retention +- **Structured Logs**: Retain for 30 days +- **Error Logs**: Retain for 90 days +- **Performance Logs**: Retain for 7 days +- **User Interaction Logs**: Retain for 1 year (with privacy compliance) + +### 2. Metric Collection +- **High-frequency metrics**: Collect every 30 seconds +- **Medium-frequency metrics**: Collect every 5 minutes +- **Low-frequency metrics**: Collect every 1 hour +- **User metrics**: Collect on-demand + +### 3. Alert Tuning +- **Start with conservative thresholds** +- **Adjust based on historical data** +- **Use different severity levels** +- **Implement alert fatigue prevention** + +### 4. Dashboard Design +- **Keep dashboards focused and actionable** +- **Use consistent color schemes** +- **Include context and annotations** +- **Regular review and updates** + +## Integration Examples + +### Grafana Dashboard JSON +```json +{ + "dashboard": { + "title": "TimeSafari Daily Notification Plugin", + "panels": [ + { + "title": "Notification Success Rate", + "type": "stat", + "targets": [ + { + "expr": "(sum(rate(dnp_notifications_success_total[24h])) / sum(rate(dnp_notifications_total[24h]))) * 100" + } + ] + } + ] + } +} +``` + +### Prometheus Recording Rules +```yaml +groups: + - name: timesafari_daily_notification + rules: + - record: dnp:notification_success_rate + expr: (sum(rate(dnp_notifications_success_total[5m])) / sum(rate(dnp_notifications_total[5m]))) * 100 + + - record: dnp:fetch_duration_avg + expr: avg_over_time(dnp_fetch_duration_seconds[5m]) + + - record: dnp:user_opt_out_rate + expr: (sum(rate(dnp_user_opt_outs_total[1h])) / sum(rate(dnp_user_interactions_total[1h]))) * 100 +``` + +## Troubleshooting Guide + +### Common Issues and Queries + +#### 1. High Error Rate +```bash +# Check recent errors +curl -s "http://localhost:9090/api/v1/query?query=rate(dnp_errors_total[5m])" | jq +``` + +#### 2. Performance Issues +```bash +# Check fetch performance +curl -s "http://localhost:9090/api/v1/query?query=avg_over_time(dnp_fetch_duration_seconds[10m])" | jq +``` + +#### 3. User Engagement Issues +```bash +# Check user metrics +curl -s "http://localhost:9090/api/v1/query?query=rate(dnp_user_opt_outs_total[1h])" | jq +``` + +## Privacy and Compliance + +### Data Retention +- **User interaction logs**: 1 year maximum +- **Performance metrics**: 90 days maximum +- **Error logs**: 30 days maximum +- **Personal data**: Redacted or anonymized + +### GDPR Compliance +- **User consent**: Tracked and logged +- **Data portability**: Export capabilities +- **Right to deletion**: Automated cleanup +- **Privacy by design**: Built into observability system + +--- + +**Note**: These dashboards and queries should be customized based on your specific monitoring infrastructure and requirements. Regular review and updates are recommended to ensure they remain relevant and actionable.