feat(11-03): reminderLeadMinutes schema + VALARM wiring in outbox worker (CAL-13/CAL-14)

- Add reminderLeadMinutes to eventFieldsSchema (ingress validation, T-11-06)
- Add reminderLeadMinutes to outboxPayloadSchema (drain re-validation, IN-03 defense-in-depth)
- Import extractValarms + computeAlertInstantUtc from vevent.ts
- UPDATE branch: hasExplicitReminder gate mirrors hasExplicitRecurrence (WR-01 pattern)
  - absent field → extractValarms(rawVevent) preserved verbatim (CAL-14, D-08)
  - explicit null → clear VALARM (no valarmsToPreserve, null passed to buildVeventString)
  - explicit value + allDay → computeAlertInstantUtc at 9 AM local (D-04)
  - explicit value + timed → passed through to buildTimedValarm via buildVeventString
- CREATE branch: always explicit picker value; compute allDayAlertInstantUtc when allDay
This commit is contained in:
Lucas Berger
2026-06-13 22:16:42 -04:00
parent 79f6871167
commit 4f42b7535b
2 changed files with 61 additions and 1 deletions
+6
View File
@@ -117,6 +117,12 @@ const eventFieldsSchema = z.object({
.regex(/^\d{4}-\d{2}-\d{2}$/)
.optional(), // 'YYYY-MM-DD' → RRULE UNTIL
recurrenceCount: z.number().int().min(1).optional(), // integer ≥ 1 → RRULE COUNT
// Phase 11: per-event reminder lead in minutes (CAL-13/CAL-14, D-08).
// absent — field not present; outbox worker preserves existing VALARM (no-change, D-08)
// null — explicit "None" → clear the VALARM on write-back
// 0 — same-day all-day reminder (9 AM on event date); timed 0 = None (D-06)
// positive int — N minutes before event start (timed) or N/1440 days before (all-day)
reminderLeadMinutes: z.number().int().min(0).nullable().optional(),
});
/** sync-status query params. */