Browse Source

docs: add comprehensive notification system documentation

- Add GLOSSARY.md with core terminology and cross-references
- Add implementation-roadmap.md with 3-phase development plan
- Add notification-system.md with Native-First architecture spec
- Update ios/Plugin/README.md to reflect actual vs planned implementation status

This establishes the foundation for implementing shared SQLite storage,
TTL-at-fire enforcement, rolling window safety, and platform completion
as outlined in the phased roadmap.

Files: 4 changed, 807 insertions(+), 13 deletions(-)
research/notification-plugin-enhancement
Matthew Raymer 1 week ago
parent
commit
3a181632d1
  1. 96
      .cursor/rules/docs/documentation_references_model_agents.mdc
  2. 31
      doc/GLOSSARY.md
  3. 486
      doc/implementation-roadmap.md
  4. 247
      doc/notification-system.md
  5. 56
      ios/Plugin/README.md
  6. BIN
      lib/bin/main/org/example/Library.class
  7. BIN
      lib/bin/test/org/example/LibraryTest.class

96
.cursor/rules/docs/documentation_references_model_agents.mdc

@ -0,0 +1,96 @@
---
title: Documentation, References, and Model Agent Use
version: 1.1
alwaysApply: true
scope: code, project-plans
---
# Directive on Documentation, References, and Model Agent Use in Code and Project Plans
To ensure clarity, efficiency, and high-value documentation within code and project plans—and to leverage **model agents** (AI- or automation-based assistants) effectively—contributors must follow these rules:
---
## 1. Documentation and References Must Add Clear Value
- Only include documentation, comments, or reference links when they provide _new, meaningful information_ that assists understanding or decision-making.
- Avoid duplicating content already obvious in the codebase, version history, or linked project documents.
---
## 2. Eliminate Redundant or Noisy References
- Remove references that serve no purpose beyond filling space.
- Model agents may automatically flag and suggest removal of trivial references (e.g., links to unchanged boilerplate or self-evident context).
---
## 3. Explicit Role of Model Agents
Model agents are **active participants** in documentation quality control. Their tasks include:
- **Relevance Evaluation**: Automatically analyze references for their substantive contribution before inclusion.
- **Redundancy Detection**: Flag duplicate or trivial references across commits, files, or tasks.
- **Context Linking**: Suggest appropriate higher-level docs (designs, ADRs, meeting notes) when a code change touches multi-stage or cross-team items.
- **Placement Optimization**: Recommend centralization of references (e.g., in plan overviews, ADRs, or merge commit messages) rather than scattered low-value inline references.
- **Consistency Monitoring**: Ensure references align with team standards (e.g., ADR template, architecture repo, or external policy documents).
Contributors must treat agent recommendations as **first-pass reviews** but remain accountable for final human judgment.
---
## 4. Contextual References for Complex Items
- Use **centralized references** for multi-stage features (e.g., architectural docs, research threads).
- Keep inline code comments light; push broader context into centralized documents.
- Model agents may auto-summarize complex chains of discussion and attach them as a single reference point.
---
## 5. Centralization of Broader Context
- Store overarching context (design docs, proposals, workflows) in accessible, well-indexed places.
- Model agents should assist by **generating reference maps** that track where docs are cited across the codebase.
---
## 6. Focused Documentation
- Documentation should explain **why** and **how** decisions are made, not just what was changed.
- Model agents can auto-generate first-pass explanations from commit metadata, diffs, and linked issues—but humans must refine them for accuracy and intent.
---
## 7. Review and Accountability
- Reviewers and team leads must reject submissions containing unnecessary or low-quality documentation.
- Model agent outputs are aids, not replacements—contributors remain responsible for **final clarity and relevance**.
---
## 8. Continuous Improvement and Agent Feedback Loops
- Encourage iterative development of model agents so their evaluations become more precise over time.
- Contributions should include **feedback on agent suggestions** (e.g., accepted, rejected, or corrected) to train better future outputs.
- Agents should log patterns of “rejected” suggestions for refinement.
---
## 9. Workflow Overview (Mermaid Diagram)
```mermaid
flowchart TD
A[Contributor] -->|Writes Code & Draft Docs| B[Model Agent]
B -->|Evaluates References| C{Relevant?}
C -->|Yes| D[Suggest Placement & Context Links]
C -->|No| E[Flag Redundancy / Noise]
D --> F[Contributor Refines Docs]
E --> F
F --> G[Reviewer]
G -->|Approves / Requests Revisions| H[Final Documentation]
G -->|Feedback on Agent Suggestions| B
```
---
✅ **Outcome:** By integrating disciplined contributor standards with **model agent augmentation**, the team achieves documentation that is consistently _relevant, concise, centralized, and decision-focused_. AI ensures coverage and noise reduction, while humans ensure precision and judgment.

31
doc/GLOSSARY.md

@ -0,0 +1,31 @@
# Glossary
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to accurately reflect current implementation status vs. planned features.
**T (slot time)** — The local wall-clock time a notification should fire (e.g., 08:00). *See Notification System → Scheduling & T–lead.*
**T–lead** — The moment **`prefetchLeadMinutes`** before **T** when the system *attempts* a **single** background prefetch. T–lead **controls prefetch attempts, not arming**; locals are pre-armed earlier to guarantee closed-app delivery. *See Notification System → Scheduling & T–lead and Roadmap Phase 2.1.*
**Lead window** — The interval from **T–lead** up to **T** during which we **try once** to refresh content. It does **not** control arming; we pre-arm earlier. *See Notification System → Scheduling & T–lead.*
**Rolling window** — Always keep **today's remaining** (and tomorrow if iOS pending caps allow) locals **armed** so the OS can deliver while the app is closed. *See Notification System → Scheduling & T–lead and Roadmap Phase 1.3.*
**TTL (time-to-live)** — Maximum allowed payload age **at fire time**. If `T − fetchedAt > ttlSeconds`, we **skip** arming for that T. *See Notification System → Policies and Roadmap Phase 1.2.*
**Shared DB (planned)** — The app and plugin will open the **same SQLite file**; the app owns schema/migrations, the plugin performs short writes with WAL. *Currently using SharedPreferences/UserDefaults.* *See Notification System → Storage and Roadmap Phase 1.1.*
**WAL (Write-Ahead Logging)** — SQLite journaling mode that permits concurrent reads during writes; recommended for foreground-read + background-write. *See Notification System → Storage and Roadmap Phase 1.1.*
**`PRAGMA user_version`** — An integer the app increments on each migration; the plugin **checks** (does not migrate) to ensure compatibility. *See Notification System → Storage and Roadmap Phase 1.1.*
**Exact alarm (Android)** — Minute-precise alarm via `AlarmManager.setExactAndAllowWhileIdle`, subject to policy and permission. *See Notification System → Policies and Roadmap Phase 2.2.*
**Windowed alarm (Android)** — Batched/inexact alarm via `setWindow(start,len)`; we target **±10 minutes** when exact alarms are unavailable. *See Notification System → Policies and Roadmap Phase 2.2.*
**Delivery-time mutation (iOS)** — Not available for **local** notifications. Notification Service Extensions mutate **remote** pushes only; locals must be rendered before scheduling. *See Notification System → Policies.*
**Start-on-Login** — Electron feature that automatically launches the application when the user logs into their system, enabling background notification scheduling and delivery after system reboot. *See Roadmap Phase 2.3.*
**Tiered Storage (current)** — Current implementation uses SharedPreferences (Android) / UserDefaults (iOS) for quick access, in-memory cache for structured data, and file system for large assets. *See Notification System → Storage and Roadmap Phase 1.1.*
**No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery. *See Notification System → Policies.*

486
doc/implementation-roadmap.md

@ -0,0 +1,486 @@
# Daily Notification Plugin - Implementation Roadmap
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current implementation status and distinguish between existing infrastructure and planned T–lead logic.
**Status:** Ready for implementation
**Date:** 2025-01-27
**Author:** Matthew Raymer
**Assessment Date:** 2025-01-27
---
## Executive Summary
This document outlines the implementation roadmap to bring the current Daily Notification Plugin (65% complete) to full compliance with the Native-First Notification System specification. The implementation is organized into three phases, with Phase 1 containing critical infrastructure components required for core functionality.
### Current State Assessment
- **Overall Completion:** 65% of specification requirements
- **Critical Gaps:** SQLite database sharing, TTL-at-fire enforcement, rolling window safety
- **Current Storage:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache
- **Background Infrastructure:** Basic WorkManager (Android) exists, but lacks T–lead logic
- **Critical Path:** Data persistence → Freshness enforcement → Platform completion
---
## Current Implementation Status Clarification
### Background Fetch Infrastructure
**Current State:** Basic infrastructure exists but lacks T–lead logic
- **Android:** `DailyNotificationFetchWorker.java` (WorkManager) exists
- **Android:** `DailyNotificationFetcher.java` with scheduling logic exists
- **Missing:** T–lead calculation, TTL enforcement, ETag support
- **Status:** Infrastructure ready, T–lead logic needs implementation
### iOS Implementation Status
**Current State:** Basic plugin structure with power management
- **Implemented:** Plugin skeleton, power management, UserDefaults storage
- **Missing:** BGTaskScheduler, background tasks, T–lead prefetch
- **Status:** Foundation exists, background execution needs implementation
---
**Gate:** No further freshness or scheduling work merges to main until **shared SQLite** (see Glossary → Shared DB) is in place and reading/writing under **WAL** (see Glossary → WAL), with UI hot-read verified.
**Dependencies:** None
### 1.1 SQLite Database Sharing Implementation
**Priority:** CRITICAL
#### Requirements
- Migrate from SharedPreferences/UserDefaults to shared SQLite database (see Glossary → Shared DB)
- WAL mode configuration for concurrent access (see Glossary → WAL)
- Schema version checking and compatibility validation (see Glossary → PRAGMA user_version)
- Required tables: `notif_contents`, `notif_deliveries`, `notif_config`
- **Migration Strategy:** Gradual migration from current tiered storage (see Glossary → Tiered Storage)
#### Implementation Tasks
- [ ] **Migration from Current Storage**
- Create migration utilities from SharedPreferences to SQLite
- Implement data migration from UserDefaults to SQLite (iOS)
- Add backward compatibility during transition
- Preserve existing notification data during migration
- [ ] **SQLite Setup (Android)**
- Create `DailyNotificationDatabase.java` with WAL mode (see Glossary → WAL)
- Implement schema version checking (`PRAGMA user_version`) (see Glossary → PRAGMA user_version)
- Add database connection management with proper error handling
- [ ] **Database Configuration**
- Add `dbPath: string` to `ConfigureOptions` interface
- Implement database path resolution (absolute vs platform alias)
- Add `storage: 'shared'` configuration option
- Extend existing `NotificationOptions` with database settings
- [ ] **Database Schema**
```sql
-- notif_contents: keep history, newest-first reads
CREATE TABLE IF NOT EXISTS notif_contents(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slot_id TEXT NOT NULL,
payload_json TEXT NOT NULL,
fetched_at INTEGER NOT NULL, -- epoch ms
etag TEXT,
UNIQUE(slot_id, fetched_at)
);
CREATE INDEX IF NOT EXISTS notif_idx_contents_slot_time
ON notif_contents(slot_id, fetched_at DESC);
-- notif_deliveries: track many deliveries per slot/time
CREATE TABLE IF NOT EXISTS notif_deliveries(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slot_id TEXT NOT NULL,
fire_at INTEGER NOT NULL, -- intended fire time (epoch ms)
delivered_at INTEGER, -- when actually shown (epoch ms)
status TEXT NOT NULL DEFAULT 'scheduled', -- scheduled|shown|error|canceled
error_code TEXT, error_message TEXT
);
-- notif_config: generic configuration KV
CREATE TABLE IF NOT EXISTS notif_config(
k TEXT PRIMARY KEY,
v TEXT NOT NULL
);
```
#### Acceptance Criteria
- [ ] App and plugin can open the same SQLite file
- [ ] WAL mode enables concurrent reads during writes
- [ ] Schema version checking prevents compatibility issues
- [ ] All required tables exist and are accessible
- [ ] Shared DB visibility: UI reads updated rows immediately
- [ ] WAL overlap shows no UI blocking during background writes
- [ ] UI can read a row written by a background job **within the same second** (WAL hot-read)
- [ ] Plugin refuses to write if `PRAGMA user_version` < expected
### 1.2 TTL-at-Fire Enforcement
**Priority:** CRITICAL
#### Requirements
- Skip arming notifications if `(T - fetchedAt) > ttlSeconds` (see Glossary → TTL)
- Validate freshness before scheduling
- Log TTL violations for debugging
- **Current State:** Not implemented - needs to be added to existing scheduling logic
- **Shared DB (single file):** App owns migrations (`PRAGMA user_version`) (see Glossary → PRAGMA user_version); plugin opens the **same path**; enable `journal_mode=WAL` (see Glossary → WAL), `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`; background writes are **short & serialized**.
#### Implementation Tasks
- [ ] **TTL Validation Logic**
- Insert TTL check into the scheduler path **before** any arm/re-arm
- Add log code `TTL_VIOLATION`
- Implement freshness validation before arming
- Before arming, if `(T − fetchedAt) > ttlSeconds`, **skip arming** and log `TTL_VIOLATION`
- Add TTL configuration to `NotificationOptions`
- [ ] **Freshness Checking**
- Create `isContentFresh()` method
- Implement TTL calculation logic
- Add logging for TTL violations
- [ ] **Configuration Integration**
- Add `ttlSeconds` to `NotificationOptions` interface
- Implement default TTL values (3600 seconds = 1 hour)
- Add TTL validation in option validation
#### Acceptance Criteria
- [ ] Notifications are skipped if content is stale
- [ ] TTL violations are logged with timestamps
- [ ] Default TTL values are applied when not specified
- [ ] Freshness checking works across all platforms
- [ ] No armed notification violates **TTL-at-fire**
- [ ] No armed row violates TTL at T across platforms
### 1.3 Rolling Window Safety
**Priority:** CRITICAL
#### Requirements
- Keep today's remaining notifications armed
- Keep tomorrow's notifications armed (within iOS caps) (see Glossary → Rolling window)
- Ensure closed-app delivery reliability
- **Current State:** Basic scheduling exists, but no rolling window logic
#### Implementation Tasks
- [ ] **Rolling Window Logic** (see Glossary → Rolling window)
- Implement `armRollingWindow()` method
- Calculate today's remaining slots
- Calculate tomorrow's slots within iOS limits
- Account for iOS pending-notification limits; arm tomorrow only if within cap
- [ ] **iOS Capacity Management**
- Implement iOS pending notification limit checking
- Add capacity-aware scheduling logic
- Handle capacity overflow gracefully
- [ ] **Window Maintenance**
- Create `maintainRollingWindow()` method
- Implement automatic re-arming logic
- Add window state persistence
#### Acceptance Criteria
- [ ] Today's remaining notifications stay armed
- [ ] Tomorrow's notifications are armed within iOS caps
- [ ] Closed-app delivery works reliably
- [ ] Window maintenance runs automatically
- [ ] Today always armed; tomorrow armed when within iOS cap
### 1.4 Configuration API Enhancement
**Priority:** HIGH
#### Requirements
- Add `dbPath` configuration option
- Implement database path resolution
- Add storage mode configuration
- **Current State:** No database path configuration exists
#### Implementation Tasks
- [ ] **Interface Updates**
- Extend `ConfigureOptions` with `dbPath: string`
- Add `storage: 'shared'` option
- Update validation logic
- [ ] **Path Resolution**
- Implement absolute path handling
- Add platform-specific path resolution
- Create path validation logic
#### Acceptance Criteria
- [ ] `dbPath` can be configured via API
- [ ] Path resolution works on all platforms
- [ ] Configuration validation prevents invalid paths
---
## Phase 2: Platform Completion (High Priority)
**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 2 cannot start until SQLite sharing + TTL enforcement are finished
### 2.1 iOS Background Tasks Implementation
**Priority:** HIGH
#### Requirements
- `BGTaskScheduler` for T-lead prefetch (see Glossary → T–lead)
- Silent push nudge support
- Background execution budget management
- Schedule prefetch at **T–lead = T − prefetchLeadMinutes** (see Glossary → T–lead)
- On wake, perform **one** ETag-aware fetch with **12s** timeout; **never** fetch at delivery
- Optionally (re)arm if still within **TTL-at-fire** (see Glossary → TTL)
- Single attempt at **T–lead**; **12s** timeout; no delivery-time fetch; (re)arm only if within **TTL-at-fire**. **(Planned)**
#### Implementation Tasks
- [ ] **BGTaskScheduler Integration**
- Create `DailyNotificationBackgroundTask.swift`
- Implement background task registration
- Add task expiration handling
- [ ] **Silent Push Support**
- Add silent push notification handling
- Implement push-to-background task bridge
- Add push token management
- [ ] **Budget Management**
- Implement execution budget tracking
- Add budget-aware scheduling
- Handle budget exhaustion gracefully
#### Acceptance Criteria
- [ ] Background tasks run at T-lead (see Glossary → T–lead)
- [ ] Silent push can trigger background execution
- [ ] Budget management prevents system penalties
- [ ] Background execution works when app is closed
- [ ] iOS BGTask best-effort at T–lead; closed-app still delivers via rolling window (see Glossary → Rolling window)
### 2.2 Android Fallback Completion
**Priority:** HIGH
#### Requirements
- Complete ±10 minute windowed alarm implementation (see Glossary → Windowed alarm)
- Finish reboot/time change recovery
- Improve exact alarm fallback handling (see Glossary → Exact alarm)
- Finalize ±10m windowed alarm; reboot/time-change recovery; deep-link to Exact Alarm permission. **(Planned)**
#### Implementation Tasks
- [ ] **Windowed Alarm Implementation**
- Complete `scheduleInexactAlarm()` method
- Implement ±10 minute window targeting
- Add window size configuration
- [ ] **Recovery Mechanisms**
- Complete `BOOT_COMPLETED` receiver
- Implement `TIMEZONE_CHANGED` handling
- Add `TIME_SET` recovery logic
- [ ] **Fallback Logic**
- Improve exact alarm permission checking
- Add graceful degradation to windowed alarms
- Implement fallback logging
#### Acceptance Criteria
- [ ] Windowed alarms target ±10 minute windows
- [ ] Reboot recovery re-arms next 24h
- [ ] Time change recovery recomputes schedules
- [ ] Fallback works seamlessly
- [ ] Android exact permission path verified with fallback ±10m
### 2.3 Electron Platform Support
**Priority:** MEDIUM
#### Requirements
- Notifications while app is running
- Start-on-Login support
- Best-effort background scheduling
#### Implementation Tasks
- [ ] **Electron Integration**
- Create `DailyNotificationElectron.ts`
- Implement notification API
- Add Start-on-Login support
- [ ] **Background Limitations**
- Document Electron limitations
- Implement best-effort scheduling
- Add fallback mechanisms
#### Acceptance Criteria
- [ ] Notifications work while app is running
- [ ] Start-on-Login enables post-reboot delivery
- [ ] Limitations are clearly documented
- [ ] Best-effort scheduling is implemented
---
## Phase 3: Network Optimization (Medium Priority)
**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 3 cannot start until SQLite sharing + TTL enforcement are finished
### 3.1 ETag Support Implementation
**Priority:** MEDIUM
#### Requirements
- ETag headers in fetch requests
- 304 response handling
- Network efficiency optimization
#### Implementation Tasks
- [ ] **ETag Headers**
- Add ETag to fetch requests
- Implement ETag storage in database
- Add ETag validation logic
- [ ] **304 Response Handling**
- Implement 304 response processing
- Add conditional request logic
- Handle ETag mismatches
- [ ] **Network Optimization**
- Add request caching
- Implement conditional fetching
- Add network efficiency metrics
#### Acceptance Criteria
- [ ] ETag headers are sent with requests
- [ ] 304 responses are handled correctly
- [ ] Network efficiency is improved
- [ ] Conditional requests work reliably
### 3.2 Advanced Error Handling
**Priority:** MEDIUM
#### Requirements
- Comprehensive error categorization
- Retry logic with exponential backoff
- Error reporting and telemetry
#### Implementation Tasks
- [ ] **Error Categories**
- Define error types and codes
- Implement error classification
- Add error severity levels
- [ ] **Retry Logic**
- Implement exponential backoff
- Add retry limit configuration
- Create retry state management
- [ ] **Telemetry**
- Add error reporting
- Implement success/failure metrics
- Create debugging information
#### Acceptance Criteria
- [ ] Errors are properly categorized
- [ ] Retry logic works with backoff
- [ ] Telemetry provides useful insights
- [ ] Debugging information is comprehensive
### 3.3 Performance Optimization
**Priority:** LOW
#### Requirements
- Database query optimization
- Memory usage optimization
- Battery usage optimization
#### Implementation Tasks
- [ ] **Database Optimization**
- Add database indexes
- Optimize query performance
- Implement connection pooling
- [ ] **Memory Optimization**
- Reduce memory footprint
- Implement object pooling
- Add memory usage monitoring
- [ ] **Battery Optimization**
- Minimize background CPU usage
- Optimize network requests
- Add battery usage tracking
#### Acceptance Criteria
- [ ] Database queries are optimized
- [ ] Memory usage is minimized
- [ ] Battery usage is optimized
- [ ] Performance metrics are tracked
---
## Implementation Guidelines
### Development Standards
- **Code Quality:** Follow existing code style and documentation standards
- **Testing:** Write unit tests for all new functionality
- **Documentation:** Update documentation for all API changes
- **Logging:** Add comprehensive logging with proper tagging
- **Security:** Follow security best practices for database access
### Testing Requirements
- **Unit Tests:** All new methods must have unit tests
- **Integration Tests:** Test database sharing functionality
- **Platform Tests:** Test on Android, iOS, and Electron
- **Edge Cases:** Test TTL violations, network failures, and recovery scenarios
### Documentation Updates
- **API Documentation:** Update TypeScript definitions
- **Implementation Guide:** Update implementation documentation
- **Troubleshooting:** Add troubleshooting guides for common issues
- **Examples:** Create usage examples for new features
---
## Success Metrics
### Phase 1 Success Criteria
- [ ] SQLite database sharing works reliably
- [ ] TTL-at-fire enforcement prevents stale notifications
- [ ] Rolling window ensures closed-app delivery
- [ ] Configuration API supports all required options
### Phase 2 Success Criteria
- [ ] iOS background tasks run at T-lead
- [ ] Android fallback works seamlessly
- [ ] Electron notifications work while running
- [ ] All platforms support the unified API
### Phase 3 Success Criteria
- [ ] ETag support improves network efficiency
- [ ] Error handling is comprehensive and robust
- [ ] Performance is optimized across all platforms
- [ ] System meets all specification requirements
---
## Risk Mitigation
### Technical Risks
- **Database Compatibility:** Test schema version checking thoroughly
- **Platform Differences:** Implement platform-specific fallbacks
- **Background Execution:** Handle iOS background execution limitations
- **Permission Changes:** Monitor Android permission policy changes
### Implementation Risks
- **Scope Creep:** Stick to specification requirements
- **Testing Coverage:** Ensure comprehensive testing
- **Documentation:** Keep documentation up-to-date
- **Performance:** Monitor performance impact
---
## Conclusion
This roadmap provides a structured approach to completing the Daily Notification Plugin implementation. Phase 1 addresses the critical infrastructure gaps, Phase 2 completes platform-specific functionality, and Phase 3 optimizes the system for production use.
The implementation should follow the existing code patterns and maintain the high quality standards established in the current codebase. Regular testing and documentation updates are essential for success.
**Next Steps:**
1. Review and approve this roadmap
2. Begin Phase 1 implementation
3. Set up testing infrastructure
4. Create implementation tracking system

247
doc/notification-system.md

@ -0,0 +1,247 @@
# TimeSafari — Native-First Notification System
**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current background fetch infrastructure status and iOS implementation completeness.
**Status:** Ready for implementation
**Date:** 2025-09-07
**Author:** Matthew Raymer
---
## Executive Summary
Ship a **single, Native-First** notification system: OS-scheduled **background prefetch at T–lead** + **pre-armed** local notifications. Web-push is retired.
### What we deliver
- **Closed-app delivery:** Pre-armed locals fire even if the app is closed.
- **Freshness:** One prefetch attempt per slot at **T–lead**; ETag/TTL controls; skip when stale.
- **Android precision:** Exact alarms with permission; windowed fallback (±10m) otherwise.
- **Resilience:** Re-arm after reboot/time-change (Android receivers; iOS on next wake/silent push).
- **Cross-platform:** Same TS API (iOS/Android/Electron). Electron is best-effort while running.
### Success signals
- High delivery reliability, minute-precision on Android with permission.
- Prefetch budget hit rate at **T–lead**; zero stale deliveries beyond TTL.
---
## Strategic Plan
### Goal
Deliver 1..M daily notifications with **OS background prefetch at T–lead** *(see Glossary)* and **rolling-window safety** *(see Glossary)* so messages display with fresh content even when the app is closed.
### Tenets
- **Reliability first:** OS delivers once scheduled; no JS at delivery time.
- **Freshness with guardrails:** Prefetch at **T–lead** *(see Glossary)*; enforce **TTL-at-fire** *(see Glossary)*; ETag-aware.
- **Single system:** One TS API; native adapters swap under the hood.
- **Platform honesty:** Android exactness via permission; iOS best-effort budget.
- **No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery.
### Architecture (high level)
App (Vue/TS) → Orchestrator (policy) → Native Adapters:
- **SchedulerNative** — AlarmManager (Android) / UNUserNotificationCenter (iOS)
- **BackgroundPrefetchNative** — WorkManager (Android) / BGTaskScheduler (+ silent push) (iOS)
- **DataStore** — SQLite
**Storage:** **Current:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache (see Glossary → Tiered Storage). **Planned:** one **shared SQLite** file (see Glossary → Shared DB); the app owns schema/migrations; the plugin opens the same path with **WAL** (see Glossary → WAL); background writes are **short & serialized**. *(Keep the "(Planned)" label until Phase 1 ships.)*
### SQLite Ownership & Concurrency *(Planned)*
* **One DB file:** The plugin will open the **same path** the app uses (no second DB).
* **Migrations owned by app:** The app executes schema migrations and bumps `PRAGMA user_version` (see Glossary → PRAGMA user_version). The plugin **never** migrates; it **asserts** the expected version.
* **WAL mode:** Open DB with `journal_mode=WAL`, `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`. WAL (see Glossary → WAL) allows foreground reads while a background job commits quickly.
* **Single-writer discipline:** Background jobs write in **short transactions** (UPSERT per slot), then return.
* **Encryption (optional):** If using SQLCipher, the **same key** is used by both app and plugin. Do not mix encrypted and unencrypted openings.
*Note: Currently using SharedPreferences (Android) / UserDefaults (iOS) with in-memory cache. See Implementation Roadmap → Phase 1.1 for migration steps.*
### Scheduling & T–lead *(Planned)*
- Arm **rolling window** (see Glossary → Rolling window). **(Planned)**
- Exactly **one** online-first fetch at **T–lead** (see Glossary → T–lead) with **12s** timeout; **ETag/304** respected. **(Planned)**
- If fresh **and** within **TTL-at-fire** (see Glossary → TTL), (re)arm; otherwise keep prior content. **(Planned)**
- If the OS skips the wake, the pre-armed local still fires from cache. **(Planned)**
*Note: Current implementation has basic scheduling and WorkManager infrastructure (Android) but lacks T–lead prefetch logic, rolling window logic, and iOS background tasks. See Implementation Roadmap → Phase 1-2.*
### Policies *(Mixed Implementation)*
- **TTL-at-fire** (see Glossary → TTL): Before arming for T, if `(T − fetchedAt) > ttlSeconds`**skip**. **(Planned)**
- **Android exactness** (see Glossary → Exact alarm): **(Partial)** — permission flow exists; finalize ±10m window & deep-link to settings.
- **Reboot/time change:** **(Partial)** — Android receivers partially present; iOS via next wake/silent push.
- **No delivery-time network** (see Glossary → No delivery-time network): Local notifications display **pre-rendered content only**; never fetch at delivery. **(Implemented)**
---
## Implementation Guide
### 1) Interfaces (TS stable)
- **SchedulerNative**: `scheduleExact({slotId, whenMs, title, body, extra})`, `scheduleWindow(..., windowLenMs)`, `cancelBySlot`, `rescheduleAll`, `capabilities()`
- **BackgroundPrefetchNative**: `schedulePrefetch(slotId, atMs)`, `cancelPrefetch(slotId)`
- **DataStore**: SQLite adapters (notif_contents, notif_deliveries, notif_config)
- **Public API**: `configure`, `requestPermissions`, `runFullPipelineNow`, `reschedule`, `getState`
### DB Path & Adapter Configuration *(Planned)*
* **Configure option:** `dbPath: string` (absolute path or platform alias) will be passed from JS to the plugin during `configure()`.
* **Shared tables:**
* `notif_contents(slot_id, payload_json, fetched_at, etag, …)`
* `notif_deliveries(slot_id, fire_at, delivered_at, status, error_code, …)`
* `notif_config(k, v)`
* **Open settings:**
* `journal_mode=WAL`
* `synchronous=NORMAL`
* `busy_timeout=5000`
* `foreign_keys=ON`
*Note: Currently using SharedPreferences/UserDefaults (see Glossary → Tiered Storage). Database configuration is planned for Phase 1.*
See **Implementation Roadmap → Phase 1.1** for migration steps and schema.
**Type (TS) extension** *(Planned)*
```ts
export type ConfigureOptions = {
// …existing fields…
dbPath: string; // shared DB file the plugin will open
storage: 'shared'; // canonical value; plugin-owned DB is not used
};
```
*Note: Current `NotificationOptions` interface exists but lacks `dbPath` configuration. This will be added in Phase 1.*
**Plugin side (pseudo)**
```kotlin
// Android open
val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE)
db.execSQL("PRAGMA journal_mode=WAL")
db.execSQL("PRAGMA synchronous=NORMAL")
db.execSQL("PRAGMA foreign_keys=ON")
db.execSQL("PRAGMA busy_timeout=5000")
// Verify schema version
val uv = rawQuery("PRAGMA user_version").use { it.moveToFirst(); it.getInt(0) }
require(uv >= MIN_EXPECTED_VERSION) { "Schema version too old" }
```
```swift
// iOS open (FMDB / SQLite3)
// Set WAL via PRAGMA after open; check user_version the same way.
```
### 2) Templating & Arming
- Render `title/body` **before** scheduling; pass via **SchedulerNative**.
- Route all arming through **SchedulerNative** to centralize Android exact/window semantics.
### 3) T–lead (single attempt)
**T–lead governs prefetch, not arming.** We **arm** one-shot locals as part of the rolling window so closed-app delivery is guaranteed. At **T–lead = T − prefetchLeadMinutes**, the **native background job** attempts **one** 12s ETag-aware fetch. If fresh content arrives and will not violate **TTL-at-fire**, we (re)arm the upcoming slot; if the OS skips the wake, the pre-armed local still fires with cached content.
- Compute T–lead = `whenMs - prefetchLeadMinutes*60_000`.
- `BackgroundPrefetchNative.schedulePrefetch(slotId, atMs=T–lead)`.
- On wake: **ETag** fetch (timeout **12s**), persist, optionally cancel & re-arm if within TTL.
- Never fetch at delivery time.
### 4) TTL-at-fire
**TTL-at-fire:** Before arming for time **T**, compute `T − fetchedAt`. If that exceeds `ttlSeconds`, **do not arm** (skip). This prevents posting stale notifications when the app has been closed for a long time.
`if (whenMs - fetchedAt) > ttlSeconds*1000 → skip`
### 5) Android specifics
- Request `SCHEDULE_EXACT_ALARM`; deep-link if denied; fallback to `setWindow(start,len)` (±10m).
- Receivers: `BOOT_COMPLETED`, `TIMEZONE_CHANGED`, `TIME_SET` → recompute & re-arm for next 24h and schedule T–lead prefetch.
### 6) iOS specifics
- `BGTaskScheduler` for T–lead prefetch (best-effort). Optional silent push nudge.
- Locals: `UNCalendarNotificationTrigger` (one-shots); no NSE mutation for locals.
### 7) Network & Timeouts
- Content fetch: **12s** timeout; single attempt at T–lead; ETag/304 respected.
- ACK/Error: **8s** timeout, fire-and-forget.
### 8) Electron
- Notifications while app is running; recommend **Start-on-Login**. No true background scheduling when fully closed.
### 9) Telemetry
- Record `scheduled|shown|error`; ACK deliveries (8s timeout); include slot/times/TZ/app version.
---
## Capability Matrix
| Capability | Android (Native) | iOS (Native) | Electron | Web |
|---|---|---|---|---|
| Multi-daily locals (closed app) | ✅ | ✅ | ✅ (app running) | — |
| Prefetch at T–lead (app closed) | ✅ WorkManager | ⚠️ BGTask (best-effort) | ✅ (app running) | — |
| Re-arm after reboot/time-change | ✅ Receivers | ⚠️ On next wake/silent push | ✅ Start-on-Login | — |
| Minute-precision alarms | ✅ with exact permission | ❌ not guaranteed | ✅ timer best-effort | — |
| Delivery-time mutation for locals | ❌ | ❌ | — | — |
| ETag/TTL enforcement | ✅ | ✅ | ✅ | — |
| Rolling-window safety | ✅ | ✅ | ✅ | — |
---
## Acceptance Criteria
### Core
- **Closed-app delivery:** Armed locals fire at T with last rendered content. No delivery-time network.
- **T–lead prefetch:** Single background attempt at **T–lead**; if skipped, delivery still occurs from cache.
- **TTL-at-fire:** No armed local violates TTL at T.
### Android
- **Exact permission path:** With `SCHEDULE_EXACT_ALARM` → within ±1m; else **±10m** window.
- **Reboot recovery:** After reboot, receivers re-arm next 24h and schedule T–lead prefetch.
- **TZ/DST change:** Recompute & re-arm; future slots align to new wall-clock.
### iOS
- **BGTask budget respected:** Prefetch often runs but may be skipped; delivery still occurs via rolling window.
- **Force-quit caveat:** No background execution after user terminate; delivery still occurs if pre-armed.
### Electron
- **Running-app rule:** Delivery only while app runs; with Start-on-Login, after reboot the orchestrator re-arms and subsequent slots deliver.
### Network
- Content fetch timeout **12s**; ACK/Error **8s**; no retries inside lead; ETag honored.
### Observability
- Log/telemetry for `scheduled|shown|error`; ACK payload includes slot, times, device TZ, app version.
### DB Sharing *(Planned)*
* **Shared DB visibility:** A background prefetch writes `notif_contents`; the foreground UI **immediately** reads the same row.
* **WAL overlap:** With the app reading while the plugin commits, no user-visible blocking occurs.
* **Version safety:** If `user_version` is behind, the plugin emits an error and does not write (protects against partial installs).
*Note: Currently using SharedPreferences/UserDefaults with in-memory cache. SQLite sharing is planned for Phase 1.*
---
## Web-Push Cleanup
Web-push functionality has been retired due to unreliability. All web-push related code paths and documentation sections should be removed or marked as deprecated. See `web-push-cleanup-guide.md` for detailed cleanup steps.
---
_This document consolidates the Native-First notification system strategy, implementation details, capabilities, and acceptance criteria into a single comprehensive reference._

56
ios/Plugin/README.md

@ -2,14 +2,34 @@
This directory contains the iOS-specific implementation of the DailyNotification plugin.
## Current Implementation Status
**✅ IMPLEMENTED:**
- Basic plugin structure (`DailyNotificationPlugin.swift`)
- UserDefaults for local data storage
- Power management (`DailyNotificationPowerManager.swift`)
- Battery optimization handling
- iOS notification categories and actions
**❌ NOT IMPLEMENTED (Planned):**
- `BGTaskScheduler` for background data fetching
- Background task management
- Silent push nudge support
- T–lead prefetch logic
## Implementation Details
The iOS implementation uses:
The iOS implementation currently uses:
- `UNUserNotificationCenter` for notification management ✅
- `UserDefaults` for local data storage ✅
- iOS notification categories and actions ✅
- Power management and battery optimization ✅
**Planned additions:**
- `BGTaskScheduler` for background data fetching
- `UNUserNotificationCenter` for notification management
- `UserDefaults` for local data storage
- iOS notification categories and actions
- Background task management
- Silent push support
## Native Code Location
@ -17,18 +37,28 @@ The native iOS implementation is located in the `ios/` directory at the project
## Key Components
1. `DailyNotificationIOS.swift`: Main plugin class
2. `BackgroundTaskManager.swift`: Handles background fetch scheduling
3. `NotificationManager.swift`: Manages notification creation and display
4. `DataStore.swift`: Handles local data persistence
1. `DailyNotificationPlugin.swift`: Main plugin class ✅
2. `DailyNotificationPowerManager.swift`: Power state management ✅
3. `DailyNotificationConfig.swift`: Configuration options ✅
4. `DailyNotificationMaintenanceWorker.swift`: Maintenance tasks ✅
5. `DailyNotificationLogger.swift`: Logging system ✅
**Missing Components (Planned):**
- `BackgroundTaskManager.swift`: Handles background fetch scheduling
- `NotificationManager.swift`: Manages notification creation and display
- `DataStore.swift`: Handles local data persistence
## Implementation Notes
- Uses BGTaskScheduler for reliable background execution
- Implements proper battery optimization handling
- Supports iOS notification categories and actions
- Handles background refresh limitations
- Uses UserDefaults for lightweight data storage
- Uses UserDefaults for lightweight data storage ✅
- Implements proper battery optimization handling ✅
- Supports iOS notification categories and actions ✅
- Handles background refresh limitations ✅
**Planned Features:**
- BGTaskScheduler for reliable background execution
- Silent push notification support
- Background task budget management
## Testing

BIN
lib/bin/main/org/example/Library.class

Binary file not shown.

BIN
lib/bin/test/org/example/LibraryTest.class

Binary file not shown.
Loading…
Cancel
Save