# Plugin Requirements & Implementation Directive

**Author**: Matthew Raymer  
**Date**: November 2025  
**Status**: Active Requirements - Implementation Guide

## Purpose

This document defines the **rules the plugin must follow** to behave predictably across Android and iOS platforms. It specifies:

* Persistence requirements
* Recovery strategies
* JS/TS API contract and caveats
* Missed alarm handling
* Platform-specific requirements
* Testing requirements

**This document should be updated** after exploration findings are documented.

**Reference**: See [Platform Capability Reference](../alarms/01-platform-capability-reference.md) for OS-level facts.

---

## 1. Core Requirements

### 1.1 Plugin Behavior Guarantees

The plugin **must** guarantee the following behaviors:

| Behavior | Android | iOS | Implementation Required |
| -------- | ------- | --- | ----------------------- |
| Notification fires after swipe/termination | ✅ Yes | ✅ Yes | OS-guaranteed (verify) |
| Notification fires after reboot | ⚠️ Only if rescheduled | ✅ Yes | Android: Boot receiver required |
| Missed alarm detection | ✅ Required | ✅ Required | Both: App launch recovery |
| Force stop recovery | ✅ Required | N/A | Android: App restart recovery |
| Exact timing | ✅ With permission | ⚠️ ±180s tolerance | Android: Permission check |

### 1.2 Plugin Behavior Limitations

The plugin **cannot** guarantee:

| Limitation | Platform | Reason |
| ---------- | -------- | ------ |
| Notification after Force Stop (Android) | Android | OS hard kill |
| App code execution on iOS notification fire | iOS | OS limitation |
| Background execution timing (iOS) | iOS | System-controlled |
| Exact timing (iOS) | iOS | ±180s tolerance |

---

## 2. Persistence Requirements

### 2.1 Required Persistence Items

The plugin **must** persist the following for each scheduled alarm/notification:

| Field | Type | Required | Purpose |
| ----- | ---- | -------- | ------- |
| `alarm_id` | String | ✅ Yes | Unique identifier |
| `trigger_time` | Long/TimeInterval | ✅ Yes | When to fire |
| `repeat_rule` | String/Enum | ✅ Yes | NONE, DAILY, WEEKLY, CUSTOM |
| `channel_id` | String | ✅ Yes | Notification channel (Android) |
| `priority` | String/Int | ✅ Yes | Notification priority |
| `title` | String | ✅ Yes | Notification title |
| `body` | String | ✅ Yes | Notification body |
| `sound_enabled` | Boolean | ✅ Yes | Sound preference |
| `vibration_enabled` | Boolean | ✅ Yes | Vibration preference |
| `payload` | String/JSON | ⚠️ Optional | Additional content |
| `created_at` | Long/TimeInterval | ✅ Yes | Creation timestamp |
| `updated_at` | Long/TimeInterval | ✅ Yes | Last update timestamp |
| `enabled` | Boolean | ✅ Yes | Whether alarm is active |

### 2.2 Storage Implementation

**Android**:
* **Primary**: Room database (`DailyNotificationDatabase`)
* **Location**: `android/src/main/java/com/timesafari/dailynotification/`
* **Entities**: `Schedule`, `NotificationContentEntity`, `ContentCache`

**iOS**:
* **Primary**: UNUserNotificationCenter (OS-managed)
* **Secondary**: Plugin storage (UserDefaults, CoreData, or files)
* **Location**: `ios/Plugin/`
* **Component**: `DailyNotificationStorage?`

### 2.3 Persistence Validation

The plugin **must**:
* Validate persistence on every alarm schedule
* Log persistence failures
* Handle persistence errors gracefully
* Provide recovery mechanism if persistence fails

---

## 3. Recovery Requirements

### 3.1 Required Recovery Points

The plugin **must** implement recovery at the following points:

#### 3.1.1 Boot Event (Android Only)

**Trigger**: `BOOT_COMPLETED` broadcast

**Required Actions**:
1. Load all enabled alarms from persistent storage
2. Reschedule each alarm using AlarmManager
3. Detect missed alarms (trigger_time < now)
4. Generate missed alarm events/notifications
5. Log recovery actions

**Code Reference**: `BootReceiver.kt` line 24

**Implementation Status**: ☐ Implemented / ☐ Missing

---

#### 3.1.2 App Cold Start

**Trigger**: App launched from terminated state

**Required Actions**:
1. Load all enabled alarms from persistent storage
2. Verify active alarms match stored alarms
3. Detect missed alarms (trigger_time < now)
4. Reschedule future alarms
5. Generate missed alarm events/notifications
6. Log recovery actions

**Implementation Status**: ☐ Implemented / ☐ Missing

**Code Location**: Check plugin initialization (`DailyNotificationPlugin.load()` or equivalent)

---

#### 3.1.3 App Warm Start

**Trigger**: App returning from background

**Required Actions**:
1. Verify active alarms are still scheduled
2. Detect missed alarms (trigger_time < now)
3. Reschedule if needed
4. Log recovery actions

**Implementation Status**: ☐ Implemented / ☐ Missing

---

#### 3.1.4 User Taps Notification

**Trigger**: User interaction with notification

**Required Actions**:
1. Launch app (OS handles)
2. Detect if notification was missed
3. Handle notification action
4. Update alarm state if needed

**Implementation Status**: ☐ Implemented / ☐ Missing

---

### 3.2 Missed Alarm Handling

The plugin **must** detect and handle missed alarms:

**Definition**: An alarm is "missed" if:
* `trigger_time < now`
* Alarm was not fired (or firing status unknown)
* Alarm is still enabled

**Required Actions**:
1. **Detect** missed alarms during recovery
2. **Generate** missed alarm event/notification
3. **Reschedule** future occurrences (if repeating)
4. **Log** missed alarm for debugging
5. **Update** alarm state (mark as missed or reschedule)

**Implementation Requirements**:
* Must run on app launch (cold/warm start)
* Must run on boot (Android)
* Must not duplicate missed alarm notifications
* Must handle timezone changes

**Code Location**: To be implemented in recovery logic

---

## 4. JS/TS API Contract

### 4.1 API Guarantees

The plugin **must** document and guarantee the following behaviors to JavaScript/TypeScript developers:

#### 4.1.1 `scheduleDailyNotification(options)`

**Guarantees**:
* ✅ Notification will fire if app is swiped from recents
* ✅ Notification will fire if app is terminated by OS
* ⚠️ Notification will fire after reboot **only if**:
  * Android: Boot receiver is registered and working
  * iOS: Automatic (OS handles)
* ❌ Notification will **NOT** fire after Android Force Stop until app is opened
* ⚠️ iOS notifications have ±180s timing tolerance

**Caveats**:
* Android requires `SCHEDULE_EXACT_ALARM` permission on Android 12+
* Android requires `RECEIVE_BOOT_COMPLETED` permission for reboot recovery
* iOS requires notification authorization

**Error Codes**:
* `EXACT_ALARM_PERMISSION_REQUIRED` - Android 12+ exact alarm permission needed
* `NOTIFICATIONS_DENIED` - Notification permission denied
* `SCHEDULE_FAILED` - Scheduling failed (check logs)

---

#### 4.1.2 `scheduleDailyReminder(options)`

**Guarantees**:
* Same as `scheduleDailyNotification()` above
* Static reminder (no content dependency)
* Fires even if content fetch fails

---

#### 4.1.3 `getNotificationStatus()`

**Guarantees**:
* Returns current notification status
* Includes pending notifications
* Includes last notification time
* May include missed alarm information

---

### 4.2 API Warnings

The plugin **must** document the following warnings:

**Android**:
* "Notifications will not fire after device reboot unless the app is opened at least once"
* "Force Stop will prevent all notifications until the app is manually opened"
* "Exact alarm permission is required on Android 12+ for precise timing"

**iOS**:
* "Notifications have ±180 seconds timing tolerance"
* "App code does not run when notifications fire (unless user interacts)"
* "Background execution is system-controlled and not guaranteed"

**Cross-Platform**:
* "Missed alarms are detected on app launch, not at trigger time"
* "Repeating alarms must be rescheduled for each occurrence"

---

### 4.3 API Error Handling

The plugin **must**:
* Return clear error messages
* Include error codes for programmatic handling
* Open system settings when permission is needed
* Provide actionable guidance in error messages

**Example Error Response**:
```typescript
{
  code: "EXACT_ALARM_PERMISSION_REQUIRED",
  message: "Exact alarm permission required. Please grant 'Alarms & reminders' permission in Settings, then try again.",
  action: "opened_settings" // or "permission_denied"
}
```

---

## 5. Platform-Specific Requirements

### 5.1 Android Requirements

#### 5.1.1 Permissions

**Required Permissions**:
* `RECEIVE_BOOT_COMPLETED` - Boot receiver
* `SCHEDULE_EXACT_ALARM` - Android 12+ (API 31+) for exact alarms
* `POST_NOTIFICATIONS` - Android 13+ (API 33+) for notifications

**Permission Handling**:
* Check permission before scheduling
* Request permission if not granted
* Open system settings if permission denied
* Provide clear error messages

**Code Reference**: `DailyNotificationPlugin.kt` line 1309

---

#### 5.1.2 Manifest Entries

**Required Manifest Entries**:
```xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<receiver
    android:name="org.timesafari.dailynotification.BootReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<receiver
    android:name="org.timesafari.dailynotification.DailyNotificationReceiver"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="org.timesafari.daily.NOTIFICATION" />
    </intent-filter>
</receiver>
```

**Location**: Test app manifest: `test-apps/android-test-app/app/src/main/AndroidManifest.xml`

---

#### 5.1.3 Notification Channels

**Required Channels**:
* `timesafari.daily` - Primary notification channel
* `daily_reminders` - Reminder notifications (if used)

**Channel Configuration**:
* Importance: HIGH (for alarms), DEFAULT (for reminders)
* Sound: Enabled by default
* Vibration: Enabled by default
* Show badge: Enabled

**Code Reference**: `ChannelManager.java` or `NotifyReceiver.kt` line 454

---

#### 5.1.4 Alarm Scheduling

**Required API Usage**:
* `setAlarmClock()` for Android 5.0+ (preferred)
* `setExactAndAllowWhileIdle()` for Android 6.0+ (fallback)
* `setExact()` for older versions (fallback)

**Code Reference**: `NotifyReceiver.kt` line 219, 223, 231

---

### 5.2 iOS Requirements

#### 5.2.1 Permissions

**Required Permissions**:
* Notification authorization (requested at runtime)

**Permission Handling**:
* Request permission before scheduling
* Handle authorization status
* Provide clear error messages

---

#### 5.2.2 Background Tasks

**Required Background Task Identifiers**:
* `org.timesafari.dailynotification.fetch` - Background fetch
* `org.timesafari.dailynotification.notify` - Notification task (if used)

**Background Task Registration**:
* Register in `Info.plist`:
  ```xml
  <key>BGTaskSchedulerPermittedIdentifiers</key>
  <array>
      <string>org.timesafari.dailynotification.fetch</string>
  </array>
  ```

**Code Reference**: `DailyNotificationPlugin.swift` line 31-32

---

#### 5.2.3 Notification Scheduling

**Required API Usage**:
* `UNUserNotificationCenter.add()` - Schedule notifications
* `UNCalendarNotificationTrigger` - Calendar-based triggers (preferred)
* `UNTimeIntervalNotificationTrigger` - Time interval triggers

**Code Reference**: `DailyNotificationScheduler.swift` line 185

---

#### 5.2.4 Notification Categories

**Required Categories**:
* `DAILY_NOTIFICATION` - Primary notification category

**Category Configuration**:
* Actions: Configure as needed
* Options: Custom sound, custom actions

**Code Reference**: `DailyNotificationScheduler.swift` line 62+

---

## 6. Testing Requirements

### 6.1 Required Test Scenarios

The plugin **must** be tested for:

**Android**:
* [ ] Base case (alarm fires on time)
* [ ] Swipe from recents
* [ ] OS kill (memory pressure)
* [ ] Device reboot (with and without app launch)
* [ ] Force stop (with app restart)
* [ ] Exact alarm permission (Android 12+)
* [ ] Boot receiver functionality
* [ ] Missed alarm detection

**iOS**:
* [ ] Base case (notification fires on time)
* [ ] Swipe app away
* [ ] Device reboot (without app launch)
* [ ] Hard termination and relaunch
* [ ] Background execution limits
* [ ] Missed notification detection

**Cross-Platform**:
* [ ] Timezone changes
* [ ] Clock adjustments
* [ ] Multiple simultaneous alarms
* [ ] Repeating alarms
* [ ] Alarm cancellation

---

### 6.2 Test Harness Requirements

**Required Test Tools**:
* Real devices (not just emulators)
* ADB commands for Android testing
* Xcode for iOS testing
* Log monitoring tools

**Required Test Documentation**:
* Test results matrix
* Log snippets for failures
* Screenshots/videos for UI issues
* Performance metrics

---

## 7. Versioning Requirements

### 7.1 Breaking Changes

Any change to alarm behavior is **breaking** and requires:

* **MAJOR version bump** (semantic versioning)
* **Migration guide** for existing users
* **Deprecation warnings** (if applicable)
* **Clear changelog entry**

### 7.2 Non-Breaking Changes

Non-breaking changes include:
* Bug fixes
* Performance improvements
* Additional features (backward compatible)
* Documentation updates

---

## 8. Implementation Checklist

### 8.1 Android Implementation

- [ ] Boot receiver registered in manifest
- [ ] Boot receiver reschedules alarms from database
- [ ] Exact alarm permission checked and requested
- [ ] Notification channels created
- [ ] Alarm scheduling uses correct API (`setAlarmClock` preferred)
- [ ] Persistence implemented (Room database)
- [ ] Missed alarm detection on app launch
- [ ] Force stop recovery on app restart
- [ ] Error handling and user guidance

### 8.2 iOS Implementation

- [ ] Notification authorization requested
- [ ] Background tasks registered in Info.plist
- [ ] Notification scheduling uses UNUserNotificationCenter
- [ ] Calendar triggers used (not just time interval)
- [ ] Plugin-side persistence (if needed for missed detection)
- [ ] Missed notification detection on app launch
- [ ] Background task limitations documented
- [ ] Error handling and user guidance

### 8.3 Cross-Platform Implementation

- [ ] JS/TS API contract documented
- [ ] Platform-specific caveats documented
- [ ] Error codes standardized
- [ ] Test scenarios covered
- [ ] Migration guide (if breaking changes)

---

## 9. Open Questions / TODOs

**To be filled after exploration**:

| Question | Platform | Priority | Status |
| -------- | -------- | -------- | ------ |
| Does boot receiver work correctly? | Android | High | ☐ |
| Is missed alarm detection implemented? | Both | High | ☐ |
| Are all required fields persisted? | Both | Medium | ☐ |
| Is force stop recovery implemented? | Android | High | ☐ |
| Does iOS plugin persist state separately? | iOS | Medium | ☐ |

---

## Related Documentation

- [Platform Capability Reference](../alarms/01-platform-capability-reference.md) - OS-level facts
- [Plugin Behavior Exploration Template](./plugin-behavior-exploration-template.md) - Exploration template
- [Improve Alarm Directives](./improve-alarm-directives.md) - Improvement directive
- [Boot Receiver Testing Guide](./boot-receiver-testing-guide.md) - Testing procedures
- [App Startup Recovery Solution](./app-startup-recovery-solution.md) - Recovery mechanisms

---

## Version History

- **v1.0** (November 2025): Initial requirements document
  - Persistence requirements
  - Recovery requirements
  - JS/TS API contract
  - Platform-specific requirements
  - Testing requirements

