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