import { getSupabaseAdminClient } from "@/lib/supabase/admin"; import { ABSOLUTE_SESSION_CAP_SECONDS } from "@/lib/auth/jwt"; export async function createSession(userId: string): Promise<{ id: string; iat_original: number }> { const admin = getSupabaseAdminClient(); const { data, error } = await admin .from("user_sessions") .insert({ user_id: userId }) .select("id, iat_original") .single(); if (error || !data) throw new Error("Failed to create session"); return { id: data.id, iat_original: Math.floor(new Date(data.iat_original).getTime() / 1000), }; } /** * Returns true iff the session row exists, is not revoked, and the * absolute-cap (30 days from `iat_original`) has not elapsed. * * Side-effect (fire-and-forget): updates `last_seen_at`. */ export async function isSessionLive(sessionId: string, iatOriginal: number): Promise { const admin = getSupabaseAdminClient(); const { data } = await admin .from("user_sessions") .select("revoked_at") .eq("id", sessionId) .maybeSingle(); if (!data || data.revoked_at) return false; if (Math.floor(Date.now() / 1000) - iatOriginal > ABSOLUTE_SESSION_CAP_SECONDS) { return false; } void admin .from("user_sessions") .update({ last_seen_at: new Date().toISOString() }) .eq("id", sessionId); return true; } export async function revokeSession(sessionId: string): Promise { const admin = getSupabaseAdminClient(); await admin .from("user_sessions") .update({ revoked_at: new Date().toISOString() }) .eq("id", sessionId); }