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
Showing only changes of commit 00a0454514 - Show all commits
+11
View File
@@ -126,6 +126,10 @@ const syncStatusQuerySchema = z.object({
// Response shape: { occurrences: CalendarOccurrence[] } // Response shape: { occurrences: CalendarOccurrence[] }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
eventsRouter.get('/', zValidator('query', eventsQuerySchema), async (c) => { eventsRouter.get('/', zValidator('query', eventsQuerySchema), async (c) => {
// Resolve the current user first — only return events for owned + shared calendars (T-03-06).
const currentUserId = await resolveUserId(c)
if (currentUserId === null) return c.json({ error: 'Unauthorized' }, 401)
const { start, end } = c.req.valid('query') const { start, end } = c.req.valid('query')
// --- Window span guard (T-02b-02) --- // --- Window span guard (T-02b-02) ---
@@ -163,6 +167,12 @@ eventsRouter.get('/', zValidator('query', eventsQuerySchema), async (c) => {
.innerJoin(calendars, eq(calendarEvents.calendarId, calendars.id)) .innerJoin(calendars, eq(calendarEvents.calendarId, calendars.id))
.innerJoin(users, eq(calendars.userId, users.id)) .innerJoin(users, eq(calendars.userId, users.id))
.where( .where(
and(
// Ownership predicate (BUG 3 fix): restrict to calendars owned by the current user
// OR shared-family calendars (isShared=true). Mirrors the /writable-calendars idiom
// (~line 509) so both endpoints agree on the authoritative writable set (D-03).
or(eq(calendars.userId, currentUserId), eq(calendars.isShared, true)),
// Date-window pre-filter (RESEARCH.md §Open Questions 3 / Pitfall 5):
or( or(
// Recurring masters: may have occurrences inside the window even if dtstartUtc is old. // Recurring masters: may have occurrences inside the window even if dtstartUtc is old.
// Two sub-cases: // Two sub-cases:
@@ -190,6 +200,7 @@ eventsRouter.get('/', zValidator('query', eventsQuerySchema), async (c) => {
sql`${calendarEvents.dtstartDate} < ${end}`, sql`${calendarEvents.dtstartDate} < ${end}`,
), ),
), ),
),
) )
// --- Expand each row into concrete occurrences --- // --- Expand each row into concrete occurrences ---