export interface AccountAuthHandoffEffects { destroyEntitlementSubscription: () => void; resetEntitlementState: () => void; destroySubscriptionWatch: () => void; rebindConvexAuthForWatchHandoff: ( isCurrent: () => boolean, attachWatches: () => void, ) => Promise; initEntitlementSubscription: ( userId: string, isCurrent: () => boolean, ) => void | Promise; initSubscriptionWatch: ( userId: string, isCurrent: () => boolean, ) => void | Promise; cloudPrefsSignIn: (userId: string) => void | Promise; } /** * Reset user-scoped client state and start the authenticated watch handoff. * * The rebind effect is deliberately invoked before cloud preferences. Its * production implementation invalidates the old Clerk token synchronously * before its first await, after which Convex and cloud prefs may safely share * the new account's in-flight token fetch. */ export function startAccountAuthHandoff(input: { userId: string; isCurrent: () => boolean; effects: AccountAuthHandoffEffects; }): Promise { const { userId, isCurrent, effects } = input; effects.destroyEntitlementSubscription(); effects.resetEntitlementState(); effects.destroySubscriptionWatch(); const handoff = effects.rebindConvexAuthForWatchHandoff( isCurrent, () => { void effects.initEntitlementSubscription(userId, isCurrent); void effects.initSubscriptionWatch(userId, isCurrent); }, ); void effects.cloudPrefsSignIn(userId); return handoff; }