From 484f747f66695531ecf65ce5305dc13799ae5fa7 Mon Sep 17 00:00:00 2001 From: ginnoir Date: Wed, 6 May 2026 21:12:26 -0500 Subject: [PATCH] Auto-enroll user into household if membership missing on session load If a user has a valid session but no household_members row (e.g. they first signed in before the household was seeded), getCurrentSession now auto-enrolls them instead of throwing. Assigns owner if first member, member otherwise, and creates their default calendars and lists. Removes the permanently-stuck state that occurred on first deploy. Co-Authored-By: Claude Sonnet 4.6 --- src/lib/session.ts | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/lib/session.ts b/src/lib/session.ts index 0cbb6ab..bebf3ab 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -2,6 +2,8 @@ import { eq } from "drizzle-orm"; import { auth } from "@/lib/auth"; import { db } from "@/lib/db"; import { householdMembers, households, users } from "@/modules/_core/schema"; +import { ensureDefaultCalendarsForMembership } from "@/modules/calendar/server/defaults"; +import { ensureDefaultListsForHousehold } from "@/modules/lists/server/defaults"; export interface CurrentSession { user: typeof users.$inferSelect; @@ -25,7 +27,36 @@ export async function getCurrentSession(): Promise { .where(eq(householdMembers.userId, session.user.id)) .limit(1); - if (!row) throw new Error("No household membership"); + if (row) return row; - return row; + // No membership yet — happens when the household was seeded after the user's + // first sign-in (e.g. first deploy). Auto-enroll into the single household. + const [household] = await db.select().from(households).limit(1); + if (!household) throw new Error("No household membership"); + + const [anyMember] = await db + .select() + .from(householdMembers) + .where(eq(householdMembers.householdId, household.id)) + .limit(1); + const role = anyMember ? "member" : "owner"; + + await db + .insert(householdMembers) + .values({ householdId: household.id, userId: session.user.id, role }) + .onConflictDoNothing(); + + await ensureDefaultCalendarsForMembership({ householdId: household.id, userId: session.user.id }); + await ensureDefaultListsForHousehold(household.id); + + const [fixed] = await db + .select({ user: users, household: households, role: householdMembers.role }) + .from(householdMembers) + .innerJoin(users, eq(householdMembers.userId, users.id)) + .innerJoin(households, eq(householdMembers.householdId, households.id)) + .where(eq(householdMembers.userId, session.user.id)) + .limit(1); + + if (!fixed) throw new Error("No household membership"); + return fixed; }