Comprehensive refactoring to make DailyNotificationPlugin a thin adapter,
eliminate duplicated logic, remove unsafe operations, and harden security.
Batch 0 - Constants Centralization:
- Created DailyNotificationConstants.kt to eliminate magic numbers and duplicates
- Centralized: PERMISSION_REQUEST_CODE, channel constants, intent actions/extras,
SharedPreferences keys, WorkManager tags, notification IDs
- Replaced duplicates across Plugin, PermissionManager, ChannelManager, Scheduler
Batch 1 - Permission Flow Unification:
- Created PermissionStatus.kt data class for unified permission reporting
- Added PermissionManager.getPermissionStatus() as single source of truth
- Implemented PendingPermissionRequest tracking for reliable resume resolution
- Replaced method-name-based resume logic with token-based tracking
- Plugin now delegates all permission checks to PermissionManager
Batch 2 - Notification Status Checker Hardening:
- Modified NotificationStatusChecker to always check OS-level notification
enablement via NotificationManagerCompat.areNotificationsEnabled()
- Added getReadinessReport() method providing comprehensive status with issues
and actionable guidance
- Plugin checkStatus() now uses readiness report
Batch 3 - Cancel Semantics Safety:
- Removed unsafe brute-force cancellation loop (was trying request codes 0-100)
- Cancellation now only targets alarms proven to exist in database
- Prevents accidental cancellation of other alarms and false confidence
Batch 4 - Legacy Scheduler Removal:
- Removed unused legacy scheduleExactAlarm() method (48 lines)
- All scheduling now goes through modern paths:
1. exactAlarmManager.scheduleAlarm() (if available)
2. pendingIntentManager.scheduleExactAlarm() (modern path)
3. pendingIntentManager.scheduleWindowedAlarm() (fallback)
Batch 5 - Input Contract Tightening:
- Enforced single input shape for updateStarredPlans: { planIds: string[] }
- Added validation: rejects non-array, non-string elements, empty strings
- Legacy support: single string normalized to array (with warning)
- Clear error messages for contract violations
Batch 6 - Token Storage Security:
- Added explicit opt-in for JWT token persistence (persistToken: true)
- Default behavior: tokens NOT persisted (secure default)
- Security warnings logged when persistence is enabled
- Documents unencrypted storage risk
Batch 7 - Plugin Thinning:
- Moved getExactAlarmStatus() to PermissionManager.getExactAlarmStatus()
- Moved canRequestExactAlarmPermission() to PermissionManager
- Removed direct AlarmManager access in cancelAllNotifications()
- Delegated scheduleUserNotification/scheduleDualNotification permission
handling to PermissionManager.requestExactAlarmPermission()
- Removed unused imports: AlarmManager, PendingIntent, PowerManager,
NotificationManagerCompat
Result:
- Plugin is now a thin adapter delegating to services
- No duplicated permission logic
- No unsafe cancellation operations
- No legacy scheduler paths
- Secure token storage defaults
- Clear input contracts
- Comprehensive status reporting
Files modified:
- DailyNotificationConstants.kt (new)
- PermissionStatus.kt (new)
- DailyNotificationPlugin.kt (thinned, ~500 lines refactored)
- PermissionManager.java (enhanced with status methods)
- NotificationStatusChecker.java (hardened)
- DailyNotificationScheduler.java (legacy removed)
Refs: Cursor directive Batches 0-7
77 lines
3.4 KiB
Plaintext
77 lines
3.4 KiB
Plaintext
refactor(android): Complete plugin refactoring and safety fixes (Batches 0-7)
|
|
|
|
Comprehensive refactoring to make DailyNotificationPlugin a thin adapter,
|
|
eliminate duplicated logic, remove unsafe operations, and harden security.
|
|
|
|
Batch 0 - Constants Centralization:
|
|
- Created DailyNotificationConstants.kt to eliminate magic numbers and duplicates
|
|
- Centralized: PERMISSION_REQUEST_CODE, channel constants, intent actions/extras,
|
|
SharedPreferences keys, WorkManager tags, notification IDs
|
|
- Replaced duplicates across Plugin, PermissionManager, ChannelManager, Scheduler
|
|
|
|
Batch 1 - Permission Flow Unification:
|
|
- Created PermissionStatus.kt data class for unified permission reporting
|
|
- Added PermissionManager.getPermissionStatus() as single source of truth
|
|
- Implemented PendingPermissionRequest tracking for reliable resume resolution
|
|
- Replaced method-name-based resume logic with token-based tracking
|
|
- Plugin now delegates all permission checks to PermissionManager
|
|
|
|
Batch 2 - Notification Status Checker Hardening:
|
|
- Modified NotificationStatusChecker to always check OS-level notification
|
|
enablement via NotificationManagerCompat.areNotificationsEnabled()
|
|
- Added getReadinessReport() method providing comprehensive status with issues
|
|
and actionable guidance
|
|
- Plugin checkStatus() now uses readiness report
|
|
|
|
Batch 3 - Cancel Semantics Safety:
|
|
- Removed unsafe brute-force cancellation loop (was trying request codes 0-100)
|
|
- Cancellation now only targets alarms proven to exist in database
|
|
- Prevents accidental cancellation of other alarms and false confidence
|
|
|
|
Batch 4 - Legacy Scheduler Removal:
|
|
- Removed unused legacy scheduleExactAlarm() method (48 lines)
|
|
- All scheduling now goes through modern paths:
|
|
1. exactAlarmManager.scheduleAlarm() (if available)
|
|
2. pendingIntentManager.scheduleExactAlarm() (modern path)
|
|
3. pendingIntentManager.scheduleWindowedAlarm() (fallback)
|
|
|
|
Batch 5 - Input Contract Tightening:
|
|
- Enforced single input shape for updateStarredPlans: { planIds: string[] }
|
|
- Added validation: rejects non-array, non-string elements, empty strings
|
|
- Legacy support: single string normalized to array (with warning)
|
|
- Clear error messages for contract violations
|
|
|
|
Batch 6 - Token Storage Security:
|
|
- Added explicit opt-in for JWT token persistence (persistToken: true)
|
|
- Default behavior: tokens NOT persisted (secure default)
|
|
- Security warnings logged when persistence is enabled
|
|
- Documents unencrypted storage risk
|
|
|
|
Batch 7 - Plugin Thinning:
|
|
- Moved getExactAlarmStatus() to PermissionManager.getExactAlarmStatus()
|
|
- Moved canRequestExactAlarmPermission() to PermissionManager
|
|
- Removed direct AlarmManager access in cancelAllNotifications()
|
|
- Delegated scheduleUserNotification/scheduleDualNotification permission
|
|
handling to PermissionManager.requestExactAlarmPermission()
|
|
- Removed unused imports: AlarmManager, PendingIntent, PowerManager,
|
|
NotificationManagerCompat
|
|
|
|
Result:
|
|
- Plugin is now a thin adapter delegating to services
|
|
- No duplicated permission logic
|
|
- No unsafe cancellation operations
|
|
- No legacy scheduler paths
|
|
- Secure token storage defaults
|
|
- Clear input contracts
|
|
- Comprehensive status reporting
|
|
|
|
Files modified:
|
|
- DailyNotificationConstants.kt (new)
|
|
- PermissionStatus.kt (new)
|
|
- DailyNotificationPlugin.kt (thinned, ~500 lines refactored)
|
|
- PermissionManager.java (enhanced with status methods)
|
|
- NotificationStatusChecker.java (hardened)
|
|
- DailyNotificationScheduler.java (legacy removed)
|
|
|
|
Refs: Cursor directive Batches 0-7
|