Milestone v1.0: FamilySync MVP #1

Merged
luckberg merged 376 commits from gsd/v1.0-milestone into main 2026-06-10 17:39:19 -04:00
2 changed files with 10 additions and 4 deletions
Showing only changes of commit d101aa899d - Show all commits
+5 -2
View File
@@ -79,8 +79,11 @@ const outboxPayloadSchema = z
calendarUrl: z.string().url().max(1024).optional(),
_preservedRrule: z.string().max(1024).optional(),
// D-06: recurrence bounding (RRULE UNTIL / COUNT)
// T-06-02: max(10) bounds 'YYYY-MM-DD'; int().min(1) prevents zero/negative counts
recurrenceUntil: z.string().max(10).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
// CR-01: defense-in-depth — validate the exact 'YYYY-MM-DD' shape here too (the route
// schema validates on ingress, but the outbox payload is re-parsed from stored JSON).
// Guarantees .replace(/-/g,'') in assembleRruleString emits digits-only, closing the
// RRULE-part injection vector. int().min(1) prevents zero/negative counts.
recurrenceUntil: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
recurrenceCount: z.number().int().min(1).optional(), // integer ≥ 1 → RRULE COUNT
})
.passthrough()
+5 -2
View File
@@ -107,8 +107,11 @@ const eventFieldsSchema = z.object({
recurrence: z.enum(['none', 'daily', 'weekly', 'monthly', 'yearly']).optional(),
calendarUrl: z.string().url().max(1024).optional(),
// D-06: recurrence bounding (RRULE UNTIL / COUNT)
// T-06-02: max(10) bounds 'YYYY-MM-DD'; int().min(1) prevents zero/negative counts
recurrenceUntil: z.string().max(10).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
// CR-01: validate the exact 'YYYY-MM-DD' shape (reusing eventsQuerySchema's regex) so a
// ≤10-char non-date string cannot survive .replace(/-/g,'') and inject extra ';'-delimited
// RRULE parts when spliced into the UNTIL template (outboxWorker.assembleRruleString).
// int().min(1) prevents zero/negative counts.
recurrenceUntil: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
recurrenceCount: z.number().int().min(1).optional(), // integer ≥ 1 → RRULE COUNT
})