style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
@@ -23,12 +23,12 @@ key_files:
- apps/api/src/index.ts
decisions:
- "Cross-join (sql`1=1`) used to pair each due shared event with ALL push subscriptions in one Drizzle query (2 innerJoins: calendarEvents→calendars→pushSubscriptions) — matches the test scaffold's mock chain shape"
- "Grouping by uid after the flat cross-join result ensures all subscriptions for a deduped event are dispatched in one pass (prevents sub2 being silently skipped after dedup fires for sub1)"
- "sentReminders.add(key) called BEFORE iterating subs to prevent re-entry on concurrent ticks"
- 'Grouping by uid after the flat cross-join result ensures all subscriptions for a deduped event are dispatched in one pass (prevents sub2 being silently skipped after dedup fires for sub1)'
- 'sentReminders.add(key) called BEFORE iterating subs to prevent re-entry on concurrent ticks'
- "title fallback: event.title ?? uid — prevents 'undefined' in push copy for pre-05-07 rows"
metrics:
duration: 6
completed_date: "2026-06-10"
completed_date: '2026-06-10'
tasks_completed: 1
files_changed: 2
---
@@ -48,6 +48,7 @@ The RED scaffold (`tests/broker/reminderScheduler.test.ts`) was already committe
Created `apps/api/src/broker/reminderScheduler.ts` with:
**`runReminderCheck(now = new Date())`** — single reminder scan cycle:
- Drizzle query: `db.select().from(calendarEvents).innerJoin(calendars, ...).innerJoin(pushSubscriptions, sql\`1=1\`)` — 2 innerJoins; cross-join fans each event out to all subscribers
- WHERE: `isShared=true AND allDay=false AND dtstartUtc >= now+14min AND dtstartUtc <= now+16min`
- D-05 enforced in QUERY (not copy) — personal events excluded at SQL level
@@ -60,12 +61,14 @@ Created `apps/api/src/broker/reminderScheduler.ts` with:
- Empty shared-calendar / empty push_subscriptions: cross-join returns 0 rows → zero sends, no crash (D-16)
**`startReminderScheduler()`** — node-cron `* * * * *` schedule (every minute):
- Same shape as `startBrokerPoller` in `poller.ts``.catch()` on the returned promise
- Not called at import time (guards the test process per WR-04)
**`index.ts`** — added `startReminderScheduler()` call in the `isMainModule()` guard, after `startOutboxWorker()` and after `webpush.setVapidDetails()` (so VAPID is configured before the scheduler starts).
**TDD Gate Compliance:**
- RED: `test(05-01): add Wave-0 RED scaffolds + VAPID fixture + setup truncation``ef558b6` (Plan 05-01)
- GREEN: `feat(05-06): implement reminderScheduler — shared timed 15-min reminder scan``b95f671`
@@ -90,6 +93,7 @@ None. Plan executed exactly as written.
### Architecture note (no deviation — design decision)
The cross-join approach (`innerJoin(pushSubscriptions, sql\`1=1\`)`) was chosen over two separate `db.select()` calls because:
1. The test scaffold's mock requires exactly 2 `innerJoin()` calls in a single chain (`.from().innerJoin().innerJoin().where()`)
2. A cross-join is semantically correct: shared reminder → all members
3. Grouping by uid after the flat result correctly handles the fan-out while maintaining the `uid:minuteBucket` dedup semantics
@@ -102,18 +106,20 @@ None. The scheduler is fully implemented. The `calendar_events.title` column may
No new threat surface. All three plan threats mitigated:
| Threat | Status |
|--------|--------|
| T-05-17: personal-calendar event in reminder | Mitigated — `WHERE isShared=true` enforced in SQL |
| T-05-18: duplicate reminder storm at window boundary | Mitigated — in-memory dedup Set; per-event try/catch |
| T-05-19: one bad subscription aborting cycle | Mitigated — per-subscription try/catch; dispatchPush swallows 410/404 |
| Threat | Status |
| ---------------------------------------------------- | --------------------------------------------------------------------- |
| T-05-17: personal-calendar event in reminder | Mitigated — `WHERE isShared=true` enforced in SQL |
| T-05-18: duplicate reminder storm at window boundary | Mitigated — in-memory dedup Set; per-event try/catch |
| T-05-19: one bad subscription aborting cycle | Mitigated — per-subscription try/catch; dispatchPush swallows 410/404 |
## Self-Check
**Files created/verified:**
- [x] apps/api/src/broker/reminderScheduler.ts — exists
**Commits verified:**
- ef558b6: test(05-01): add Wave-0 RED scaffolds + VAPID fixture + setup truncation (RED gate — Plan 05-01)
- b95f671: feat(05-06): implement reminderScheduler — shared timed 15-min reminder scan (GREEN gate)