- pnpm 10 workspace + TypeScript strict + ESLint flat + Prettier - CLAUDE.md as canonical brief - docs/tasks/ — 22 task briefs broken out by phase for sub-sessions - docs/decisions/ — ADR scaffold Implements task 01 (repo-init).
29 lines
1.2 KiB
Markdown
29 lines
1.2 KiB
Markdown
# 41 — Reminders engine
|
|
|
|
## Goal
|
|
|
|
A generic, entity-agnostic reminder system that fires at `fire_at` and routes through the notification bus.
|
|
|
|
## Depends on
|
|
|
|
- 40 (push), 42 (bus)
|
|
|
|
## Scope
|
|
|
|
- Schema: `reminders` (`id`, `household_id`, `entity_type`, `entity_id`, `fire_at` timestamptz, `channel` text default `'auto'`, `fired_at` timestamptz nullable, `created_by`).
|
|
- Worker: a long-running tick (every 30s) that selects due un-fired reminders, calls `notify(...)`, marks `fired_at`. Runs in the same Node process via `setInterval` guarded by a Postgres advisory lock to allow future horizontal scaling.
|
|
- `_core/reminders.ts` exposes `scheduleReminder(...)`, `cancelReminder(id)`, `listReminders(entityType, entityId)`.
|
|
- Notes module's `remind_at` field calls `scheduleReminder` on save and `cancelReminder` when cleared.
|
|
- Calendar module: optional "remind me" on event create (default 30 min before).
|
|
|
|
## Out of scope
|
|
|
|
- Recurring reminders (use rrule later).
|
|
- Snooze.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] A note with `remind_at = now + 1min` fires within 90s and triggers a push notification.
|
|
- [ ] Editing the note's `remind_at` updates the existing reminder, not creates duplicates.
|
|
- [ ] Worker survives DB blips (caught + logged, not crashed).
|