From fa93e779f214eaf6a4a6c54d5d106ac650290c69 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Thu, 11 Jun 2026 22:45:07 -0500 Subject: [PATCH 1/7] feat(admin): MAU dashboard + metrics audit + dashboard improvements - Fix broken userActivities signal: switch active-user count to sessions.lastUsedAt and all trend/heatmap queries to activityLogs - Add /growth page: MAU/WAU/DAU stickiness, 12-month trend, tier pie, daily activity bar chart, MoM growth card - Add getGrowthMetrics() query (MAU/WAU/DAU from sessions, trends from activityLogs, signups from users.createdAt) - Users page: last-active column from sessions + dormant filter toggle - Unit Economics: add margin-by-tier table; wire getMarginByTier() - Support: link submissions to registered user accounts by email match, add open/closed status toggle (resolvedAt column + PATCH endpoint) - AI Billing: add margin trend line chart (real cost vs charged per day) - Nav: fetch /api/admin/alerts on mount; show red dot on Monitoring tab when error rate > 5%, on AI Billing/Unit Economics when negative-margin accounts exist or live holds > 50 Co-Authored-By: Claude Sonnet 4.6 --- .../admin/src/app/(admin)/ai-billing/page.tsx | 47 +++ apps/admin/src/app/(admin)/dashboard/page.tsx | 8 +- apps/admin/src/app/(admin)/growth/page.tsx | 381 ++++++++++++++++++ apps/admin/src/app/(admin)/support/page.tsx | 25 +- .../src/app/(admin)/unit-economics/page.tsx | 42 ++ apps/admin/src/app/(admin)/users/page.tsx | 32 +- apps/admin/src/app/AdminLayoutClient.tsx | 44 +- .../src/app/api/admin/ai-billing/route.ts | 4 + apps/admin/src/app/api/admin/alerts/route.ts | 31 ++ .../src/app/api/admin/contact/[id]/route.ts | 27 ++ apps/admin/src/app/api/admin/contact/route.ts | 56 ++- .../src/app/api/admin/unit-economics/route.ts | 6 +- apps/admin/src/app/api/admin/users/route.ts | 20 +- .../src/app/api/monitoring/[metric]/route.ts | 7 +- .../admin/ContactSubmissionsTable.tsx | 151 ++++++- .../admin/src/components/admin/UsersTable.tsx | 63 ++- apps/admin/src/lib/monitoring-queries.ts | 280 +++++++++++-- apps/admin/src/lib/monitoring-types.ts | 18 + .../db/drizzle/0161_contact_resolved_at.sql | 1 + packages/db/drizzle/meta/_journal.json | 7 + packages/db/src/schema/contact.ts | 1 + 21 files changed, 1163 insertions(+), 88 deletions(-) create mode 100644 apps/admin/src/app/(admin)/growth/page.tsx create mode 100644 apps/admin/src/app/api/admin/alerts/route.ts create mode 100644 apps/admin/src/app/api/admin/contact/[id]/route.ts create mode 100644 packages/db/drizzle/0161_contact_resolved_at.sql diff --git a/apps/admin/src/app/(admin)/ai-billing/page.tsx b/apps/admin/src/app/(admin)/ai-billing/page.tsx index 25609639dc..b23aa9ad11 100644 --- a/apps/admin/src/app/(admin)/ai-billing/page.tsx +++ b/apps/admin/src/app/(admin)/ai-billing/page.tsx @@ -17,6 +17,16 @@ import { TableRow, } from "@/components/ui/table"; import { AlertCircle, Download, Receipt, ShieldAlert, ShieldCheck } from "lucide-react"; +import { + LineChart, + Line, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, +} from "recharts"; import { fetchWithAuth } from "@/lib/auth/auth-fetch"; type Range = "24h" | "7d" | "30d" | "all"; @@ -61,6 +71,14 @@ interface Enforcement { tierAllowanceCents: Record; } +interface MarginPeriodRow { + period: string; + realCostCents: number; + chargedCents: number; + marginCents: number; + marginPct: number | null; +} + interface AiBillingResponse { range: Range; granularity: Granularity; enforcement: Enforcement; tokens: { summary: TokenTotals; byModel: TokenModelRow[]; byPeriod: TokenPeriodRow[]; byUser: TokenUserRow[]; }; @@ -69,6 +87,7 @@ interface AiBillingResponse { liability: { monthlyRemainingCents: number; topupRemainingCents: number; totalLiabilityCents: number; userCount: number; }; holds: { holdCount: number; heldCents: number; }; alerts: { balanceDrift: BalanceDriftRow[]; negativeMargin: NegativeMarginRow[]; }; + marginByPeriod: MarginPeriodRow[]; } const TIERS: Tier[] = ["free", "pro", "founder", "business"]; @@ -271,6 +290,34 @@ export default function AdminAiBillingPage() { Live holds{usd(holds.heldCents)}({num(holds.holdCount)}) + {data.marginByPeriod.length > 1 && ( + + + Margin trend + Real provider cost vs charged credits per {granularity === "month" ? "month" : "day"} — gap is your gross margin. + + + + ({ + period: String(r.period).slice(0, granularity === "month" ? 7 : 10), + realCost: +(r.realCostCents / 100).toFixed(2), + charged: +(r.chargedCents / 100).toFixed(2), + margin: +(r.marginCents / 100).toFixed(2), + }))} margin={{ top: 4, right: 16, left: 0, bottom: 4 }}> + + + `$${v}`} tick={{ fontSize: 11 }} /> + [`$${v.toFixed(2)}`]} /> + + + + + + + + + )} + Provider cost diff --git a/apps/admin/src/app/(admin)/dashboard/page.tsx b/apps/admin/src/app/(admin)/dashboard/page.tsx index 025ff17c10..4caa2807ad 100644 --- a/apps/admin/src/app/(admin)/dashboard/page.tsx +++ b/apps/admin/src/app/(admin)/dashboard/page.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { Activity, Database, MessageSquare, Users, Headphones } from "lucide-react"; +import { Activity, Database, MessageSquare, Users, Headphones, TrendingUp } from "lucide-react"; interface AdminSection { title: string; @@ -12,6 +12,12 @@ interface AdminSection { } const adminSections: AdminSection[] = [ + { + title: "Growth", + description: "MAU, signups, retention, and tier breakdown", + icon: TrendingUp, + href: "/growth", + }, { title: "Monitoring", description: "System monitoring dashboard", diff --git a/apps/admin/src/app/(admin)/growth/page.tsx b/apps/admin/src/app/(admin)/growth/page.tsx new file mode 100644 index 0000000000..a77d991467 --- /dev/null +++ b/apps/admin/src/app/(admin)/growth/page.tsx @@ -0,0 +1,381 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { + AreaChart, + Area, + BarChart, + Bar, + PieChart, + Pie, + Cell, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, +} from "recharts"; +import { format, parseISO } from "date-fns"; +import { RefreshCw, Users, TrendingUp, Activity, CreditCard } from "lucide-react"; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { Skeleton } from "@/components/ui/skeleton"; +import { fetchWithAuth } from "@/lib/auth/auth-fetch"; +import type { GrowthMetricsData } from "@/lib/monitoring"; + +const TIER_COLORS: Record = { + free: "#94a3b8", + pro: "#3b82f6", + founder: "#8b5cf6", + business: "#10b981", +}; + +const TIER_LABELS: Record = { + free: "Free", + pro: "Pro", + founder: "Founder", + business: "Business", +}; + +function StatCard({ + title, + value, + sub, + icon: Icon, + badge, + isLoading, +}: { + title: string; + value: string | number; + sub?: string; + icon: typeof Users; + badge?: { label: string; variant: "default" | "secondary" | "destructive" | "outline" }; + isLoading: boolean; +}) { + return ( + + + {title} + + + + {isLoading ? ( + + ) : ( + <> +
{value}
+
+ {sub &&

{sub}

} + {badge && {badge.label}} +
+ + )} +
+
+ ); +} + +function fmtMonth(isoDate: string) { + try { return format(parseISO(isoDate), "MMM yy"); } catch { return isoDate; } +} + +function fmtDay(isoDate: string) { + try { return format(parseISO(isoDate), "MMM d"); } catch { return isoDate; } +} + +function fmtPct(n: number | null) { + if (n === null) return "—"; + const sign = n >= 0 ? "+" : ""; + return `${sign}${n.toFixed(1)}%`; +} + +export default function GrowthPage() { + const [data, setData] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const fetchData = useCallback(async () => { + setIsLoading(true); + try { + const res = await fetchWithAuth("/api/monitoring/growth"); + const json = await res.json(); + setData(json.data); + } catch { + // keep stale data visible + } finally { + setIsLoading(false); + } + }, []); + + useEffect(() => { fetchData(); }, [fetchData]); + + const s = data?.summary; + + const momBadge = s?.momGrowthPct !== undefined && s.momGrowthPct !== null + ? { + label: fmtPct(s.momGrowthPct), + variant: (s.momGrowthPct >= 0 ? "default" : "destructive") as "default" | "destructive", + } + : undefined; + + const mauTrendData = (data?.mauTrend ?? []).map(r => ({ + ...r, + label: fmtMonth(r.period), + })); + + const dauTrendData = (data?.dauTrend ?? []).map(r => ({ + ...r, + label: fmtDay(r.day), + })); + + const tierData = data?.tierBreakdown ?? []; + + return ( +
+
+
+

Growth

+

MAU, signups, engagement, and tier breakdown

+
+ +
+ + {/* Hero stats */} +
+ + + + +
+ + {/* Secondary stats */} +
+ + + +
+ + {/* Charts row */} +
+ {/* MAU Trend — takes 2 cols */} + + + MAU Trend + Monthly active users vs new signups — last 12 months + + + {isLoading ? ( + + ) : mauTrendData.length === 0 ? ( +
+ No activity data yet +
+ ) : ( + + + + + + + + + + + + + + + + + + + + + + )} +
+
+ + {/* Tier Breakdown */} + + + Tier Breakdown + All users by subscription tier + + + {isLoading ? ( + + ) : tierData.length === 0 ? ( +
No data
+ ) : ( +
+ + + + {tierData.map((entry) => ( + + ))} + + [value.toLocaleString(), TIER_LABELS[name] ?? name]} + /> + + +
+ {tierData.map((t) => ( +
+
+
+ {TIER_LABELS[t.tier] ?? t.tier} +
+
+ {t.count.toLocaleString()} + {t.pct.toFixed(1)}% +
+
+ ))} +
+
+ )} + + +
+ + {/* DAU trend */} + + + Daily Activity (Last 30 Days) + Daily active users vs new signups + + + {isLoading ? ( + + ) : dauTrendData.length === 0 ? ( +
+ No activity data yet +
+ ) : ( + + + + + + + + + + + + )} +
+
+ + {/* MAU table */} + {mauTrendData.length > 0 && ( + + + Monthly Summary + Active users and new signups per month + + +
+ + + + + + + + + + + {[...mauTrendData].reverse().map((row, i, arr) => { + const prev = arr[i + 1]; + const mauGrowth = prev && prev.mau > 0 + ? ((row.mau - prev.mau) / prev.mau) * 100 + : null; + return ( + + + + + + + ); + })} + +
MonthMAUNew SignupsMAU Growth
{row.label}{row.mau.toLocaleString()}{row.newUsers.toLocaleString()} + {mauGrowth !== null ? ( + = 0 ? "text-emerald-500" : "text-red-500"}> + {fmtPct(mauGrowth)} + + ) : "—"} +
+
+
+
+ )} +
+ ); +} diff --git a/apps/admin/src/app/(admin)/support/page.tsx b/apps/admin/src/app/(admin)/support/page.tsx index fb52e30c03..1cf02e3f0f 100644 --- a/apps/admin/src/app/(admin)/support/page.tsx +++ b/apps/admin/src/app/(admin)/support/page.tsx @@ -7,6 +7,11 @@ import { Alert, AlertDescription } from "@/components/ui/alert"; import { MessageSquare, AlertCircle, Mail, Calendar, TrendingUp, Users } from "lucide-react"; import { fetchWithAuth } from "@/lib/auth/auth-fetch"; +interface RegisteredUser { + id: string; + subscriptionTier: string | null; +} + interface ContactSubmission { id: string; name: string; @@ -14,6 +19,8 @@ interface ContactSubmission { subject: string; message: string; createdAt: string; + resolvedAt: string | null; + registeredUser: RegisteredUser | null; } interface PaginationData { @@ -39,6 +46,7 @@ interface ApiResponse { searchTerm: string; sortBy: string; sortOrder: string; + statusFilter: string; }; } @@ -58,6 +66,7 @@ export default function AdminSupportPage() { const [searchTerm, setSearchTerm] = useState(""); const [sortBy, setSortBy] = useState("createdAt"); const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); + const [statusFilter, setStatusFilter] = useState<"all" | "open" | "closed">("all"); const fetchSubmissions = useCallback(async () => { setLoading(true); @@ -68,6 +77,7 @@ export default function AdminSupportPage() { search: searchTerm, sortBy, sortOrder, + status: statusFilter, page: pagination.page.toString(), pageSize: pagination.pageSize.toString() }); @@ -87,7 +97,7 @@ export default function AdminSupportPage() { } finally { setLoading(false); } - }, [searchTerm, sortBy, sortOrder, pagination.page, pagination.pageSize]); + }, [searchTerm, sortBy, sortOrder, statusFilter, pagination.page, pagination.pageSize]); useEffect(() => { fetchSubmissions(); @@ -95,7 +105,7 @@ export default function AdminSupportPage() { const handleSearch = (newSearchTerm: string) => { setSearchTerm(newSearchTerm); - setPagination(prev => ({ ...prev, page: 1 })); // Reset to first page on search + setPagination(prev => ({ ...prev, page: 1 })); }; const handlePageChange = (newPage: number) => { @@ -105,7 +115,12 @@ export default function AdminSupportPage() { const handleSort = (newSortBy: string, newSortOrder: "asc" | "desc") => { setSortBy(newSortBy); setSortOrder(newSortOrder); - setPagination(prev => ({ ...prev, page: 1 })); // Reset to first page on sort + setPagination(prev => ({ ...prev, page: 1 })); + }; + + const handleStatusFilter = (status: "all" | "open" | "closed") => { + setStatusFilter(status); + setPagination(prev => ({ ...prev, page: 1 })); }; const { todayCount: todaySubmissions, weekCount: weekSubmissions, uniqueEmailCount: uniqueEmails } = stats; @@ -174,6 +189,8 @@ export default function AdminSupportPage() { onSearch={handleSearch} onPageChange={handlePageChange} onSort={handleSort} + onStatusFilter={handleStatusFilter} + statusFilter={statusFilter} isLoading={loading} /> @@ -190,4 +207,4 @@ export default function AdminSupportPage() { )}
); -} \ No newline at end of file +} diff --git a/apps/admin/src/app/(admin)/unit-economics/page.tsx b/apps/admin/src/app/(admin)/unit-economics/page.tsx index fefeadaff5..7298dbdb4e 100644 --- a/apps/admin/src/app/(admin)/unit-economics/page.tsx +++ b/apps/admin/src/app/(admin)/unit-economics/page.tsx @@ -71,12 +71,22 @@ interface DebtRow { debtCents: number; } +interface TierRow { + tier: string; + realCostCents: number; + chargedCents: number; + requestCount: number; + marginCents: number; + marginPct: number | null; +} + interface UnitEconomicsResponse { range: Range; granularity: Granularity; summary: Summary; byPeriod: PeriodRow[]; byModel: ModelRow[]; + byTier: TierRow[]; topSpenders: SpenderRow[]; debtByUser: DebtRow[]; } @@ -278,6 +288,38 @@ export default function AdminUnitEconomicsPage() {
+ + Margin by tierCost and margin breakdown across subscription tiers. + + {data.byTier.length === 0 ? ( +

No billed AI usage in this range.

+ ) : ( + + + + Tier + Real costCharged + MarginMargin % + Requests + + + + {data.byTier.map((row) => ( + + {row.tier} + {usd(row.realCostCents)} + {usd(row.chargedCents)} + {usd(row.marginCents)} + {pct(row.marginPct)} + {row.requestCount.toLocaleString()} + + ))} + +
+ )} +
+
+ Outstanding debtUncovered AI cost we couldn't collect, by user. diff --git a/apps/admin/src/app/(admin)/users/page.tsx b/apps/admin/src/app/(admin)/users/page.tsx index 65890c3f6e..41f14122d6 100644 --- a/apps/admin/src/app/(admin)/users/page.tsx +++ b/apps/admin/src/app/(admin)/users/page.tsx @@ -5,7 +5,7 @@ import { UsersTable } from "@/components/admin/UsersTable"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import { Alert, AlertDescription } from "@/components/ui/alert"; -import { Users, AlertCircle, Shield, MessageCircle, Database, UserPlus } from "lucide-react"; +import { Users, AlertCircle, Shield, MessageCircle, Database, UserPlus, Clock } from "lucide-react"; import { fetchWithAuth } from "@/lib/auth/auth-fetch"; import { CreateUserForm } from "@/components/admin/CreateUserForm"; import { isOnPrem } from "@/lib/deployment-mode"; @@ -32,6 +32,7 @@ interface UserData { tokenVersion: number; subscriptionTier: 'free' | 'pro' | 'founder' | 'business'; stripeCustomerId: string | null; + lastActiveAt: string | null; stats: { drives: number; pages: number; @@ -135,14 +136,20 @@ export default function AdminUsersPage() { ); } + const DORMANT_DAYS = 30; const totalStats = users.reduce( - (acc, user) => ({ - totalDrives: acc.totalDrives + user.stats.drives, - totalPages: acc.totalPages + user.stats.pages, - totalMessages: acc.totalMessages + user.stats.totalMessages, - verifiedUsers: acc.verifiedUsers + (user.emailVerified ? 1 : 0), - }), - { totalDrives: 0, totalPages: 0, totalMessages: 0, verifiedUsers: 0 } + (acc, user) => { + const dormant = !user.lastActiveAt || + (Date.now() - new Date(user.lastActiveAt).getTime()) / (1000 * 60 * 60 * 24) > DORMANT_DAYS; + return { + totalDrives: acc.totalDrives + user.stats.drives, + totalPages: acc.totalPages + user.stats.pages, + totalMessages: acc.totalMessages + user.stats.totalMessages, + verifiedUsers: acc.verifiedUsers + (user.emailVerified ? 1 : 0), + dormantUsers: acc.dormantUsers + (dormant ? 1 : 0), + }; + }, + { totalDrives: 0, totalPages: 0, totalMessages: 0, verifiedUsers: 0, dormantUsers: 0 } ); return ( @@ -159,7 +166,7 @@ export default function AdminUsersPage() { -
+
{users.length}
@@ -188,6 +195,13 @@ export default function AdminUsersPage() { Total Messages
+
+
{totalStats.dormantUsers}
+
+ + Dormant (30d+) +
+
diff --git a/apps/admin/src/app/AdminLayoutClient.tsx b/apps/admin/src/app/AdminLayoutClient.tsx index b226369b50..e04f9671c5 100644 --- a/apps/admin/src/app/AdminLayoutClient.tsx +++ b/apps/admin/src/app/AdminLayoutClient.tsx @@ -1,9 +1,23 @@ "use client"; +import { useEffect, useState } from "react"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import Link from "next/link"; import { usePathname } from "next/navigation"; +import { fetchWithAuth } from "@/lib/auth/auth-fetch"; + +interface AlertState { + errorRateAlert: boolean; + negativeMarginAlert: boolean; + liveHoldsAlert: boolean; +} + +function AlertDot() { + return ( + + ); +} export default function AdminLayoutClient({ children, @@ -12,6 +26,7 @@ export default function AdminLayoutClient({ }) { const pathname = usePathname(); const currentTab = pathname === '/' || pathname === '/dashboard' ? 'overview' : + pathname.includes('/growth') ? 'growth' : pathname.includes('/monitoring') ? 'monitoring' : pathname.includes('/tables') ? 'tables' : pathname.includes('/global-prompt') ? 'global-prompt' : @@ -20,6 +35,18 @@ export default function AdminLayoutClient({ pathname.includes('/audit-logs') ? 'audit-logs' : pathname.includes('/support') ? 'support' : 'users'; + const [alerts, setAlerts] = useState(null); + + useEffect(() => { + fetchWithAuth('/api/admin/alerts') + .then((r) => r.ok ? r.json() : null) + .then((d) => d && setAlerts(d)) + .catch(() => null); + }, []); + + const monitoringAlert = alerts?.errorRateAlert; + const billingAlert = alerts?.negativeMarginAlert || alerts?.liveHoldsAlert; + return (
@@ -37,8 +64,13 @@ export default function AdminLayoutClient({ Overview + + Growth + - Monitoring + + Monitoring{monitoringAlert && } + Database Tables @@ -47,10 +79,14 @@ export default function AdminLayoutClient({ Global Prompt - Unit Economics + + Unit Economics{billingAlert && } + - AI Billing + + AI Billing{billingAlert && } + User Management @@ -70,4 +106,4 @@ export default function AdminLayoutClient({
); -} \ No newline at end of file +} diff --git a/apps/admin/src/app/api/admin/ai-billing/route.ts b/apps/admin/src/app/api/admin/ai-billing/route.ts index 23ceef0527..6492598c1c 100644 --- a/apps/admin/src/app/api/admin/ai-billing/route.ts +++ b/apps/admin/src/app/api/admin/ai-billing/route.ts @@ -13,6 +13,7 @@ import { getLiveHolds, getBalanceDriftAlerts, getNegativeMarginAccounts, + getMarginByPeriod, type Granularity, } from '@/lib/monitoring'; import { @@ -70,6 +71,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { holds, balanceDrift, negativeMargin, + marginByPeriod, ] = await Promise.all([ getTokenUsageSummary(startDate, endDate), getTokenUsageByModel(startDate, endDate, 50), @@ -82,6 +84,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { getLiveHolds(), getBalanceDriftAlerts(), getNegativeMarginAccounts(startDate, endDate), + getMarginByPeriod(startDate, endDate, granularity), ]); const enforcement = { @@ -153,6 +156,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { liability, holds, alerts: { balanceDrift, negativeMargin }, + marginByPeriod, }); } catch (error) { loggers.api.error('Error fetching ai-billing data:', error as Error); diff --git a/apps/admin/src/app/api/admin/alerts/route.ts b/apps/admin/src/app/api/admin/alerts/route.ts new file mode 100644 index 0000000000..258a649cd2 --- /dev/null +++ b/apps/admin/src/app/api/admin/alerts/route.ts @@ -0,0 +1,31 @@ +import { NextResponse } from 'next/server'; +import { withAdminAuth } from '@/lib/auth'; +import { getSystemHealth, getNegativeMarginAccounts, getLiveHolds } from '@/lib/monitoring'; +import { loggers } from '@pagespace/lib/logging/logger-config'; + +// Lightweight alert-state endpoint for nav badges. Cached 60s. +export const GET = withAdminAuth(async () => { + try { + const since24h = new Date(Date.now() - 24 * 60 * 60 * 1000); + const [health, negativeMargin, holds] = await Promise.all([ + getSystemHealth(since24h), + getNegativeMarginAccounts(since24h), + getLiveHolds(), + ]); + + return NextResponse.json( + { + errorRateAlert: health.errorRate !== null && health.errorRate > 5, + negativeMarginAlert: negativeMargin.length > 0, + liveHoldsAlert: holds.holdCount > 50, + errorRate: health.errorRate, + negativeMarginCount: negativeMargin.length, + liveHoldsCount: holds.holdCount, + }, + { headers: { 'Cache-Control': 's-maxage=60, stale-while-revalidate=30' } } + ); + } catch (error) { + loggers.api.error('Error fetching admin alerts:', error as Error); + return NextResponse.json({ error: 'Failed to fetch alerts' }, { status: 500 }); + } +}); diff --git a/apps/admin/src/app/api/admin/contact/[id]/route.ts b/apps/admin/src/app/api/admin/contact/[id]/route.ts new file mode 100644 index 0000000000..ed81445cf8 --- /dev/null +++ b/apps/admin/src/app/api/admin/contact/[id]/route.ts @@ -0,0 +1,27 @@ +import { db } from '@pagespace/db/db' +import { eq } from '@pagespace/db/operators' +import { contactSubmissions } from '@pagespace/db/schema/contact'; +import { loggers } from '@pagespace/lib/logging/logger-config'; +import { withAdminAuth } from '@/lib/auth'; + +export const PATCH = withAdminAuth(async (_adminUser, request, context) => { + try { + const { id } = await (context as { params: Promise<{ id: string }> }).params; + const body = await request.json() as { resolved: boolean }; + + const [updated] = await db + .update(contactSubmissions) + .set({ resolvedAt: body.resolved ? new Date() : null }) + .where(eq(contactSubmissions.id, id)) + .returning({ id: contactSubmissions.id, resolvedAt: contactSubmissions.resolvedAt }); + + if (!updated) { + return Response.json({ error: 'Submission not found' }, { status: 404 }); + } + + return Response.json({ id: updated.id, resolvedAt: updated.resolvedAt }); + } catch (error) { + loggers.api.error('Error updating contact submission:', error as Error); + return Response.json({ error: 'Failed to update submission' }, { status: 500 }); + } +}); diff --git a/apps/admin/src/app/api/admin/contact/route.ts b/apps/admin/src/app/api/admin/contact/route.ts index 600676a100..93b9c54d35 100644 --- a/apps/admin/src/app/api/admin/contact/route.ts +++ b/apps/admin/src/app/api/admin/contact/route.ts @@ -1,6 +1,7 @@ import { db } from '@pagespace/db/db' -import { asc, desc, ilike, or, and, count, gte, sql } from '@pagespace/db/operators' +import { asc, desc, ilike, or, and, count, gte, sql, eq, isNull, isNotNull } from '@pagespace/db/operators' import { contactSubmissions } from '@pagespace/db/schema/contact'; +import { users } from '@pagespace/db/schema/users'; import { loggers } from '@pagespace/lib/logging/logger-config'; import { withAdminAuth } from '@/lib/auth'; import { parseBoundedIntParam } from '@/lib/utils/query-params'; @@ -13,6 +14,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { const searchTerm = url.searchParams.get('search') || ''; const sortBy = url.searchParams.get('sortBy') || 'createdAt'; const sortOrder = url.searchParams.get('sortOrder') || 'desc'; + const statusFilter = url.searchParams.get('status') || 'all'; // 'open' | 'closed' | 'all' const page = parseBoundedIntParam(url.searchParams.get('page'), { defaultValue: 1, min: 1, @@ -25,7 +27,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { }); const offset = (page - 1) * pageSize; - // Build where conditions for search + // Build where conditions const searchConditions = searchTerm ? or( ilike(contactSubmissions.name, `%${searchTerm}%`), @@ -35,6 +37,18 @@ export const GET = withAdminAuth(async (_adminUser, request) => { ) : undefined; + const statusCondition = + statusFilter === 'open' + ? isNull(contactSubmissions.resolvedAt) + : statusFilter === 'closed' + ? isNotNull(contactSubmissions.resolvedAt) + : undefined; + + const allConditions = [searchConditions, statusCondition].filter(Boolean); + const whereClause = allConditions.length > 1 + ? and(...allConditions as Parameters) + : allConditions[0]; + // Date boundaries for stats const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); @@ -42,19 +56,19 @@ export const GET = withAdminAuth(async (_adminUser, request) => { weekAgo.setDate(weekAgo.getDate() - 7); weekAgo.setHours(0, 0, 0, 0); - const todayCondition = searchConditions - ? and(searchConditions, gte(contactSubmissions.createdAt, todayStart)) + const todayCondition = whereClause + ? and(whereClause, gte(contactSubmissions.createdAt, todayStart)) : gte(contactSubmissions.createdAt, todayStart); - const weekCondition = searchConditions - ? and(searchConditions, gte(contactSubmissions.createdAt, weekAgo)) + const weekCondition = whereClause + ? and(whereClause, gte(contactSubmissions.createdAt, weekAgo)) : gte(contactSubmissions.createdAt, weekAgo); // Get total + stats counts in parallel const [totalCountResult, todayCountResult, weekCountResult, uniqueEmailResult] = await Promise.all([ - db.select({ count: count() }).from(contactSubmissions).where(searchConditions), + db.select({ count: count() }).from(contactSubmissions).where(whereClause), db.select({ count: count() }).from(contactSubmissions).where(todayCondition), db.select({ count: count() }).from(contactSubmissions).where(weekCondition), - db.select({ count: sql`COUNT(DISTINCT ${contactSubmissions.email})` }).from(contactSubmissions).where(searchConditions), + db.select({ count: sql`COUNT(DISTINCT ${contactSubmissions.email})` }).from(contactSubmissions).where(whereClause), ]); // Build sort condition @@ -70,8 +84,8 @@ export const GET = withAdminAuth(async (_adminUser, request) => { const sortColumn = validSortColumns[sortBy as keyof typeof validSortColumns] || contactSubmissions.createdAt; const orderBy = sortOrder === 'asc' ? asc(sortColumn) : desc(sortColumn); - // Get submissions with pagination - const submissions = await db + // Get submissions with pagination, left-joining users by email + const rows = await db .select({ id: contactSubmissions.id, name: contactSubmissions.name, @@ -79,13 +93,30 @@ export const GET = withAdminAuth(async (_adminUser, request) => { subject: contactSubmissions.subject, message: contactSubmissions.message, createdAt: contactSubmissions.createdAt, + resolvedAt: contactSubmissions.resolvedAt, + userId: users.id, + userSubscriptionTier: users.subscriptionTier, }) .from(contactSubmissions) - .where(searchConditions) + .leftJoin(users, eq(users.email, contactSubmissions.email)) + .where(whereClause) .orderBy(orderBy) .limit(pageSize) .offset(offset); + const submissions = rows.map((r) => ({ + id: r.id, + name: r.name, + email: r.email, + subject: r.subject, + message: r.message, + createdAt: r.createdAt, + resolvedAt: r.resolvedAt, + registeredUser: r.userId + ? { id: r.userId, subscriptionTier: r.userSubscriptionTier } + : null, + })); + // Calculate pagination info const total = totalCountResult[0]?.count || 0; const todayCount = todayCountResult[0]?.count || 0; @@ -113,7 +144,8 @@ export const GET = withAdminAuth(async (_adminUser, request) => { meta: { searchTerm, sortBy, - sortOrder + sortOrder, + statusFilter, } }); diff --git a/apps/admin/src/app/api/admin/unit-economics/route.ts b/apps/admin/src/app/api/admin/unit-economics/route.ts index 87455952c1..490b3e0c05 100644 --- a/apps/admin/src/app/api/admin/unit-economics/route.ts +++ b/apps/admin/src/app/api/admin/unit-economics/route.ts @@ -5,6 +5,7 @@ import { getUnitEconomicsSummary, getMarginByPeriod, getMarginByModel, + getMarginByTier, getTopSpendersByMargin, getOutstandingDebtByUser, type Granularity, @@ -48,10 +49,11 @@ export const GET = withAdminAuth(async (_adminUser, request) => { const { startDate, endDate } = getDateRange(range); - const [summary, byPeriod, byModel, topSpenders, debtByUser] = await Promise.all([ + const [summary, byPeriod, byModel, byTier, topSpenders, debtByUser] = await Promise.all([ getUnitEconomicsSummary(startDate, endDate), getMarginByPeriod(startDate, endDate, granularity), getMarginByModel(startDate, endDate), + getMarginByTier(startDate, endDate), getTopSpendersByMargin(startDate, endDate, 10), getOutstandingDebtByUser(10), ]); @@ -87,7 +89,7 @@ export const GET = withAdminAuth(async (_adminUser, request) => { }); } - return NextResponse.json({ range, granularity, startDate, endDate, summary, byPeriod, byModel, topSpenders, debtByUser }); + return NextResponse.json({ range, granularity, startDate, endDate, summary, byPeriod, byModel, byTier, topSpenders, debtByUser }); } catch (error) { loggers.api.error('Error fetching unit-economics data:', error as Error); return NextResponse.json({ error: 'Failed to fetch unit-economics data' }, { status: 500 }); diff --git a/apps/admin/src/app/api/admin/users/route.ts b/apps/admin/src/app/api/admin/users/route.ts index 7d9cc12fd5..9af8c1a305 100644 --- a/apps/admin/src/app/api/admin/users/route.ts +++ b/apps/admin/src/app/api/admin/users/route.ts @@ -1,9 +1,10 @@ import { db } from '@pagespace/db/db' -import { and, eq, inArray, desc, count } from '@pagespace/db/operators' +import { and, eq, inArray, desc, count, sql, isNull } from '@pagespace/db/operators' import { users } from '@pagespace/db/schema/auth' import { drives, pages, chatMessages } from '@pagespace/db/schema/core' import { messages } from '@pagespace/db/schema/conversations' import { subscriptions } from '@pagespace/db/schema/subscriptions' +import { sessions } from '@pagespace/db/schema/sessions' import { stripe } from '@/lib/stripe'; import { loggers } from '@pagespace/lib/logging/logger-config'; import { auditRequest } from '@pagespace/lib/audit/audit-log'; @@ -51,7 +52,7 @@ export const GET = withAdminAuth(async (_adminUser, _request) => { ); // Batch aggregate stats instead of per-user N+1 queries - const [driveCounts, pageCounts, chatMessageCounts, globalMessageCounts] = await Promise.all([ + const [driveCounts, pageCounts, chatMessageCounts, globalMessageCounts, lastActiveDates] = await Promise.all([ db.select({ userId: drives.ownerId, count: count(), @@ -81,6 +82,14 @@ export const GET = withAdminAuth(async (_adminUser, _request) => { .from(messages) .where(inArray(messages.userId, userIds)) .groupBy(messages.userId), + // Last active: MAX(lastUsedAt) across non-revoked sessions per user + db.select({ + userId: sessions.userId, + lastActiveAt: sql`MAX(${sessions.lastUsedAt})`, + }) + .from(sessions) + .where(and(inArray(sessions.userId, userIds), isNull(sessions.revokedAt))) + .groupBy(sessions.userId), ]); const toCountMap = (rows: Array<{ userId: string | null; count: unknown }>) => { @@ -97,12 +106,17 @@ export const GET = withAdminAuth(async (_adminUser, _request) => { const chatMessagesCountMap = toCountMap(chatMessageCounts); const globalMessagesCountMap = toCountMap(globalMessageCounts); + const lastActiveMap = new Map( + lastActiveDates.map(row => [row.userId, row.lastActiveAt ?? null]) + ); + const usersWithStats = allUsers.map((user) => ({ ...user, drivesCount: drivesCountMap.get(user.id) ?? 0, pagesCount: pagesCountMap.get(user.id) ?? 0, chatMessagesCount: chatMessagesCountMap.get(user.id) ?? 0, globalMessagesCount: globalMessagesCountMap.get(user.id) ?? 0, + lastActiveAt: lastActiveMap.get(user.id) ?? null, })); // Fetch Stripe subscription details to check if gifted (skip on-prem - no Stripe) @@ -165,7 +179,7 @@ export const GET = withAdminAuth(async (_adminUser, _request) => { }; }); - // Remove the count fields from the response + // Remove raw count fields (they live under stats); keep lastActiveAt const cleanUsers = enrichedUsers.map((userData) => { const { // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/apps/admin/src/app/api/monitoring/[metric]/route.ts b/apps/admin/src/app/api/monitoring/[metric]/route.ts index b98de9972e..1a1cb74d4a 100644 --- a/apps/admin/src/app/api/monitoring/[metric]/route.ts +++ b/apps/admin/src/app/api/monitoring/[metric]/route.ts @@ -7,6 +7,7 @@ import { getAiUsageMetrics, getErrorAnalytics, getPerformanceMetrics, + getGrowthMetrics, getDateRange } from '@/lib/monitoring'; import { loggers } from '@pagespace/lib/logging/logger-config'; @@ -52,7 +53,11 @@ export const GET = withAdminAuth(async (_adminUser, request, conte case 'performance': data = await getPerformanceMetrics(startDate, endDate); break; - + + case 'growth': + data = await getGrowthMetrics(); + break; + default: return NextResponse.json( { error: 'Invalid metric type' }, diff --git a/apps/admin/src/components/admin/ContactSubmissionsTable.tsx b/apps/admin/src/components/admin/ContactSubmissionsTable.tsx index c823d02d5d..de32f5b784 100644 --- a/apps/admin/src/components/admin/ContactSubmissionsTable.tsx +++ b/apps/admin/src/components/admin/ContactSubmissionsTable.tsx @@ -24,8 +24,16 @@ import { Calendar, ExternalLink, ChevronLeft, - ChevronRight as ChevronRightIcon + ChevronRight as ChevronRightIcon, + CheckCircle2, + Circle, } from "lucide-react"; +import { fetchWithAuth } from "@/lib/auth/auth-fetch"; + +interface RegisteredUser { + id: string; + subscriptionTier: string | null; +} interface ContactSubmission { id: string; @@ -34,6 +42,8 @@ interface ContactSubmission { subject: string; message: string; createdAt: string; + resolvedAt: string | null; + registeredUser: RegisteredUser | null; } interface ContactSubmissionsTableProps { @@ -49,6 +59,8 @@ interface ContactSubmissionsTableProps { onSearch: (searchTerm: string) => void; onPageChange: (page: number) => void; onSort: (sortBy: string, sortOrder: 'asc' | 'desc') => void; + onStatusFilter: (status: 'all' | 'open' | 'closed') => void; + statusFilter: 'all' | 'open' | 'closed'; isLoading?: boolean; } @@ -65,18 +77,31 @@ function truncateText(text: string, maxLength: number = 100) { return text.substring(0, maxLength) + '...'; } +function tierColor(tier: string | null): string { + switch (tier) { + case 'pro': return 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300'; + case 'founder': return 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300'; + case 'business': return 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'; + default: return 'bg-muted text-muted-foreground'; + } +} + export function ContactSubmissionsTable({ submissions, pagination, onSearch, onPageChange, onSort, + onStatusFilter, + statusFilter, isLoading = false }: ContactSubmissionsTableProps) { const [searchTerm, setSearchTerm] = useState(""); const [expandedSubmissions, setExpandedSubmissions] = useState>({}); const [sortBy, setSortBy] = useState('createdAt'); const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc'); + const [resolvingId, setResolvingId] = useState(null); + const [localResolved, setLocalResolved] = useState>({}); const handleSearch = (value: string) => { setSearchTerm(value); @@ -102,6 +127,30 @@ export function ContactSubmissionsTable({ return sortOrder === 'asc' ? '↑' : '↓'; }; + const handleToggleResolved = async (submission: ContactSubmission) => { + const isResolved = localResolved[submission.id] !== undefined + ? localResolved[submission.id] + : submission.resolvedAt !== null; + setResolvingId(submission.id); + try { + const response = await fetchWithAuth(`/api/admin/contact/${submission.id}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ resolved: !isResolved }), + }); + if (response.ok) { + setLocalResolved(prev => ({ ...prev, [submission.id]: !isResolved })); + } + } finally { + setResolvingId(null); + } + }; + + const isResolved = (submission: ContactSubmission) => + localResolved[submission.id] !== undefined + ? localResolved[submission.id] + : submission.resolvedAt !== null; + if (isLoading) { return ( @@ -119,14 +168,29 @@ export function ContactSubmissionsTable({ return (
-
- - handleSearch(e.target.value)} - className="pl-10" - /> +
+
+ + handleSearch(e.target.value)} + className="pl-10" + /> +
+
+ {(['all', 'open', 'closed'] as const).map((s) => ( + + ))} +
@@ -137,7 +201,7 @@ export function ContactSubmissionsTable({ Contact Submissions - {pagination.total} total submissions + {pagination.total} {statusFilter !== 'all' ? statusFilter : 'total'} submissions @@ -152,6 +216,7 @@ export function ContactSubmissionsTable({ + Status handleSort('name')} @@ -209,7 +274,31 @@ export function ContactSubmissionsTable({ - {submission.name} + + + + +
+ {submission.name} + {submission.registeredUser && ( + + {submission.registeredUser.subscriptionTier ?? 'free'} + + )} +
+
{submission.email} @@ -241,7 +330,7 @@ export function ContactSubmissionsTable({ - +
@@ -265,10 +354,32 @@ export function ContactSubmissionsTable({
+ {submission.registeredUser ? ( +
+ Account: + + + {submission.registeredUser.subscriptionTier ?? 'free'} user + + {submission.registeredUser.id} + +
+ ) : ( +
+ Account: + Not registered +
+ )}
Submitted: {formatDateTime(submission.createdAt)}
+ {isResolved(submission) && ( +
+ Resolved: + Yes +
+ )}
@@ -287,7 +398,19 @@ export function ContactSubmissionsTable({ {submission.message}
-
+
+
); -} \ No newline at end of file +} diff --git a/apps/admin/src/components/admin/UsersTable.tsx b/apps/admin/src/components/admin/UsersTable.tsx index 628c421e0a..635ffe9c61 100644 --- a/apps/admin/src/components/admin/UsersTable.tsx +++ b/apps/admin/src/components/admin/UsersTable.tsx @@ -13,7 +13,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { ChevronDown, ChevronRight, Search, Shield, MessageCircle, Database, Settings, Crown, CreditCard, CheckCircle, Gift, ExternalLink, XCircle } from "lucide-react"; +import { ChevronDown, ChevronRight, Search, Shield, MessageCircle, Database, Settings, Crown, CreditCard, CheckCircle, Gift, ExternalLink, XCircle, Clock } from "lucide-react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { post, del } from "@/lib/auth/auth-fetch"; @@ -62,6 +62,7 @@ interface UserData { tokenVersion: number; subscriptionTier: 'free' | 'pro' | 'founder' | 'business'; stripeCustomerId: string | null; + lastActiveAt: string | null; stats: UserStats; aiSettings: AiSetting[]; recentTokens: RefreshToken[]; @@ -73,11 +74,30 @@ interface UsersTableProps { onUserUpdate?: (userId: string, updatedUser: Partial) => void; } +const DORMANT_DAYS = 30; + function formatDate(dateString: string | null) { if (!dateString) return "Never"; return new Date(dateString).toLocaleDateString(); } +function formatLastActive(dateString: string | null) { + if (!dateString) return "Never"; + const d = new Date(dateString); + const diffDays = Math.floor((Date.now() - d.getTime()) / (1000 * 60 * 60 * 24)); + if (diffDays === 0) return "Today"; + if (diffDays === 1) return "Yesterday"; + if (diffDays < 30) return `${diffDays}d ago`; + if (diffDays < 365) return `${Math.floor(diffDays / 30)}mo ago`; + return `${Math.floor(diffDays / 365)}y ago`; +} + +function isDormant(lastActiveAt: string | null) { + if (!lastActiveAt) return true; + const diffDays = (Date.now() - new Date(lastActiveAt).getTime()) / (1000 * 60 * 60 * 24); + return diffDays > DORMANT_DAYS; +} + function formatDateTime(dateString: string | null) { if (!dateString) return "Never"; return new Date(dateString).toLocaleString(); @@ -96,17 +116,20 @@ function getUserInitials(name: string | null | undefined) { export function UsersTable({ users, onUserUpdate }: UsersTableProps) { const [searchTerm, setSearchTerm] = useState(""); + const [showDormantOnly, setShowDormantOnly] = useState(false); const [expandedUsers, setExpandedUsers] = useState>({}); const [updatingUsers, setUpdatingUsers] = useState>({}); const [recentlyUpdated, setRecentlyUpdated] = useState>({}); const [selectedTiers, setSelectedTiers] = useState>({}); + const dormantCount = users.filter(u => isDormant(u.lastActiveAt)).length; + const filteredUsers = users.filter((user) => { + if (showDormantOnly && !isDormant(user.lastActiveAt)) return false; const normalizedSearchTerm = searchTerm.toLowerCase(); const name = (user.name ?? "").toLowerCase(); const email = (user.email ?? "").toLowerCase(); const currentAiProvider = (user.currentAiProvider ?? "").toLowerCase(); - return ( name.includes(normalizedSearchTerm) || email.includes(normalizedSearchTerm) || @@ -192,14 +215,25 @@ export function UsersTable({ users, onUserUpdate }: UsersTableProps) { return (
-
- - setSearchTerm(e.target.value)} - className="pl-10" - /> +
+
+ + setSearchTerm(e.target.value)} + className="pl-10" + /> +
+
@@ -236,6 +270,11 @@ export function UsersTable({ users, onUserUpdate }: UsersTableProps) { {user.emailVerified ? "Verified" : "Unverified"} + + + {formatLastActive(user.lastActiveAt)} + + {user.stats.drives} drives @@ -314,6 +353,10 @@ export function UsersTable({ users, onUserUpdate }: UsersTableProps) { User ID: {user.id}
+
+ Last Active: + {user.lastActiveAt ? formatDateTime(user.lastActiveAt) : "Never"} +
Email Verified: {formatDate(user.emailVerified)} diff --git a/apps/admin/src/lib/monitoring-queries.ts b/apps/admin/src/lib/monitoring-queries.ts index 2a43fec4e7..df4ab66416 100644 --- a/apps/admin/src/lib/monitoring-queries.ts +++ b/apps/admin/src/lib/monitoring-queries.ts @@ -3,9 +3,10 @@ */ import { db } from '@pagespace/db/db' -import { sql, eq, and, or, gt, asc, gte, lte, desc, count, inArray } from '@pagespace/db/operators' +import { sql, eq, and, or, gt, asc, gte, lte, lt, desc, count, inArray, isNull, isNotNull } from '@pagespace/db/operators' import { users } from '@pagespace/db/schema/auth' -import { apiMetrics, userActivities, aiUsageLogs, systemLogs, errorLogs } from '@pagespace/db/schema/monitoring'; +import { apiMetrics, userActivities, aiUsageLogs, systemLogs, errorLogs, activityLogs } from '@pagespace/db/schema/monitoring'; +import { sessions } from '@pagespace/db/schema/sessions'; import { creditLedger, creditBalances, creditHolds } from '@pagespace/db/schema/credits'; import { subscriptions } from '@pagespace/db/schema/subscriptions'; import type { SQL } from '@pagespace/db/operators'; @@ -55,14 +56,15 @@ export async function getSystemHealth(startDate?: Date, endDate?: Date) { .orderBy(desc(errorLogs.timestamp)) .limit(20); - // Get active users in last 15 minutes for the summary card + // Active users: distinct sessions touched in last 15 minutes (sessions.lastUsedAt is + // updated non-blocking on every authenticated request — reliable signal) const fifteenMinutesAgo = new Date(Date.now() - 15 * 60 * 1000); const activeUsers = await db .select({ - count: sql`COUNT(DISTINCT ${userActivities.userId})::int`, + count: sql`COUNT(DISTINCT ${sessions.userId})::int`, }) - .from(userActivities) - .where(gte(userActivities.timestamp, fifteenMinutesAgo)); + .from(sessions) + .where(and(gte(sessions.lastUsedAt, fifteenMinutesAgo), isNull(sessions.revokedAt))); return { logsByLevel: logsByLevel.map((entry) => ({ @@ -144,54 +146,54 @@ export async function getApiMetrics(startDate?: Date, endDate?: Date) { /** * Get user activity data + * Uses activityLogs (comprehensive audit trail written on every page/drive/member operation) + * NOT userActivities (only written on conversation deletion — effectively empty) */ export async function getUserActivity(startDate?: Date, endDate?: Date) { - const conditions = []; - + const conditions: SQL[] = [isNotNull(activityLogs.userId)]; + if (startDate) { - conditions.push(gte(userActivities.timestamp, startDate)); + conditions.push(gte(activityLogs.timestamp, startDate)); } if (endDate) { - conditions.push(lte(userActivities.timestamp, endDate)); + conditions.push(lte(activityLogs.timestamp, endDate)); } - // Get activity heatmap data - using Drizzle query const heatmapData = await db .select({ - day_of_week: sql`EXTRACT(DOW FROM ${userActivities.timestamp})`, - hour_of_day: sql`EXTRACT(HOUR FROM ${userActivities.timestamp})`, + day_of_week: sql`EXTRACT(DOW FROM ${activityLogs.timestamp})`, + hour_of_day: sql`EXTRACT(HOUR FROM ${activityLogs.timestamp})`, activity_count: count(), }) - .from(userActivities) - .where(conditions.length > 0 ? and(...conditions) : undefined) + .from(activityLogs) + .where(and(...conditions)) .groupBy( - sql`EXTRACT(DOW FROM ${userActivities.timestamp})`, - sql`EXTRACT(HOUR FROM ${userActivities.timestamp})` + sql`EXTRACT(DOW FROM ${activityLogs.timestamp})`, + sql`EXTRACT(HOUR FROM ${activityLogs.timestamp})` ); - // Get most active users const mostActiveUsers = await db .select({ - userId: userActivities.userId, + userId: activityLogs.userId, userName: users.name, actionCount: count(), }) - .from(userActivities) - .innerJoin(users, eq(userActivities.userId, users.id)) - .where(conditions.length > 0 ? and(...conditions) : undefined) - .groupBy(userActivities.userId, users.name) + .from(activityLogs) + .innerJoin(users, eq(activityLogs.userId, users.id)) + .where(and(...conditions)) + .groupBy(activityLogs.userId, users.name) .orderBy(desc(count())) .limit(10); - // Get feature usage + // operation column stores the action type (create, update, delete, rename, etc.) const featureUsage = await db .select({ - action: userActivities.action, + action: activityLogs.operation, count: count(), }) - .from(userActivities) - .where(conditions.length > 0 ? and(...conditions) : undefined) - .groupBy(userActivities.action) + .from(activityLogs) + .where(and(...conditions)) + .groupBy(activityLogs.operation) .orderBy(desc(count())) .limit(15); @@ -684,6 +686,46 @@ export async function getTopSpendersByMargin( })); } +export interface MarginByTierRow { + tier: string; + realCostCents: number; + chargedCents: number; + appliedCents: number; + requestCount: number; + marginCents: number; + marginPct: number | null; +} + +export async function getMarginByTier( + startDate?: Date, + endDate?: Date, +): Promise { + const rows = await db + .select({ + tier: users.subscriptionTier, + realCostCents: realCostSum, + chargedCents: chargedSum, + appliedCents: appliedSum, + requestCount: count(), + }) + .from(creditLedger) + .leftJoin(aiUsageLogs, eq(creditLedger.aiUsageLogId, aiUsageLogs.id)) + .innerJoin(users, eq(creditLedger.userId, users.id)) + .where(and(...usageConditions(startDate, endDate))) + .groupBy(users.subscriptionTier) + .orderBy(desc(realCostSum)); + + return rows.map((r) => ({ + tier: r.tier ?? 'free', + realCostCents: r.realCostCents, + chargedCents: r.chargedCents, + appliedCents: r.appliedCents, + requestCount: r.requestCount, + marginCents: r.chargedCents - r.realCostCents, + marginPct: computeMarginPct(r.realCostCents, r.chargedCents), + })); +} + export async function getOutstandingDebtByUser(limit = 10): Promise { const rows = await db .select({ @@ -1115,4 +1157,186 @@ export async function getLiveHolds(): Promise { holdCount: rows[0]?.holdCount ?? 0, heldCents: rows[0]?.heldCents ?? 0, }; +} + +// ── Growth & MAU queries ────────────────────────────────────────────────────── + +export interface GrowthSummary { + totalUsers: number; + mau: number; + wau: number; + dau: number; + dauMauRatio: number; + newUsersThisMonth: number; + newUsersLastMonth: number; + momGrowthPct: number | null; + payingUsers: number; + payingUsersPct: number; +} + +export interface MAUTrendRow { + period: string; + mau: number; + newUsers: number; +} + +export interface DAUTrendRow { + day: string; + dau: number; + signups: number; +} + +export interface TierBreakdownRow { + tier: string; + count: number; + pct: number; +} + +export interface GrowthMetrics { + summary: GrowthSummary; + mauTrend: MAUTrendRow[]; + dauTrend: DAUTrendRow[]; + tierBreakdown: TierBreakdownRow[]; +} + +export async function getGrowthMetrics(): Promise { + const now = new Date(); + const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); + const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); + const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); + const startOfThisMonth = new Date(now.getFullYear(), now.getMonth(), 1); + const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1); + const twelveMonthsAgo = new Date(now.getFullYear() - 1, now.getMonth(), 1); + + const [totalUsersResult] = await db.select({ count: count() }).from(users); + const totalUsers = totalUsersResult?.count ?? 0; + + // Current MAU/WAU/DAU from session activity (most reliable signal) + const [mauResult] = await db + .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) + .from(sessions) + .where(and(gte(sessions.lastUsedAt, thirtyDaysAgo), isNull(sessions.revokedAt))); + + const [wauResult] = await db + .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) + .from(sessions) + .where(and(gte(sessions.lastUsedAt, sevenDaysAgo), isNull(sessions.revokedAt))); + + const [dauResult] = await db + .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) + .from(sessions) + .where(and(gte(sessions.lastUsedAt, oneDayAgo), isNull(sessions.revokedAt))); + + const mau = mauResult?.count ?? 0; + const wau = wauResult?.count ?? 0; + const dau = dauResult?.count ?? 0; + + const [newThisMonthResult] = await db + .select({ count: count() }) + .from(users) + .where(gte(users.createdAt, startOfThisMonth)); + + const [newLastMonthResult] = await db + .select({ count: count() }) + .from(users) + .where(and(gte(users.createdAt, startOfLastMonth), lt(users.createdAt, startOfThisMonth))); + + const newUsersThisMonth = newThisMonthResult?.count ?? 0; + const newUsersLastMonth = newLastMonthResult?.count ?? 0; + const momGrowthPct = newUsersLastMonth > 0 + ? ((newUsersThisMonth - newUsersLastMonth) / newUsersLastMonth) * 100 + : null; + + const [payingResult] = await db + .select({ count: count() }) + .from(users) + .where(sql`${users.subscriptionTier} != 'free'`); + const payingUsers = payingResult?.count ?? 0; + + // MAU trend (12 months) from activity_logs — comprehensive audit trail + const mauTrendRaw = await db + .select({ + month: sql`DATE_TRUNC('month', ${activityLogs.timestamp})`, + mau: sql`COUNT(DISTINCT ${activityLogs.userId})::int`, + }) + .from(activityLogs) + .where(and(gte(activityLogs.timestamp, twelveMonthsAgo), isNotNull(activityLogs.userId))) + .groupBy(sql`DATE_TRUNC('month', ${activityLogs.timestamp})`) + .orderBy(asc(sql`DATE_TRUNC('month', ${activityLogs.timestamp})`)); + + const signupsByMonthRaw = await db + .select({ + month: sql`DATE_TRUNC('month', ${users.createdAt})`, + signups: count(), + }) + .from(users) + .where(gte(users.createdAt, twelveMonthsAgo)) + .groupBy(sql`DATE_TRUNC('month', ${users.createdAt})`) + .orderBy(asc(sql`DATE_TRUNC('month', ${users.createdAt})`)); + + const signupsByMonth = new Map(signupsByMonthRaw.map(r => [r.month, r.signups])); + const mauTrend: MAUTrendRow[] = mauTrendRaw.map(r => ({ + period: r.month, + mau: r.mau, + newUsers: signupsByMonth.get(r.month) ?? 0, + })); + + // DAU trend (last 30 days) from activity_logs + const dauTrendRaw = await db + .select({ + day: sql`DATE_TRUNC('day', ${activityLogs.timestamp})`, + dau: sql`COUNT(DISTINCT ${activityLogs.userId})::int`, + }) + .from(activityLogs) + .where(and(gte(activityLogs.timestamp, thirtyDaysAgo), isNotNull(activityLogs.userId))) + .groupBy(sql`DATE_TRUNC('day', ${activityLogs.timestamp})`) + .orderBy(asc(sql`DATE_TRUNC('day', ${activityLogs.timestamp})`)); + + const signupsByDayRaw = await db + .select({ + day: sql`DATE_TRUNC('day', ${users.createdAt})`, + signups: count(), + }) + .from(users) + .where(gte(users.createdAt, thirtyDaysAgo)) + .groupBy(sql`DATE_TRUNC('day', ${users.createdAt})`) + .orderBy(asc(sql`DATE_TRUNC('day', ${users.createdAt})`)); + + const signupsByDay = new Map(signupsByDayRaw.map(r => [r.day, r.signups])); + const dauTrend: DAUTrendRow[] = dauTrendRaw.map(r => ({ + day: r.day, + dau: r.dau, + signups: signupsByDay.get(r.day) ?? 0, + })); + + // Tier breakdown + const tierRaw = await db + .select({ tier: users.subscriptionTier, count: count() }) + .from(users) + .groupBy(users.subscriptionTier) + .orderBy(desc(count())); + + const tierBreakdown: TierBreakdownRow[] = tierRaw.map(r => ({ + tier: r.tier, + count: r.count, + pct: totalUsers > 0 ? (r.count / totalUsers) * 100 : 0, + })); + + return { + summary: { + totalUsers, + mau, + wau, + dau, + dauMauRatio: mau > 0 ? (dau / mau) * 100 : 0, + newUsersThisMonth, + newUsersLastMonth, + momGrowthPct, + payingUsers, + payingUsersPct: totalUsers > 0 ? (payingUsers / totalUsers) * 100 : 0, + }, + mauTrend, + dauTrend, + tierBreakdown, + }; } \ No newline at end of file diff --git a/apps/admin/src/lib/monitoring-types.ts b/apps/admin/src/lib/monitoring-types.ts index 050e786812..195426d918 100644 --- a/apps/admin/src/lib/monitoring-types.ts +++ b/apps/admin/src/lib/monitoring-types.ts @@ -118,6 +118,24 @@ export interface PerformanceMetricsData { }>; } +export interface GrowthMetricsData { + summary: { + totalUsers: number; + mau: number; + wau: number; + dau: number; + dauMauRatio: number; + newUsersThisMonth: number; + newUsersLastMonth: number; + momGrowthPct: number | null; + payingUsers: number; + payingUsersPct: number; + }; + mauTrend: Array<{ period: string; mau: number; newUsers: number }>; + dauTrend: Array<{ day: string; dau: number; signups: number }>; + tierBreakdown: Array<{ tier: string; count: number; pct: number }>; +} + export interface MonitoringWidgetProps { data: T | null; isLoading: boolean; diff --git a/packages/db/drizzle/0161_contact_resolved_at.sql b/packages/db/drizzle/0161_contact_resolved_at.sql new file mode 100644 index 0000000000..8ea350907d --- /dev/null +++ b/packages/db/drizzle/0161_contact_resolved_at.sql @@ -0,0 +1 @@ +ALTER TABLE "contact_submissions" ADD COLUMN "resolvedAt" timestamp; \ No newline at end of file diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index b4bd7feb5a..cb1d462c2e 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -1128,6 +1128,13 @@ "when": 1781229017394, "tag": "0160_talented_forgotten_one", "breakpoints": true + }, + { + "idx": 161, + "version": "7", + "when": 1781308800000, + "tag": "0161_contact_resolved_at", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/db/src/schema/contact.ts b/packages/db/src/schema/contact.ts index 24c418c10d..982bd5bc3b 100644 --- a/packages/db/src/schema/contact.ts +++ b/packages/db/src/schema/contact.ts @@ -8,6 +8,7 @@ export const contactSubmissions = pgTable('contact_submissions', { subject: text('subject').notNull(), message: text('message').notNull(), createdAt: timestamp('createdAt', { mode: 'date' }).defaultNow().notNull(), + resolvedAt: timestamp('resolvedAt', { mode: 'date' }), }, (table) => { return { emailIdx: index('contact_submissions_email_idx').on(table.email), From cc8bc7f967825ddd95f7d56603d20bc622a62027 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Thu, 11 Jun 2026 22:56:27 -0500 Subject: [PATCH 2/7] fix(admin): correct alerts route + RouteContext pattern for contact PATCH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - alerts/route.ts: use getApiMetrics (not getSystemHealth) for error rate — errorRate is computed in getApiMetrics, getSystemHealth only returns log levels - contact/[id]/route.ts: use explicit RouteContext generic for withAdminAuth instead of unsafe type cast, matching convention in gift-subscription route - journal: correct migration timestamp to present day Co-Authored-By: Claude Sonnet 4.6 --- apps/admin/src/app/api/admin/alerts/route.ts | 10 +++++----- apps/admin/src/app/api/admin/contact/[id]/route.ts | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/admin/src/app/api/admin/alerts/route.ts b/apps/admin/src/app/api/admin/alerts/route.ts index 258a649cd2..758cd0c222 100644 --- a/apps/admin/src/app/api/admin/alerts/route.ts +++ b/apps/admin/src/app/api/admin/alerts/route.ts @@ -1,24 +1,24 @@ import { NextResponse } from 'next/server'; import { withAdminAuth } from '@/lib/auth'; -import { getSystemHealth, getNegativeMarginAccounts, getLiveHolds } from '@/lib/monitoring'; +import { getApiMetrics, getNegativeMarginAccounts, getLiveHolds } from '@/lib/monitoring'; import { loggers } from '@pagespace/lib/logging/logger-config'; // Lightweight alert-state endpoint for nav badges. Cached 60s. export const GET = withAdminAuth(async () => { try { const since24h = new Date(Date.now() - 24 * 60 * 60 * 1000); - const [health, negativeMargin, holds] = await Promise.all([ - getSystemHealth(since24h), + const [metrics, negativeMargin, holds] = await Promise.all([ + getApiMetrics(since24h), getNegativeMarginAccounts(since24h), getLiveHolds(), ]); return NextResponse.json( { - errorRateAlert: health.errorRate !== null && health.errorRate > 5, + errorRateAlert: metrics.errorRate > 5, negativeMarginAlert: negativeMargin.length > 0, liveHoldsAlert: holds.holdCount > 50, - errorRate: health.errorRate, + errorRate: metrics.errorRate, negativeMarginCount: negativeMargin.length, liveHoldsCount: holds.holdCount, }, diff --git a/apps/admin/src/app/api/admin/contact/[id]/route.ts b/apps/admin/src/app/api/admin/contact/[id]/route.ts index ed81445cf8..1ae3d67a59 100644 --- a/apps/admin/src/app/api/admin/contact/[id]/route.ts +++ b/apps/admin/src/app/api/admin/contact/[id]/route.ts @@ -4,9 +4,11 @@ import { contactSubmissions } from '@pagespace/db/schema/contact'; import { loggers } from '@pagespace/lib/logging/logger-config'; import { withAdminAuth } from '@/lib/auth'; -export const PATCH = withAdminAuth(async (_adminUser, request, context) => { +type RouteContext = { params: Promise<{ id: string }> }; + +export const PATCH = withAdminAuth(async (_adminUser, request, context) => { try { - const { id } = await (context as { params: Promise<{ id: string }> }).params; + const { id } = await context.params; const body = await request.json() as { resolved: boolean }; const [updated] = await db From 46b55b11cee7ba893c674269c64e642fd1504957 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Thu, 11 Jun 2026 22:58:32 -0500 Subject: [PATCH 3/7] fix(admin/growth): address Codex P1+P2 review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P1 — MAU/WAU/DAU: drop isNull(revokedAt) filter so users who were active in the window but later logged out still count; revokedAt is current session state, not a historical activity gate. P2 — MoM growth: switch from partial-calendar-month vs full-last-month to rolling 30d vs prior 30d, eliminating the systematic negative-growth bias before month-end. P2 — Map date keys: DATE_TRUNC returns Date objects from node-postgres despite sql annotation; normalise via toISOString() before using as Map keys so signup-trend lookups don't silently return zero. Update growth page stat labels to reflect rolling-window semantics. Co-Authored-By: Claude Sonnet 4.6 --- apps/admin/src/app/(admin)/growth/page.tsx | 8 ++--- apps/admin/src/lib/monitoring-queries.ts | 34 ++++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/apps/admin/src/app/(admin)/growth/page.tsx b/apps/admin/src/app/(admin)/growth/page.tsx index a77d991467..6fe0cc0fb9 100644 --- a/apps/admin/src/app/(admin)/growth/page.tsx +++ b/apps/admin/src/app/(admin)/growth/page.tsx @@ -178,9 +178,9 @@ export default function GrowthPage() { {/* Secondary stats */}
diff --git a/apps/admin/src/lib/monitoring-queries.ts b/apps/admin/src/lib/monitoring-queries.ts index df4ab66416..a94f94b7cf 100644 --- a/apps/admin/src/lib/monitoring-queries.ts +++ b/apps/admin/src/lib/monitoring-queries.ts @@ -1211,35 +1211,42 @@ export async function getGrowthMetrics(): Promise { const [totalUsersResult] = await db.select({ count: count() }).from(users); const totalUsers = totalUsersResult?.count ?? 0; - // Current MAU/WAU/DAU from session activity (most reliable signal) + // Current MAU/WAU/DAU from session activity — count ALL sessions with lastUsedAt in + // the window, regardless of revokedAt. A user who was active 15 days ago and then logged + // out still counts toward MAU; revokedAt describes current session state, not history. const [mauResult] = await db .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) .from(sessions) - .where(and(gte(sessions.lastUsedAt, thirtyDaysAgo), isNull(sessions.revokedAt))); + .where(gte(sessions.lastUsedAt, thirtyDaysAgo)); const [wauResult] = await db .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) .from(sessions) - .where(and(gte(sessions.lastUsedAt, sevenDaysAgo), isNull(sessions.revokedAt))); + .where(gte(sessions.lastUsedAt, sevenDaysAgo)); const [dauResult] = await db .select({ count: sql`COUNT(DISTINCT ${sessions.userId})::int` }) .from(sessions) - .where(and(gte(sessions.lastUsedAt, oneDayAgo), isNull(sessions.revokedAt))); + .where(gte(sessions.lastUsedAt, oneDayAgo)); const mau = mauResult?.count ?? 0; const wau = wauResult?.count ?? 0; const dau = dauResult?.count ?? 0; + // Use rolling 30-day vs previous 30-day window to avoid partial-month bias. + // Calendar-month comparison (current partial month vs full last month) systematically + // shows negative growth before month-end — rolling windows are bias-free. + const sixtyDaysAgo = new Date(now.getTime() - 60 * 24 * 60 * 60 * 1000); + const [newThisMonthResult] = await db .select({ count: count() }) .from(users) - .where(gte(users.createdAt, startOfThisMonth)); + .where(gte(users.createdAt, thirtyDaysAgo)); const [newLastMonthResult] = await db .select({ count: count() }) .from(users) - .where(and(gte(users.createdAt, startOfLastMonth), lt(users.createdAt, startOfThisMonth))); + .where(and(gte(users.createdAt, sixtyDaysAgo), lt(users.createdAt, thirtyDaysAgo))); const newUsersThisMonth = newThisMonthResult?.count ?? 0; const newUsersLastMonth = newLastMonthResult?.count ?? 0; @@ -1274,11 +1281,14 @@ export async function getGrowthMetrics(): Promise { .groupBy(sql`DATE_TRUNC('month', ${users.createdAt})`) .orderBy(asc(sql`DATE_TRUNC('month', ${users.createdAt})`)); - const signupsByMonth = new Map(signupsByMonthRaw.map(r => [r.month, r.signups])); + // DATE_TRUNC returns Date objects from the node-postgres driver despite the sql + // annotation — normalise to ISO strings so Map key equality works across queries. + const toKey = (v: unknown) => (v instanceof Date ? v.toISOString() : String(v)); + const signupsByMonth = new Map(signupsByMonthRaw.map(r => [toKey(r.month), r.signups])); const mauTrend: MAUTrendRow[] = mauTrendRaw.map(r => ({ - period: r.month, + period: toKey(r.month), mau: r.mau, - newUsers: signupsByMonth.get(r.month) ?? 0, + newUsers: signupsByMonth.get(toKey(r.month)) ?? 0, })); // DAU trend (last 30 days) from activity_logs @@ -1302,11 +1312,11 @@ export async function getGrowthMetrics(): Promise { .groupBy(sql`DATE_TRUNC('day', ${users.createdAt})`) .orderBy(asc(sql`DATE_TRUNC('day', ${users.createdAt})`)); - const signupsByDay = new Map(signupsByDayRaw.map(r => [r.day, r.signups])); + const signupsByDay = new Map(signupsByDayRaw.map(r => [toKey(r.day), r.signups])); const dauTrend: DAUTrendRow[] = dauTrendRaw.map(r => ({ - day: r.day, + day: toKey(r.day), dau: r.dau, - signups: signupsByDay.get(r.day) ?? 0, + signups: signupsByDay.get(toKey(r.day)) ?? 0, })); // Tier breakdown From 412dc3e1fda4e6ec6b661aac79e34e8a22e16aa8 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Thu, 11 Jun 2026 23:05:19 -0500 Subject: [PATCH 4/7] fix(admin/monitoring): remove unused imports and vars to pass ESLint Co-Authored-By: Claude Sonnet 4.6 --- apps/admin/src/lib/monitoring-queries.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/admin/src/lib/monitoring-queries.ts b/apps/admin/src/lib/monitoring-queries.ts index a94f94b7cf..99f675acf2 100644 --- a/apps/admin/src/lib/monitoring-queries.ts +++ b/apps/admin/src/lib/monitoring-queries.ts @@ -5,7 +5,7 @@ import { db } from '@pagespace/db/db' import { sql, eq, and, or, gt, asc, gte, lte, lt, desc, count, inArray, isNull, isNotNull } from '@pagespace/db/operators' import { users } from '@pagespace/db/schema/auth' -import { apiMetrics, userActivities, aiUsageLogs, systemLogs, errorLogs, activityLogs } from '@pagespace/db/schema/monitoring'; +import { apiMetrics, aiUsageLogs, systemLogs, errorLogs, activityLogs } from '@pagespace/db/schema/monitoring'; import { sessions } from '@pagespace/db/schema/sessions'; import { creditLedger, creditBalances, creditHolds } from '@pagespace/db/schema/credits'; import { subscriptions } from '@pagespace/db/schema/subscriptions'; @@ -1204,8 +1204,6 @@ export async function getGrowthMetrics(): Promise { const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); - const startOfThisMonth = new Date(now.getFullYear(), now.getMonth(), 1); - const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1); const twelveMonthsAgo = new Date(now.getFullYear() - 1, now.getMonth(), 1); const [totalUsersResult] = await db.select({ count: count() }).from(users); From b2e9f1149b3e5543d069f78b2237f7cf3a2221a5 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Thu, 11 Jun 2026 23:08:48 -0500 Subject: [PATCH 5/7] fix(admin): fix TypeScript errors in recharts formatters and contact schema import Co-Authored-By: Claude Sonnet 4.6 --- apps/admin/src/app/(admin)/ai-billing/page.tsx | 2 +- apps/admin/src/app/(admin)/growth/page.tsx | 2 +- apps/admin/src/app/api/admin/contact/route.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/admin/src/app/(admin)/ai-billing/page.tsx b/apps/admin/src/app/(admin)/ai-billing/page.tsx index b23aa9ad11..cf8971da23 100644 --- a/apps/admin/src/app/(admin)/ai-billing/page.tsx +++ b/apps/admin/src/app/(admin)/ai-billing/page.tsx @@ -307,7 +307,7 @@ export default function AdminAiBillingPage() { `$${v}`} tick={{ fontSize: 11 }} /> - [`$${v.toFixed(2)}`]} /> + [`$${Number(v ?? 0).toFixed(2)}`]} /> diff --git a/apps/admin/src/app/(admin)/growth/page.tsx b/apps/admin/src/app/(admin)/growth/page.tsx index 6fe0cc0fb9..f40f793a10 100644 --- a/apps/admin/src/app/(admin)/growth/page.tsx +++ b/apps/admin/src/app/(admin)/growth/page.tsx @@ -275,7 +275,7 @@ export default function GrowthPage() { [value.toLocaleString(), TIER_LABELS[name] ?? name]} + formatter={(value, name) => [Number(value ?? 0).toLocaleString(), TIER_LABELS[String(name)] ?? String(name)]} /> diff --git a/apps/admin/src/app/api/admin/contact/route.ts b/apps/admin/src/app/api/admin/contact/route.ts index 93b9c54d35..af6d5a2ac8 100644 --- a/apps/admin/src/app/api/admin/contact/route.ts +++ b/apps/admin/src/app/api/admin/contact/route.ts @@ -1,7 +1,7 @@ import { db } from '@pagespace/db/db' import { asc, desc, ilike, or, and, count, gte, sql, eq, isNull, isNotNull } from '@pagespace/db/operators' import { contactSubmissions } from '@pagespace/db/schema/contact'; -import { users } from '@pagespace/db/schema/users'; +import { users } from '@pagespace/db/schema/auth'; import { loggers } from '@pagespace/lib/logging/logger-config'; import { withAdminAuth } from '@/lib/auth'; import { parseBoundedIntParam } from '@/lib/utils/query-params'; From 51a9a59d6d1ed4d75ceae0d91431d8571f4d3749 Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Fri, 12 Jun 2026 09:41:37 -0500 Subject: [PATCH 6/7] fix(db): add missing 0161 snapshot to prevent duplicate migration generation db:generate in CI reads the latest snapshot and diffs against the current schema. Without 0161_snapshot.json, it would regenerate the resolvedAt column migration causing 'column already exists' on db:migrate. Co-Authored-By: Claude Sonnet 4.6 --- packages/db/drizzle/meta/0161_snapshot.json | 16959 ++++++++++++++++++ 1 file changed, 16959 insertions(+) create mode 100644 packages/db/drizzle/meta/0161_snapshot.json diff --git a/packages/db/drizzle/meta/0161_snapshot.json b/packages/db/drizzle/meta/0161_snapshot.json new file mode 100644 index 0000000000..828dcb125c --- /dev/null +++ b/packages/db/drizzle/meta/0161_snapshot.json @@ -0,0 +1,16959 @@ +{ + "id": "16123305-1c1c-4ae4-98ca-7c96b1f28e53", + "prevId": "a48112d6-5587-4508-8987-3128f3011dd8", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.device_tokens": { + "name": "device_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenHash": { + "name": "tokenHash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenPrefix": { + "name": "tokenPrefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "lastUsedAt": { + "name": "lastUsedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deviceId": { + "name": "deviceId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "platform": { + "name": "platform", + "type": "PlatformType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "deviceName": { + "name": "deviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tokenVersion": { + "name": "tokenVersion", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "userAgent": { + "name": "userAgent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ipAddress": { + "name": "ipAddress", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lastIpAddress": { + "name": "lastIpAddress", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "trustScore": { + "name": "trustScore", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "suspiciousActivityCount": { + "name": "suspiciousActivityCount", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revokedReason": { + "name": "revokedReason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "replacedByTokenId": { + "name": "replacedByTokenId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "device_tokens_user_id_idx": { + "name": "device_tokens_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "device_tokens_token_hash_idx": { + "name": "device_tokens_token_hash_idx", + "columns": [ + { + "expression": "tokenHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "device_tokens_device_id_idx": { + "name": "device_tokens_device_id_idx", + "columns": [ + { + "expression": "deviceId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "device_tokens_expires_at_idx": { + "name": "device_tokens_expires_at_idx", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "device_tokens_active_device_idx": { + "name": "device_tokens_active_device_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deviceId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "platform", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"device_tokens\".\"revokedAt\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "device_tokens_userId_users_id_fk": { + "name": "device_tokens_userId_users_id_fk", + "tableFrom": "device_tokens", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "device_tokens_tokenHash_unique": { + "name": "device_tokens_tokenHash_unique", + "nullsNotDistinct": false, + "columns": [ + "tokenHash" + ] + } + } + }, + "public.email_unsubscribe_tokens": { + "name": "email_unsubscribe_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notification_type": { + "name": "notification_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "used_at": { + "name": "used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_unsubscribe_tokens_token_hash_idx": { + "name": "email_unsubscribe_tokens_token_hash_idx", + "columns": [ + { + "expression": "token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "email_unsubscribe_tokens_user_id_idx": { + "name": "email_unsubscribe_tokens_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "email_unsubscribe_tokens_expires_at_idx": { + "name": "email_unsubscribe_tokens_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_unsubscribe_tokens_user_id_users_id_fk": { + "name": "email_unsubscribe_tokens_user_id_users_id_fk", + "tableFrom": "email_unsubscribe_tokens", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_unsubscribe_tokens_token_hash_unique": { + "name": "email_unsubscribe_tokens_token_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "token_hash" + ] + } + } + }, + "public.mcp_tokens": { + "name": "mcp_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenHash": { + "name": "tokenHash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenPrefix": { + "name": "tokenPrefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isScoped": { + "name": "isScoped", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "lastUsed": { + "name": "lastUsed", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "mcp_tokens_user_id_idx": { + "name": "mcp_tokens_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_tokens_token_hash_idx": { + "name": "mcp_tokens_token_hash_idx", + "columns": [ + { + "expression": "tokenHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_tokens_userId_users_id_fk": { + "name": "mcp_tokens_userId_users_id_fk", + "tableFrom": "mcp_tokens", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mcp_tokens_tokenHash_unique": { + "name": "mcp_tokens_tokenHash_unique", + "nullsNotDistinct": false, + "columns": [ + "tokenHash" + ] + } + } + }, + "public.passkeys": { + "name": "passkeys", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transports": { + "name": "transports", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "passkeys_user_id_idx": { + "name": "passkeys_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkeys_credential_id_idx": { + "name": "passkeys_credential_id_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkeys_user_id_users_id_fk": { + "name": "passkeys_user_id_users_id_fk", + "tableFrom": "passkeys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "passkeys_credential_id_unique": { + "name": "passkeys_credential_id_unique", + "nullsNotDistinct": false, + "columns": [ + "credential_id" + ] + } + } + }, + "public.socket_tokens": { + "name": "socket_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenHash": { + "name": "tokenHash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "socket_tokens_user_id_idx": { + "name": "socket_tokens_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "socket_tokens_token_hash_idx": { + "name": "socket_tokens_token_hash_idx", + "columns": [ + { + "expression": "tokenHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "socket_tokens_expires_at_idx": { + "name": "socket_tokens_expires_at_idx", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "socket_tokens_userId_users_id_fk": { + "name": "socket_tokens_userId_users_id_fk", + "tableFrom": "socket_tokens", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "socket_tokens_tokenHash_unique": { + "name": "socket_tokens_tokenHash_unique", + "nullsNotDistinct": false, + "columns": [ + "tokenHash" + ] + } + } + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "googleId": { + "name": "googleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "appleId": { + "name": "appleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "AuthProvider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'email'" + }, + "tokenVersion": { + "name": "tokenVersion", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "role": { + "name": "role", + "type": "UserRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "adminRoleVersion": { + "name": "adminRoleVersion", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "currentAiProvider": { + "name": "currentAiProvider", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'openai'" + }, + "currentAiModel": { + "name": "currentAiModel", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'openai/gpt-5.3-chat'" + }, + "storageUsedBytes": { + "name": "storageUsedBytes", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "activeUploads": { + "name": "activeUploads", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "lastStorageCalculated": { + "name": "lastStorageCalculated", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "stripeCustomerId": { + "name": "stripeCustomerId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subscriptionTier": { + "name": "subscriptionTier", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'free'" + }, + "tosAcceptedAt": { + "name": "tosAcceptedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failedLoginAttempts": { + "name": "failedLoginAttempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "lockedUntil": { + "name": "lockedUntil", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "suspendedAt": { + "name": "suspendedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "suspendedReason": { + "name": "suspendedReason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "users_googleId_unique": { + "name": "users_googleId_unique", + "nullsNotDistinct": false, + "columns": [ + "googleId" + ] + }, + "users_appleId_unique": { + "name": "users_appleId_unique", + "nullsNotDistinct": false, + "columns": [ + "appleId" + ] + }, + "users_stripeCustomerId_unique": { + "name": "users_stripeCustomerId_unique", + "nullsNotDistinct": false, + "columns": [ + "stripeCustomerId" + ] + } + } + }, + "public.verification_tokens": { + "name": "verification_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenHash": { + "name": "tokenHash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenPrefix": { + "name": "tokenPrefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "usedAt": { + "name": "usedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_tokens_user_id_idx": { + "name": "verification_tokens_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "verification_tokens_token_hash_idx": { + "name": "verification_tokens_token_hash_idx", + "columns": [ + { + "expression": "tokenHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "verification_tokens_type_idx": { + "name": "verification_tokens_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "verification_tokens_userId_users_id_fk": { + "name": "verification_tokens_userId_users_id_fk", + "tableFrom": "verification_tokens", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "verification_tokens_tokenHash_unique": { + "name": "verification_tokens_tokenHash_unique", + "nullsNotDistinct": false, + "columns": [ + "tokenHash" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "device_id": { + "name": "device_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_version": { + "name": "token_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "admin_role_version": { + "name": "admin_role_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_by_service": { + "name": "created_by_service", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by_ip": { + "name": "created_by_ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_used_ip": { + "name": "last_used_ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_reason": { + "name": "revoked_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sessions_user_id_idx": { + "name": "sessions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sessions_expires_at_idx": { + "name": "sessions_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sessions_user_active_idx": { + "name": "sessions_user_active_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "revoked_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sessions_user_device_idx": { + "name": "sessions_user_device_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "device_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sessions_token_hash_unique": { + "name": "sessions_token_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "token_hash" + ] + } + } + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "toolCalls": { + "name": "toolCalls", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "toolResults": { + "name": "toolResults", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "editedAt": { + "name": "editedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceAgentId": { + "name": "sourceAgentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "messageType": { + "name": "messageType", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'standard'" + } + }, + "indexes": { + "chat_messages_page_id_idx": { + "name": "chat_messages_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_messages_user_id_idx": { + "name": "chat_messages_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_messages_conversation_id_idx": { + "name": "chat_messages_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_messages_page_id_conversation_id_idx": { + "name": "chat_messages_page_id_conversation_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_messages_page_id_is_active_created_at_idx": { + "name": "chat_messages_page_id_is_active_created_at_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isActive", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_messages_pageId_pages_id_fk": { + "name": "chat_messages_pageId_pages_id_fk", + "tableFrom": "chat_messages", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_messages_userId_users_id_fk": { + "name": "chat_messages_userId_users_id_fk", + "tableFrom": "chat_messages", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_messages_sourceAgentId_pages_id_fk": { + "name": "chat_messages_sourceAgentId_pages_id_fk", + "tableFrom": "chat_messages", + "tableTo": "pages", + "columnsFrom": [ + "sourceAgentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.drives": { + "name": "drives", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ownerId": { + "name": "ownerId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isTrashed": { + "name": "isTrashed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trashedAt": { + "name": "trashedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "drivePrompt": { + "name": "drivePrompt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "publishSubdomain": { + "name": "publishSubdomain", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "homePageId": { + "name": "homePageId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drives_owner_id_idx": { + "name": "drives_owner_id_idx", + "columns": [ + { + "expression": "ownerId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drives_owner_id_slug_key": { + "name": "drives_owner_id_slug_key", + "columns": [ + { + "expression": "ownerId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drives_ownerId_users_id_fk": { + "name": "drives_ownerId_users_id_fk", + "tableFrom": "drives", + "tableTo": "users", + "columnsFrom": [ + "ownerId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drives_homePageId_pages_id_fk": { + "name": "drives_homePageId_pages_id_fk", + "tableFrom": "drives", + "tableTo": "pages", + "columnsFrom": [ + "homePageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drives_publishSubdomain_unique": { + "name": "drives_publishSubdomain_unique", + "nullsNotDistinct": false, + "columns": [ + "publishSubdomain" + ] + } + } + }, + "public.favorites": { + "name": "favorites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "itemType": { + "name": "itemType", + "type": "FavoriteItemType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'page'" + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "favorites_user_id_page_id_key": { + "name": "favorites_user_id_page_id_key", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "favorites_user_id_drive_id_key": { + "name": "favorites_user_id_drive_id_key", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "favorites_user_id_position_idx": { + "name": "favorites_user_id_position_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "favorites_userId_users_id_fk": { + "name": "favorites_userId_users_id_fk", + "tableFrom": "favorites", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "favorites_pageId_pages_id_fk": { + "name": "favorites_pageId_pages_id_fk", + "tableFrom": "favorites", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "favorites_driveId_drives_id_fk": { + "name": "favorites_driveId_drives_id_fk", + "tableFrom": "favorites", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mentions": { + "name": "mentions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "sourcePageId": { + "name": "sourcePageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "targetPageId": { + "name": "targetPageId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "mentions_source_page_id_target_page_id_key": { + "name": "mentions_source_page_id_target_page_id_key", + "columns": [ + { + "expression": "sourcePageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "targetPageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mentions_source_page_id_idx": { + "name": "mentions_source_page_id_idx", + "columns": [ + { + "expression": "sourcePageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mentions_target_page_id_idx": { + "name": "mentions_target_page_id_idx", + "columns": [ + { + "expression": "targetPageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mentions_sourcePageId_pages_id_fk": { + "name": "mentions_sourcePageId_pages_id_fk", + "tableFrom": "mentions", + "tableTo": "pages", + "columnsFrom": [ + "sourcePageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mentions_targetPageId_pages_id_fk": { + "name": "mentions_targetPageId_pages_id_fk", + "tableFrom": "mentions", + "tableTo": "pages", + "columnsFrom": [ + "targetPageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.page_tags": { + "name": "page_tags", + "schema": "", + "columns": { + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tagId": { + "name": "tagId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "page_tags_pageId_pages_id_fk": { + "name": "page_tags_pageId_pages_id_fk", + "tableFrom": "page_tags", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_tags_tagId_tags_id_fk": { + "name": "page_tags_tagId_tags_id_fk", + "tableFrom": "page_tags", + "tableTo": "tags", + "columnsFrom": [ + "tagId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "page_tags_pageId_tagId_pk": { + "name": "page_tags_pageId_tagId_pk", + "columns": [ + "pageId", + "tagId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.pages": { + "name": "pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "PageType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "contentMode": { + "name": "contentMode", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'html'" + }, + "isPaginated": { + "name": "isPaginated", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "position": { + "name": "position", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "isTrashed": { + "name": "isTrashed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "aiProvider": { + "name": "aiProvider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "aiModel": { + "name": "aiModel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "systemPrompt": { + "name": "systemPrompt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabledTools": { + "name": "enabledTools", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "includeDrivePrompt": { + "name": "includeDrivePrompt", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "agentDefinition": { + "name": "agentDefinition", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "visibleToGlobalAssistant": { + "name": "visibleToGlobalAssistant", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "includePageTree": { + "name": "includePageTree", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "pageTreeScope": { + "name": "pageTreeScope", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'children'" + }, + "toolExposureMode": { + "name": "toolExposureMode", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'upfront'" + }, + "fileSize": { + "name": "fileSize", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "mimeType": { + "name": "mimeType", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "originalFileName": { + "name": "originalFileName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "filePath": { + "name": "filePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fileMetadata": { + "name": "fileMetadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "processingStatus": { + "name": "processingStatus", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'pending'" + }, + "processingError": { + "name": "processingError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "processedAt": { + "name": "processedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "extractionMethod": { + "name": "extractionMethod", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "extractionMetadata": { + "name": "extractionMetadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "contentHash": { + "name": "contentHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "excludeFromSearch": { + "name": "excludeFromSearch", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "isPrivate": { + "name": "isPrivate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdBy": { + "name": "createdBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "trashedAt": { + "name": "trashedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "stateHash": { + "name": "stateHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parentId": { + "name": "parentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "originalParentId": { + "name": "originalParentId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_drive_id_idx": { + "name": "pages_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_parent_id_idx": { + "name": "pages_parent_id_idx", + "columns": [ + { + "expression": "parentId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_parent_id_position_idx": { + "name": "pages_parent_id_position_idx", + "columns": [ + { + "expression": "parentId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_drive_id_is_trashed_type_idx": { + "name": "pages_drive_id_is_trashed_type_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isTrashed", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_createdBy_users_id_fk": { + "name": "pages_createdBy_users_id_fk", + "tableFrom": "pages", + "tableTo": "users", + "columnsFrom": [ + "createdBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_driveId_drives_id_fk": { + "name": "pages_driveId_drives_id_fk", + "tableFrom": "pages", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.storage_events": { + "name": "storage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "eventType": { + "name": "eventType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sizeDelta": { + "name": "sizeDelta", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "totalSizeAfter": { + "name": "totalSizeAfter", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "storage_events_user_id_idx": { + "name": "storage_events_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "storage_events_created_at_idx": { + "name": "storage_events_created_at_idx", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "storage_events_userId_users_id_fk": { + "name": "storage_events_userId_users_id_fk", + "tableFrom": "storage_events", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "storage_events_pageId_pages_id_fk": { + "name": "storage_events_pageId_pages_id_fk", + "tableFrom": "storage_events", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.tags": { + "name": "tags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "tags_name_unique": { + "name": "tags_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "public.user_mentions": { + "name": "user_mentions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "sourcePageId": { + "name": "sourcePageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "targetUserId": { + "name": "targetUserId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mentionedByUserId": { + "name": "mentionedByUserId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_mentions_source_page_id_target_user_id_key": { + "name": "user_mentions_source_page_id_target_user_id_key", + "columns": [ + { + "expression": "sourcePageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "targetUserId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_mentions_source_page_id_idx": { + "name": "user_mentions_source_page_id_idx", + "columns": [ + { + "expression": "sourcePageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_mentions_target_user_id_idx": { + "name": "user_mentions_target_user_id_idx", + "columns": [ + { + "expression": "targetUserId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_mentions_sourcePageId_pages_id_fk": { + "name": "user_mentions_sourcePageId_pages_id_fk", + "tableFrom": "user_mentions", + "tableTo": "pages", + "columnsFrom": [ + "sourcePageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_mentions_targetUserId_users_id_fk": { + "name": "user_mentions_targetUserId_users_id_fk", + "tableFrom": "user_mentions", + "tableTo": "users", + "columnsFrom": [ + "targetUserId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_mentions_mentionedByUserId_users_id_fk": { + "name": "user_mentions_mentionedByUserId_users_id_fk", + "tableFrom": "user_mentions", + "tableTo": "users", + "columnsFrom": [ + "mentionedByUserId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "action": { + "name": "action", + "type": "PermissionAction", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "subjectType": { + "name": "subjectType", + "type": "SubjectType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "subjectId": { + "name": "subjectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_page_id_idx": { + "name": "permissions_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_subject_id_subject_type_idx": { + "name": "permissions_subject_id_subject_type_idx", + "columns": [ + { + "expression": "subjectId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subjectType", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_page_id_subject_id_subject_type_idx": { + "name": "permissions_page_id_subject_id_subject_type_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subjectId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subjectType", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_pageId_pages_id_fk": { + "name": "permissions_pageId_pages_id_fk", + "tableFrom": "permissions", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.drive_agent_members": { + "name": "drive_agent_members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agentPageId": { + "name": "agentPageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "MemberRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'MEMBER'" + }, + "customRoleId": { + "name": "customRoleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "addedBy": { + "name": "addedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "addedAt": { + "name": "addedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "drive_agent_members_drive_id_idx": { + "name": "drive_agent_members_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_agent_members_agent_page_id_idx": { + "name": "drive_agent_members_agent_page_id_idx", + "columns": [ + { + "expression": "agentPageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_agent_members_driveId_drives_id_fk": { + "name": "drive_agent_members_driveId_drives_id_fk", + "tableFrom": "drive_agent_members", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_agent_members_agentPageId_pages_id_fk": { + "name": "drive_agent_members_agentPageId_pages_id_fk", + "tableFrom": "drive_agent_members", + "tableTo": "pages", + "columnsFrom": [ + "agentPageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_agent_members_customRoleId_drive_roles_id_fk": { + "name": "drive_agent_members_customRoleId_drive_roles_id_fk", + "tableFrom": "drive_agent_members", + "tableTo": "drive_roles", + "columnsFrom": [ + "customRoleId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "drive_agent_members_addedBy_users_id_fk": { + "name": "drive_agent_members_addedBy_users_id_fk", + "tableFrom": "drive_agent_members", + "tableTo": "users", + "columnsFrom": [ + "addedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drive_agent_members_drive_agent_key": { + "name": "drive_agent_members_drive_agent_key", + "nullsNotDistinct": false, + "columns": [ + "driveId", + "agentPageId" + ] + } + } + }, + "public.drive_members": { + "name": "drive_members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "MemberRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'MEMBER'" + }, + "customRoleId": { + "name": "customRoleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "invitedBy": { + "name": "invitedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "invitedAt": { + "name": "invitedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "acceptedAt": { + "name": "acceptedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastAccessedAt": { + "name": "lastAccessedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_members_drive_id_idx": { + "name": "drive_members_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_members_user_id_idx": { + "name": "drive_members_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_members_role_idx": { + "name": "drive_members_role_idx", + "columns": [ + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_members_custom_role_id_idx": { + "name": "drive_members_custom_role_id_idx", + "columns": [ + { + "expression": "customRoleId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_members_driveId_drives_id_fk": { + "name": "drive_members_driveId_drives_id_fk", + "tableFrom": "drive_members", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_members_userId_users_id_fk": { + "name": "drive_members_userId_users_id_fk", + "tableFrom": "drive_members", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_members_customRoleId_drive_roles_id_fk": { + "name": "drive_members_customRoleId_drive_roles_id_fk", + "tableFrom": "drive_members", + "tableTo": "drive_roles", + "columnsFrom": [ + "customRoleId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "drive_members_invitedBy_users_id_fk": { + "name": "drive_members_invitedBy_users_id_fk", + "tableFrom": "drive_members", + "tableTo": "users", + "columnsFrom": [ + "invitedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drive_members_drive_user_key": { + "name": "drive_members_drive_user_key", + "nullsNotDistinct": false, + "columns": [ + "driveId", + "userId" + ] + } + } + }, + "public.drive_roles": { + "name": "drive_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "permissions": { + "name": "permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "drive_wide_permissions": { + "name": "drive_wide_permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "drive_roles_drive_id_idx": { + "name": "drive_roles_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_roles_position_idx": { + "name": "drive_roles_position_idx", + "columns": [ + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_roles_driveId_drives_id_fk": { + "name": "drive_roles_driveId_drives_id_fk", + "tableFrom": "drive_roles", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drive_roles_drive_name_key": { + "name": "drive_roles_drive_name_key", + "nullsNotDistinct": false, + "columns": [ + "driveId", + "name" + ] + } + } + }, + "public.mcp_token_drives": { + "name": "mcp_token_drives", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokenId": { + "name": "tokenId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "MemberRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "customRoleId": { + "name": "customRoleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "addedBy": { + "name": "addedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_token_drives_token_id_idx": { + "name": "mcp_token_drives_token_id_idx", + "columns": [ + { + "expression": "tokenId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_token_drives_drive_id_idx": { + "name": "mcp_token_drives_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_token_drives_token_drive_unique": { + "name": "mcp_token_drives_token_drive_unique", + "columns": [ + { + "expression": "tokenId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_token_drives_tokenId_mcp_tokens_id_fk": { + "name": "mcp_token_drives_tokenId_mcp_tokens_id_fk", + "tableFrom": "mcp_token_drives", + "tableTo": "mcp_tokens", + "columnsFrom": [ + "tokenId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_token_drives_driveId_drives_id_fk": { + "name": "mcp_token_drives_driveId_drives_id_fk", + "tableFrom": "mcp_token_drives", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_token_drives_customRoleId_drive_roles_id_fk": { + "name": "mcp_token_drives_customRoleId_drive_roles_id_fk", + "tableFrom": "mcp_token_drives", + "tableTo": "drive_roles", + "columnsFrom": [ + "customRoleId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "mcp_token_drives_addedBy_users_id_fk": { + "name": "mcp_token_drives_addedBy_users_id_fk", + "tableFrom": "mcp_token_drives", + "tableTo": "users", + "columnsFrom": [ + "addedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.page_permissions": { + "name": "page_permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "canView": { + "name": "canView", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canEdit": { + "name": "canEdit", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canShare": { + "name": "canShare", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDelete": { + "name": "canDelete", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "grantedBy": { + "name": "grantedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "grantedAt": { + "name": "grantedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "page_permissions_page_id_idx": { + "name": "page_permissions_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_permissions_user_id_idx": { + "name": "page_permissions_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_permissions_expires_at_idx": { + "name": "page_permissions_expires_at_idx", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_permissions_pageId_pages_id_fk": { + "name": "page_permissions_pageId_pages_id_fk", + "tableFrom": "page_permissions", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_permissions_userId_users_id_fk": { + "name": "page_permissions_userId_users_id_fk", + "tableFrom": "page_permissions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_permissions_grantedBy_users_id_fk": { + "name": "page_permissions_grantedBy_users_id_fk", + "tableFrom": "page_permissions", + "tableTo": "users", + "columnsFrom": [ + "grantedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "page_permissions_page_user_key": { + "name": "page_permissions_page_user_key", + "nullsNotDistinct": false, + "columns": [ + "pageId", + "userId" + ] + } + } + }, + "public.user_profiles": { + "name": "user_profiles", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "displayName": { + "name": "displayName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatarUrl": { + "name": "avatarUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isPublic": { + "name": "isPublic", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "user_profiles_is_public_idx": { + "name": "user_profiles_is_public_idx", + "columns": [ + { + "expression": "isPublic", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_profiles_userId_users_id_fk": { + "name": "user_profiles_userId_users_id_fk", + "tableFrom": "user_profiles", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.channel_message_reactions": { + "name": "channel_message_reactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "messageId": { + "name": "messageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emoji": { + "name": "emoji", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "unique_reaction_idx": { + "name": "unique_reaction_idx", + "columns": [ + { + "expression": "messageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "emoji", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reaction_message_idx": { + "name": "reaction_message_idx", + "columns": [ + { + "expression": "messageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_message_reactions_messageId_channel_messages_id_fk": { + "name": "channel_message_reactions_messageId_channel_messages_id_fk", + "tableFrom": "channel_message_reactions", + "tableTo": "channel_messages", + "columnsFrom": [ + "messageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_message_reactions_userId_users_id_fk": { + "name": "channel_message_reactions_userId_users_id_fk", + "tableFrom": "channel_message_reactions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.channel_messages": { + "name": "channel_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fileId": { + "name": "fileId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "attachmentMeta": { + "name": "attachmentMeta", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "editedAt": { + "name": "editedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aiMeta": { + "name": "aiMeta", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "parentId": { + "name": "parentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "replyCount": { + "name": "replyCount", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "lastReplyAt": { + "name": "lastReplyAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "mirroredFromId": { + "name": "mirroredFromId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quotedMessageId": { + "name": "quotedMessageId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "channel_messages_page_id_idx": { + "name": "channel_messages_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_messages_file_id_idx": { + "name": "channel_messages_file_id_idx", + "columns": [ + { + "expression": "fileId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_messages_parent_created_idx": { + "name": "channel_messages_parent_created_idx", + "columns": [ + { + "expression": "parentId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_messages_quoted_id_idx": { + "name": "channel_messages_quoted_id_idx", + "columns": [ + { + "expression": "quotedMessageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_messages_pageId_pages_id_fk": { + "name": "channel_messages_pageId_pages_id_fk", + "tableFrom": "channel_messages", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_messages_userId_users_id_fk": { + "name": "channel_messages_userId_users_id_fk", + "tableFrom": "channel_messages", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_messages_fileId_files_id_fk": { + "name": "channel_messages_fileId_files_id_fk", + "tableFrom": "channel_messages", + "tableTo": "files", + "columnsFrom": [ + "fileId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "channel_messages_parentId_channel_messages_id_fk": { + "name": "channel_messages_parentId_channel_messages_id_fk", + "tableFrom": "channel_messages", + "tableTo": "channel_messages", + "columnsFrom": [ + "parentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_messages_mirroredFromId_channel_messages_id_fk": { + "name": "channel_messages_mirroredFromId_channel_messages_id_fk", + "tableFrom": "channel_messages", + "tableTo": "channel_messages", + "columnsFrom": [ + "mirroredFromId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "channel_messages_quotedMessageId_channel_messages_id_fk": { + "name": "channel_messages_quotedMessageId_channel_messages_id_fk", + "tableFrom": "channel_messages", + "tableTo": "channel_messages", + "columnsFrom": [ + "quotedMessageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.channel_read_status": { + "name": "channel_read_status", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channelId": { + "name": "channelId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastReadAt": { + "name": "lastReadAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_read_status_user_id_idx": { + "name": "channel_read_status_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_read_status_channel_id_idx": { + "name": "channel_read_status_channel_id_idx", + "columns": [ + { + "expression": "channelId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_read_status_userId_users_id_fk": { + "name": "channel_read_status_userId_users_id_fk", + "tableFrom": "channel_read_status", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_read_status_channelId_pages_id_fk": { + "name": "channel_read_status_channelId_pages_id_fk", + "tableFrom": "channel_read_status", + "tableTo": "pages", + "columnsFrom": [ + "channelId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_read_status_userId_channelId_pk": { + "name": "channel_read_status_userId_channelId_pk", + "columns": [ + "userId", + "channelId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.channel_thread_followers": { + "name": "channel_thread_followers", + "schema": "", + "columns": { + "rootMessageId": { + "name": "rootMessageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_thread_followers_user_id_idx": { + "name": "channel_thread_followers_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_thread_followers_rootMessageId_channel_messages_id_fk": { + "name": "channel_thread_followers_rootMessageId_channel_messages_id_fk", + "tableFrom": "channel_thread_followers", + "tableTo": "channel_messages", + "columnsFrom": [ + "rootMessageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_thread_followers_userId_users_id_fk": { + "name": "channel_thread_followers_userId_users_id_fk", + "tableFrom": "channel_thread_followers", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_thread_followers_rootMessageId_userId_pk": { + "name": "channel_thread_followers_rootMessageId_userId_pk", + "columns": [ + "rootMessageId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.pulse_summaries": { + "name": "pulse_summaries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "greeting": { + "name": "greeting", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "pulse_summary_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'scheduled'" + }, + "contextData": { + "name": "contextData", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "aiProvider": { + "name": "aiProvider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "aiModel": { + "name": "aiModel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "periodStart": { + "name": "periodStart", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "periodEnd": { + "name": "periodEnd", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "generatedAt": { + "name": "generatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_pulse_summaries_user_id": { + "name": "idx_pulse_summaries_user_id", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_pulse_summaries_generated_at": { + "name": "idx_pulse_summaries_generated_at", + "columns": [ + { + "expression": "generatedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_pulse_summaries_expires_at": { + "name": "idx_pulse_summaries_expires_at", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_pulse_summaries_user_generated": { + "name": "idx_pulse_summaries_user_generated", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "generatedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pulse_summaries_userId_users_id_fk": { + "name": "pulse_summaries_userId_users_id_fk", + "tableFrom": "pulse_summaries", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_dashboards": { + "name": "user_dashboards", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_dashboards_userId_users_id_fk": { + "name": "user_dashboards_userId_users_id_fk", + "tableFrom": "user_dashboards", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_dashboards_userId_unique": { + "name": "user_dashboards_userId_unique", + "nullsNotDistinct": false, + "columns": [ + "userId" + ] + } + } + }, + "public.conversations": { + "name": "conversations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "contextId": { + "name": "contextId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lastMessageAt": { + "name": "lastMessageAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "isShared": { + "name": "isShared", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "conversations_user_id_idx": { + "name": "conversations_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "conversations_user_id_type_idx": { + "name": "conversations_user_id_type_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "conversations_user_id_last_message_at_idx": { + "name": "conversations_user_id_last_message_at_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lastMessageAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "conversations_context_id_idx": { + "name": "conversations_context_id_idx", + "columns": [ + { + "expression": "contextId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "conversations_userId_users_id_fk": { + "name": "conversations_userId_users_id_fk", + "tableFrom": "conversations", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.messages": { + "name": "messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "messageType": { + "name": "messageType", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'standard'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "toolCalls": { + "name": "toolCalls", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "toolResults": { + "name": "toolResults", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "editedAt": { + "name": "editedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "messages_conversation_id_idx": { + "name": "messages_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "messages_conversation_id_created_at_idx": { + "name": "messages_conversation_id_created_at_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "messages_user_id_idx": { + "name": "messages_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "messages_conversationId_conversations_id_fk": { + "name": "messages_conversationId_conversations_id_fk", + "tableFrom": "messages", + "tableTo": "conversations", + "columnsFrom": [ + "conversationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_userId_users_id_fk": { + "name": "messages_userId_users_id_fk", + "tableFrom": "messages", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.notifications": { + "name": "notifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "NotificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "isRead": { + "name": "isRead", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "readAt": { + "name": "readAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "triggeredByUserId": { + "name": "triggeredByUserId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "notifications_user_id_idx": { + "name": "notifications_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "notifications_user_id_is_read_idx": { + "name": "notifications_user_id_is_read_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isRead", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "notifications_user_id_is_read_created_at_idx": { + "name": "notifications_user_id_is_read_created_at_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isRead", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "notifications_created_at_idx": { + "name": "notifications_created_at_idx", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "notifications_type_idx": { + "name": "notifications_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "notifications_userId_users_id_fk": { + "name": "notifications_userId_users_id_fk", + "tableFrom": "notifications", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_pageId_pages_id_fk": { + "name": "notifications_pageId_pages_id_fk", + "tableFrom": "notifications", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_driveId_drives_id_fk": { + "name": "notifications_driveId_drives_id_fk", + "tableFrom": "notifications", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_triggeredByUserId_users_id_fk": { + "name": "notifications_triggeredByUserId_users_id_fk", + "tableFrom": "notifications", + "tableTo": "users", + "columnsFrom": [ + "triggeredByUserId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.email_notification_log": { + "name": "email_notification_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notificationId": { + "name": "notificationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notificationType": { + "name": "notificationType", + "type": "NotificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "recipientEmail": { + "name": "recipientEmail", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "errorMessage": { + "name": "errorMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sentAt": { + "name": "sentAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_notification_log_user_idx": { + "name": "email_notification_log_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "email_notification_log_sent_at_idx": { + "name": "email_notification_log_sent_at_idx", + "columns": [ + { + "expression": "sentAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "email_notification_log_notification_id_idx": { + "name": "email_notification_log_notification_id_idx", + "columns": [ + { + "expression": "notificationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_notification_log_userId_users_id_fk": { + "name": "email_notification_log_userId_users_id_fk", + "tableFrom": "email_notification_log", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.email_notification_preferences": { + "name": "email_notification_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notificationType": { + "name": "notificationType", + "type": "NotificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "emailEnabled": { + "name": "emailEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_notification_preferences_user_type_idx": { + "name": "email_notification_preferences_user_type_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "notificationType", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_notification_preferences_userId_users_id_fk": { + "name": "email_notification_preferences_userId_users_id_fk", + "tableFrom": "email_notification_preferences", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.display_preferences": { + "name": "display_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "preferenceType": { + "name": "preferenceType", + "type": "display_preference_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "display_preferences_user_type_idx": { + "name": "display_preferences_user_type_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "preferenceType", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "display_preferences_userId_users_id_fk": { + "name": "display_preferences_userId_users_id_fk", + "tableFrom": "display_preferences", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.activity_logs": { + "name": "activity_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actorEmail": { + "name": "actorEmail", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'legacy@unknown'" + }, + "actorDisplayName": { + "name": "actorDisplayName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isAiGenerated": { + "name": "isAiGenerated", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "aiProvider": { + "name": "aiProvider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "aiModel": { + "name": "aiModel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "aiConversationId": { + "name": "aiConversationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resourceType": { + "name": "resourceType", + "type": "activity_resource", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resourceId": { + "name": "resourceId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resourceTitle": { + "name": "resourceTitle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contentSnapshot": { + "name": "contentSnapshot", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contentFormat": { + "name": "contentFormat", + "type": "content_format", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "contentRef": { + "name": "contentRef", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contentSize": { + "name": "contentSize", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rollbackFromActivityId": { + "name": "rollbackFromActivityId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rollbackSourceOperation": { + "name": "rollbackSourceOperation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rollbackSourceTimestamp": { + "name": "rollbackSourceTimestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "rollbackSourceTitle": { + "name": "rollbackSourceTitle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updatedFields": { + "name": "updatedFields", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "previousValues": { + "name": "previousValues", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "newValues": { + "name": "newValues", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "streamId": { + "name": "streamId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "streamSeq": { + "name": "streamSeq", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "changeGroupId": { + "name": "changeGroupId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "changeGroupType": { + "name": "changeGroupType", + "type": "activity_change_group_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "stateHashBefore": { + "name": "stateHashBefore", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stateHashAfter": { + "name": "stateHashAfter", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isArchived": { + "name": "isArchived", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "chainSeq": { + "name": "chainSeq", + "type": "bigserial", + "primaryKey": false, + "notNull": true + }, + "previousLogHash": { + "name": "previousLogHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logHash": { + "name": "logHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chainSeed": { + "name": "chainSeed", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_activity_logs_timestamp": { + "name": "idx_activity_logs_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_user_timestamp": { + "name": "idx_activity_logs_user_timestamp", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_drive_timestamp": { + "name": "idx_activity_logs_drive_timestamp", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_page_timestamp": { + "name": "idx_activity_logs_page_timestamp", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_archived": { + "name": "idx_activity_logs_archived", + "columns": [ + { + "expression": "isArchived", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_rollback_from": { + "name": "idx_activity_logs_rollback_from", + "columns": [ + { + "expression": "rollbackFromActivityId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_stream": { + "name": "idx_activity_logs_stream", + "columns": [ + { + "expression": "streamId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "streamSeq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"activity_logs\".\"streamId\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_change_group": { + "name": "idx_activity_logs_change_group", + "columns": [ + { + "expression": "changeGroupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"activity_logs\".\"changeGroupId\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_log_hash": { + "name": "idx_activity_logs_log_hash", + "columns": [ + { + "expression": "logHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"activity_logs\".\"logHash\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_activity_logs_chain_seq": { + "name": "idx_activity_logs_chain_seq", + "columns": [ + { + "expression": "chainSeq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "activity_logs_userId_users_id_fk": { + "name": "activity_logs_userId_users_id_fk", + "tableFrom": "activity_logs", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "activity_logs_driveId_drives_id_fk": { + "name": "activity_logs_driveId_drives_id_fk", + "tableFrom": "activity_logs", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "activity_logs_pageId_pages_id_fk": { + "name": "activity_logs_pageId_pages_id_fk", + "tableFrom": "activity_logs", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.ai_usage_logs": { + "name": "ai_usage_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cost": { + "name": "cost", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "currency": { + "name": "currency", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'USD'" + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "streaming_duration": { + "name": "streaming_duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "context_messages": { + "name": "context_messages", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "context_size": { + "name": "context_size", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "system_prompt_tokens": { + "name": "system_prompt_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "tool_definition_tokens": { + "name": "tool_definition_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "conversation_tokens": { + "name": "conversation_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "message_count": { + "name": "message_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "was_truncated": { + "name": "was_truncated", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "truncation_strategy": { + "name": "truncation_strategy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reconcile_status": { + "name": "reconcile_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reconcile_attempts": { + "name": "reconcile_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reconciled_at": { + "name": "reconciled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_ai_usage_timestamp": { + "name": "idx_ai_usage_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_user_id": { + "name": "idx_ai_usage_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_user_source": { + "name": "idx_ai_usage_user_source", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_provider": { + "name": "idx_ai_usage_provider", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_cost": { + "name": "idx_ai_usage_cost", + "columns": [ + { + "expression": "cost", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_conversation": { + "name": "idx_ai_usage_conversation", + "columns": [ + { + "expression": "conversation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_context": { + "name": "idx_ai_usage_context", + "columns": [ + { + "expression": "conversation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_context_size": { + "name": "idx_ai_usage_context_size", + "columns": [ + { + "expression": "context_size", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_expires_at": { + "name": "idx_ai_usage_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_reconcile": { + "name": "idx_ai_usage_reconcile", + "columns": [ + { + "expression": "reconcile_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "reconcile_status = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.api_metrics": { + "name": "api_metrics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "method": { + "name": "method", + "type": "http_method", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status_code": { + "name": "status_code", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "request_size": { + "name": "request_size", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_size": { + "name": "response_size", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cache_hit": { + "name": "cache_hit", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cache_key": { + "name": "cache_key", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_api_metrics_timestamp": { + "name": "idx_api_metrics_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_api_metrics_endpoint": { + "name": "idx_api_metrics_endpoint", + "columns": [ + { + "expression": "endpoint", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_api_metrics_user_id": { + "name": "idx_api_metrics_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_api_metrics_status": { + "name": "idx_api_metrics_status", + "columns": [ + { + "expression": "status_code", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_api_metrics_duration": { + "name": "idx_api_metrics_duration", + "columns": [ + { + "expression": "duration", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.error_logs": { + "name": "error_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "method": { + "name": "method", + "type": "http_method", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "file": { + "name": "file", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "line": { + "name": "line", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "column": { + "name": "column", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "resolved": { + "name": "resolved", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resolution": { + "name": "resolution", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_errors_timestamp": { + "name": "idx_errors_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_errors_name": { + "name": "idx_errors_name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_errors_user_id": { + "name": "idx_errors_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_errors_resolved": { + "name": "idx_errors_resolved", + "columns": [ + { + "expression": "resolved", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_errors_endpoint": { + "name": "idx_errors_endpoint", + "columns": [ + { + "expression": "endpoint", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.siem_delivery_cursors": { + "name": "siem_delivery_cursors", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "lastDeliveredId": { + "name": "lastDeliveredId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lastDeliveredAt": { + "name": "lastDeliveredAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastError": { + "name": "lastError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lastErrorAt": { + "name": "lastErrorAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deliveryCount": { + "name": "deliveryCount", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.siem_delivery_receipts": { + "name": "siem_delivery_receipts", + "schema": "", + "columns": { + "receiptId": { + "name": "receiptId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "deliveryId": { + "name": "deliveryId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "firstEntryId": { + "name": "firstEntryId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastEntryId": { + "name": "lastEntryId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "firstEntryTimestamp": { + "name": "firstEntryTimestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "lastEntryTimestamp": { + "name": "lastEntryTimestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "entryCount": { + "name": "entryCount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "deliveredAt": { + "name": "deliveredAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "webhookStatus": { + "name": "webhookStatus", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "webhookResponseHash": { + "name": "webhookResponseHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ackReceivedAt": { + "name": "ackReceivedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "siem_delivery_receipts_delivery_source_unique": { + "name": "siem_delivery_receipts_delivery_source_unique", + "columns": [ + { + "expression": "deliveryId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_siem_receipts_delivery_id": { + "name": "idx_siem_receipts_delivery_id", + "columns": [ + { + "expression": "deliveryId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_siem_receipts_first_entry": { + "name": "idx_siem_receipts_first_entry", + "columns": [ + { + "expression": "firstEntryId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_siem_receipts_last_entry": { + "name": "idx_siem_receipts_last_entry", + "columns": [ + { + "expression": "lastEntryId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_siem_receipts_delivered_at": { + "name": "idx_siem_receipts_delivered_at", + "columns": [ + { + "expression": "deliveredAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_siem_receipts_source_range": { + "name": "idx_siem_receipts_source_range", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "firstEntryTimestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lastEntryTimestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.system_logs": { + "name": "system_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "level": { + "name": "level", + "type": "log_level", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "method": { + "name": "method", + "type": "http_method", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_name": { + "name": "error_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_stack": { + "name": "error_stack", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memory_used": { + "name": "memory_used", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memory_total": { + "name": "memory_total", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pid": { + "name": "pid", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_system_logs_timestamp": { + "name": "idx_system_logs_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_system_logs_level": { + "name": "idx_system_logs_level", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_system_logs_category": { + "name": "idx_system_logs_category", + "columns": [ + { + "expression": "category", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_system_logs_user_id": { + "name": "idx_system_logs_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_system_logs_request_id": { + "name": "idx_system_logs_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_system_logs_error": { + "name": "idx_system_logs_error", + "columns": [ + { + "expression": "error_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_activities": { + "name": "user_activities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource": { + "name": "resource", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_user_activities_timestamp": { + "name": "idx_user_activities_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_user_activities_user_id": { + "name": "idx_user_activities_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_user_activities_action": { + "name": "idx_user_activities_action", + "columns": [ + { + "expression": "action", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_user_activities_resource": { + "name": "idx_user_activities_resource", + "columns": [ + { + "expression": "resource", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.drive_backup_files": { + "name": "drive_backup_files", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fileId": { + "name": "fileId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "storagePath": { + "name": "storagePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sizeBytes": { + "name": "sizeBytes", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "mimeType": { + "name": "mimeType", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "checksumVersion": { + "name": "checksumVersion", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backup_files_backup_idx": { + "name": "drive_backup_files_backup_idx", + "columns": [ + { + "expression": "backupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_files_backupId_drive_backups_id_fk": { + "name": "drive_backup_files_backupId_drive_backups_id_fk", + "tableFrom": "drive_backup_files", + "tableTo": "drive_backups", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "drive_backup_files_backupId_fileId_pk": { + "name": "drive_backup_files_backupId_fileId_pk", + "columns": [ + "backupId", + "fileId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.drive_backup_members": { + "name": "drive_backup_members", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customRoleId": { + "name": "customRoleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "invitedBy": { + "name": "invitedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "invitedAt": { + "name": "invitedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "acceptedAt": { + "name": "acceptedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backup_members_backup_idx": { + "name": "drive_backup_members_backup_idx", + "columns": [ + { + "expression": "backupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_members_backupId_drive_backups_id_fk": { + "name": "drive_backup_members_backupId_drive_backups_id_fk", + "tableFrom": "drive_backup_members", + "tableTo": "drive_backups", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "drive_backup_members_backupId_userId_pk": { + "name": "drive_backup_members_backupId_userId_pk", + "columns": [ + "backupId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.drive_backup_pages": { + "name": "drive_backup_pages", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageVersionId": { + "name": "pageVersionId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parentId": { + "name": "parentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "originalParentId": { + "name": "originalParentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "isTrashed": { + "name": "isTrashed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trashedAt": { + "name": "trashedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backup_pages_backup_idx": { + "name": "drive_backup_pages_backup_idx", + "columns": [ + { + "expression": "backupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_pages_backupId_drive_backups_id_fk": { + "name": "drive_backup_pages_backupId_drive_backups_id_fk", + "tableFrom": "drive_backup_pages", + "tableTo": "drive_backups", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_backup_pages_pageVersionId_page_versions_id_fk": { + "name": "drive_backup_pages_pageVersionId_page_versions_id_fk", + "tableFrom": "drive_backup_pages", + "tableTo": "page_versions", + "columnsFrom": [ + "pageVersionId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "drive_backup_pages_backupId_pageId_pk": { + "name": "drive_backup_pages_backupId_pageId_pk", + "columns": [ + "backupId", + "pageId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.drive_backup_permissions": { + "name": "drive_backup_permissions", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "canView": { + "name": "canView", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "canEdit": { + "name": "canEdit", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canShare": { + "name": "canShare", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDelete": { + "name": "canDelete", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "grantedBy": { + "name": "grantedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "note": { + "name": "note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backup_permissions_backup_idx": { + "name": "drive_backup_permissions_backup_idx", + "columns": [ + { + "expression": "backupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_permissions_backupId_drive_backups_id_fk": { + "name": "drive_backup_permissions_backupId_drive_backups_id_fk", + "tableFrom": "drive_backup_permissions", + "tableTo": "drive_backups", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "drive_backup_permissions_backupId_pageId_userId_pk": { + "name": "drive_backup_permissions_backupId_pageId_userId_pk", + "columns": [ + "backupId", + "pageId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.drive_backup_roles": { + "name": "drive_backup_roles", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "roleId": { + "name": "roleId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "permissions": { + "name": "permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "drive_wide_permissions": { + "name": "drive_wide_permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "position": { + "name": "position", + "type": "real", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backup_roles_backup_idx": { + "name": "drive_backup_roles_backup_idx", + "columns": [ + { + "expression": "backupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_roles_backupId_drive_backups_id_fk": { + "name": "drive_backup_roles_backupId_drive_backups_id_fk", + "tableFrom": "drive_backup_roles", + "tableTo": "drive_backups", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "drive_backup_roles_backupId_roleId_pk": { + "name": "drive_backup_roles_backupId_roleId_pk", + "columns": [ + "backupId", + "roleId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.drive_backup_schedules": { + "name": "drive_backup_schedules", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "frequency": { + "name": "frequency", + "type": "drive_backup_schedule_frequency", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'daily'" + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "nextRunAt": { + "name": "nextRunAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastRunAt": { + "name": "lastRunAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "drive_backup_schedules_enabled_next_run_idx": { + "name": "drive_backup_schedules_enabled_next_run_idx", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "nextRunAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backup_schedules_driveId_drives_id_fk": { + "name": "drive_backup_schedules_driveId_drives_id_fk", + "tableFrom": "drive_backup_schedules", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drive_backup_schedules_driveId_unique": { + "name": "drive_backup_schedules_driveId_unique", + "nullsNotDistinct": false, + "columns": [ + "driveId" + ] + } + } + }, + "public.drive_backups": { + "name": "drive_backups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "createdBy": { + "name": "createdBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "drive_backup_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "status": { + "name": "status", + "type": "drive_backup_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "changeGroupId": { + "name": "changeGroupId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "changeGroupType": { + "name": "changeGroupType", + "type": "activity_change_group_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "isPinned": { + "name": "isPinned", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "completedAt": { + "name": "completedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failedAt": { + "name": "failedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failureReason": { + "name": "failureReason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "drive_backups_drive_created_at_idx": { + "name": "drive_backups_drive_created_at_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_backups_status_idx": { + "name": "drive_backups_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_backups_driveId_drives_id_fk": { + "name": "drive_backups_driveId_drives_id_fk", + "tableFrom": "drive_backups", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_backups_createdBy_users_id_fk": { + "name": "drive_backups_createdBy_users_id_fk", + "tableFrom": "drive_backups", + "tableTo": "users", + "columnsFrom": [ + "createdBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.page_versions": { + "name": "page_versions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "createdBy": { + "name": "createdBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "page_version_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'auto'" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "changeGroupId": { + "name": "changeGroupId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "changeGroupType": { + "name": "changeGroupType", + "type": "activity_change_group_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "contentRef": { + "name": "contentRef", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contentFormat": { + "name": "contentFormat", + "type": "content_format", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "contentSize": { + "name": "contentSize", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "stateHash": { + "name": "stateHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pageRevision": { + "name": "pageRevision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "isPinned": { + "name": "isPinned", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "page_versions_page_created_at_idx": { + "name": "page_versions_page_created_at_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_versions_drive_created_at_idx": { + "name": "page_versions_drive_created_at_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_versions_pinned_idx": { + "name": "page_versions_pinned_idx", + "columns": [ + { + "expression": "isPinned", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_versions_page_id_is_pinned_created_at_idx": { + "name": "page_versions_page_id_is_pinned_created_at_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isPinned", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_versions_pageId_pages_id_fk": { + "name": "page_versions_pageId_pages_id_fk", + "tableFrom": "page_versions", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_versions_driveId_drives_id_fk": { + "name": "page_versions_driveId_drives_id_fk", + "tableFrom": "page_versions", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_versions_createdBy_users_id_fk": { + "name": "page_versions_createdBy_users_id_fk", + "tableFrom": "page_versions", + "tableTo": "users", + "columnsFrom": [ + "createdBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user1Id": { + "name": "user1Id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user2Id": { + "name": "user2Id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ConnectionStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "requestedBy": { + "name": "requestedBy", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requestMessage": { + "name": "requestMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "requestedAt": { + "name": "requestedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "acceptedAt": { + "name": "acceptedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "blockedBy": { + "name": "blockedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "blockedAt": { + "name": "blockedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "connections_user1_id_idx": { + "name": "connections_user1_id_idx", + "columns": [ + { + "expression": "user1Id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_user2_id_idx": { + "name": "connections_user2_id_idx", + "columns": [ + { + "expression": "user2Id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_status_idx": { + "name": "connections_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_user1_status_idx": { + "name": "connections_user1_status_idx", + "columns": [ + { + "expression": "user1Id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_user2_status_idx": { + "name": "connections_user2_status_idx", + "columns": [ + { + "expression": "user2Id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "connections_user1Id_users_id_fk": { + "name": "connections_user1Id_users_id_fk", + "tableFrom": "connections", + "tableTo": "users", + "columnsFrom": [ + "user1Id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "connections_user2Id_users_id_fk": { + "name": "connections_user2Id_users_id_fk", + "tableFrom": "connections", + "tableTo": "users", + "columnsFrom": [ + "user2Id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "connections_requestedBy_users_id_fk": { + "name": "connections_requestedBy_users_id_fk", + "tableFrom": "connections", + "tableTo": "users", + "columnsFrom": [ + "requestedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "connections_blockedBy_users_id_fk": { + "name": "connections_blockedBy_users_id_fk", + "tableFrom": "connections", + "tableTo": "users", + "columnsFrom": [ + "blockedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "connections_user_pair_key": { + "name": "connections_user_pair_key", + "nullsNotDistinct": false, + "columns": [ + "user1Id", + "user2Id" + ] + } + } + }, + "public.direct_messages": { + "name": "direct_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "senderId": { + "name": "senderId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fileId": { + "name": "fileId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "attachmentMeta": { + "name": "attachmentMeta", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "isRead": { + "name": "isRead", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "readAt": { + "name": "readAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "isEdited": { + "name": "isEdited", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "editedAt": { + "name": "editedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "parentId": { + "name": "parentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "replyCount": { + "name": "replyCount", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "lastReplyAt": { + "name": "lastReplyAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "mirroredFromId": { + "name": "mirroredFromId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quotedMessageId": { + "name": "quotedMessageId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "direct_messages_conversation_id_idx": { + "name": "direct_messages_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_sender_id_idx": { + "name": "direct_messages_sender_id_idx", + "columns": [ + { + "expression": "senderId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_created_at_idx": { + "name": "direct_messages_created_at_idx", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_file_id_idx": { + "name": "direct_messages_file_id_idx", + "columns": [ + { + "expression": "fileId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_conversation_active_created_idx": { + "name": "direct_messages_conversation_active_created_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isActive", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_inactive_deleted_at_idx": { + "name": "direct_messages_inactive_deleted_at_idx", + "columns": [ + { + "expression": "isActive", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_conversation_created_idx": { + "name": "direct_messages_conversation_created_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_conversation_is_read_idx": { + "name": "direct_messages_conversation_is_read_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isRead", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_unread_count_idx": { + "name": "direct_messages_unread_count_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "senderId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isRead", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_parent_created_idx": { + "name": "direct_messages_parent_created_idx", + "columns": [ + { + "expression": "parentId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "direct_messages_quoted_id_idx": { + "name": "direct_messages_quoted_id_idx", + "columns": [ + { + "expression": "quotedMessageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "direct_messages_conversationId_dm_conversations_id_fk": { + "name": "direct_messages_conversationId_dm_conversations_id_fk", + "tableFrom": "direct_messages", + "tableTo": "dm_conversations", + "columnsFrom": [ + "conversationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "direct_messages_senderId_users_id_fk": { + "name": "direct_messages_senderId_users_id_fk", + "tableFrom": "direct_messages", + "tableTo": "users", + "columnsFrom": [ + "senderId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "direct_messages_fileId_files_id_fk": { + "name": "direct_messages_fileId_files_id_fk", + "tableFrom": "direct_messages", + "tableTo": "files", + "columnsFrom": [ + "fileId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "direct_messages_parentId_direct_messages_id_fk": { + "name": "direct_messages_parentId_direct_messages_id_fk", + "tableFrom": "direct_messages", + "tableTo": "direct_messages", + "columnsFrom": [ + "parentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "direct_messages_mirroredFromId_direct_messages_id_fk": { + "name": "direct_messages_mirroredFromId_direct_messages_id_fk", + "tableFrom": "direct_messages", + "tableTo": "direct_messages", + "columnsFrom": [ + "mirroredFromId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "direct_messages_quotedMessageId_direct_messages_id_fk": { + "name": "direct_messages_quotedMessageId_direct_messages_id_fk", + "tableFrom": "direct_messages", + "tableTo": "direct_messages", + "columnsFrom": [ + "quotedMessageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dm_conversations": { + "name": "dm_conversations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "participant1Id": { + "name": "participant1Id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant2Id": { + "name": "participant2Id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastMessageAt": { + "name": "lastMessageAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastMessagePreview": { + "name": "lastMessagePreview", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "participant1LastRead": { + "name": "participant1LastRead", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "participant2LastRead": { + "name": "participant2LastRead", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "dm_conversations_participant1_id_idx": { + "name": "dm_conversations_participant1_id_idx", + "columns": [ + { + "expression": "participant1Id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "dm_conversations_participant2_id_idx": { + "name": "dm_conversations_participant2_id_idx", + "columns": [ + { + "expression": "participant2Id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "dm_conversations_last_message_at_idx": { + "name": "dm_conversations_last_message_at_idx", + "columns": [ + { + "expression": "lastMessageAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "dm_conversations_participant1_last_message_idx": { + "name": "dm_conversations_participant1_last_message_idx", + "columns": [ + { + "expression": "participant1Id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lastMessageAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "dm_conversations_participant2_last_message_idx": { + "name": "dm_conversations_participant2_last_message_idx", + "columns": [ + { + "expression": "participant2Id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lastMessageAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "dm_conversations_participant1Id_users_id_fk": { + "name": "dm_conversations_participant1Id_users_id_fk", + "tableFrom": "dm_conversations", + "tableTo": "users", + "columnsFrom": [ + "participant1Id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_conversations_participant2Id_users_id_fk": { + "name": "dm_conversations_participant2Id_users_id_fk", + "tableFrom": "dm_conversations", + "tableTo": "users", + "columnsFrom": [ + "participant2Id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "dm_conversations_participant_pair_key": { + "name": "dm_conversations_participant_pair_key", + "nullsNotDistinct": false, + "columns": [ + "participant1Id", + "participant2Id" + ] + } + } + }, + "public.dm_message_reactions": { + "name": "dm_message_reactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "messageId": { + "name": "messageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emoji": { + "name": "emoji", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "dm_unique_reaction_idx": { + "name": "dm_unique_reaction_idx", + "columns": [ + { + "expression": "messageId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "emoji", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "dm_reaction_message_idx": { + "name": "dm_reaction_message_idx", + "columns": [ + { + "expression": "messageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "dm_message_reactions_messageId_direct_messages_id_fk": { + "name": "dm_message_reactions_messageId_direct_messages_id_fk", + "tableFrom": "dm_message_reactions", + "tableTo": "direct_messages", + "columnsFrom": [ + "messageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_message_reactions_userId_users_id_fk": { + "name": "dm_message_reactions_userId_users_id_fk", + "tableFrom": "dm_message_reactions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dm_thread_followers": { + "name": "dm_thread_followers", + "schema": "", + "columns": { + "rootMessageId": { + "name": "rootMessageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "dm_thread_followers_user_id_idx": { + "name": "dm_thread_followers_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "dm_thread_followers_rootMessageId_direct_messages_id_fk": { + "name": "dm_thread_followers_rootMessageId_direct_messages_id_fk", + "tableFrom": "dm_thread_followers", + "tableTo": "direct_messages", + "columnsFrom": [ + "rootMessageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_thread_followers_userId_users_id_fk": { + "name": "dm_thread_followers_userId_users_id_fk", + "tableFrom": "dm_thread_followers", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "dm_thread_followers_rootMessageId_userId_pk": { + "name": "dm_thread_followers_rootMessageId_userId_pk", + "columns": [ + "rootMessageId", + "userId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.stripe_events": { + "name": "stripe_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "processedAt": { + "name": "processedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "stripe_events_type_idx": { + "name": "stripe_events_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "stripe_events_processed_at_idx": { + "name": "stripe_events_processed_at_idx", + "columns": [ + { + "expression": "processedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.subscriptions": { + "name": "subscriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripeSubscriptionId": { + "name": "stripeSubscriptionId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripePriceId": { + "name": "stripePriceId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "currentPeriodStart": { + "name": "currentPeriodStart", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "currentPeriodEnd": { + "name": "currentPeriodEnd", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "cancelAtPeriodEnd": { + "name": "cancelAtPeriodEnd", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "stripeScheduleId": { + "name": "stripeScheduleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scheduledPriceId": { + "name": "scheduledPriceId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scheduledChangeDate": { + "name": "scheduledChangeDate", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "subscriptions_user_id_idx": { + "name": "subscriptions_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "subscriptions_stripe_subscription_id_idx": { + "name": "subscriptions_stripe_subscription_id_idx", + "columns": [ + { + "expression": "stripeSubscriptionId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "subscriptions_stripe_schedule_id_idx": { + "name": "subscriptions_stripe_schedule_id_idx", + "columns": [ + { + "expression": "stripeScheduleId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "subscriptions_userId_users_id_fk": { + "name": "subscriptions_userId_users_id_fk", + "tableFrom": "subscriptions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "subscriptions_stripeSubscriptionId_unique": { + "name": "subscriptions_stripeSubscriptionId_unique", + "nullsNotDistinct": false, + "columns": [ + "stripeSubscriptionId" + ] + } + } + }, + "public.contact_submissions": { + "name": "contact_submissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "resolvedAt": { + "name": "resolvedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "contact_submissions_email_idx": { + "name": "contact_submissions_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "contact_submissions_created_at_idx": { + "name": "contact_submissions_created_at_idx", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.feedback_submissions": { + "name": "feedback_submissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "attachments": { + "name": "attachments", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "page_url": { + "name": "page_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "screen_size": { + "name": "screen_size", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "viewport_size": { + "name": "viewport_size", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "app_version": { + "name": "app_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "console_errors": { + "name": "console_errors", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'new'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "feedback_submissions_user_id_idx": { + "name": "feedback_submissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "feedback_submissions_status_idx": { + "name": "feedback_submissions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "feedback_submissions_created_at_idx": { + "name": "feedback_submissions_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "feedback_submissions_user_id_users_id_fk": { + "name": "feedback_submissions_user_id_users_id_fk", + "tableFrom": "feedback_submissions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.file_conversations": { + "name": "file_conversations", + "schema": "", + "columns": { + "fileId": { + "name": "fileId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "linkedBy": { + "name": "linkedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linkedAt": { + "name": "linkedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "linkSource": { + "name": "linkSource", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "file_conversations_file_id_idx": { + "name": "file_conversations_file_id_idx", + "columns": [ + { + "expression": "fileId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "file_conversations_conversation_id_idx": { + "name": "file_conversations_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "file_conversations_fileId_files_id_fk": { + "name": "file_conversations_fileId_files_id_fk", + "tableFrom": "file_conversations", + "tableTo": "files", + "columnsFrom": [ + "fileId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "file_conversations_conversationId_dm_conversations_id_fk": { + "name": "file_conversations_conversationId_dm_conversations_id_fk", + "tableFrom": "file_conversations", + "tableTo": "dm_conversations", + "columnsFrom": [ + "conversationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "file_conversations_linkedBy_users_id_fk": { + "name": "file_conversations_linkedBy_users_id_fk", + "tableFrom": "file_conversations", + "tableTo": "users", + "columnsFrom": [ + "linkedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "file_conversations_fileId_conversationId_pk": { + "name": "file_conversations_fileId_conversationId_pk", + "columns": [ + "fileId", + "conversationId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.file_pages": { + "name": "file_pages", + "schema": "", + "columns": { + "fileId": { + "name": "fileId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "linkedBy": { + "name": "linkedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linkedAt": { + "name": "linkedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "linkSource": { + "name": "linkSource", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "file_pages_file_id_idx": { + "name": "file_pages_file_id_idx", + "columns": [ + { + "expression": "fileId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "file_pages_page_id_idx": { + "name": "file_pages_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "file_pages_fileId_files_id_fk": { + "name": "file_pages_fileId_files_id_fk", + "tableFrom": "file_pages", + "tableTo": "files", + "columnsFrom": [ + "fileId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "file_pages_pageId_pages_id_fk": { + "name": "file_pages_pageId_pages_id_fk", + "tableFrom": "file_pages", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "file_pages_linkedBy_users_id_fk": { + "name": "file_pages_linkedBy_users_id_fk", + "tableFrom": "file_pages", + "tableTo": "users", + "columnsFrom": [ + "linkedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "file_pages_fileId_pageId_pk": { + "name": "file_pages_fileId_pageId_pk", + "columns": [ + "fileId", + "pageId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.files": { + "name": "files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sizeBytes": { + "name": "sizeBytes", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "mimeType": { + "name": "mimeType", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "storagePath": { + "name": "storagePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "checksumVersion": { + "name": "checksumVersion", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "createdBy": { + "name": "createdBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lastAccessedAt": { + "name": "lastAccessedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "files_drive_id_idx": { + "name": "files_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "files_driveId_drives_id_fk": { + "name": "files_driveId_drives_id_fk", + "tableFrom": "files", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "files_createdBy_users_id_fk": { + "name": "files_createdBy_users_id_fk", + "tableFrom": "files", + "tableTo": "users", + "columnsFrom": [ + "createdBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.task_assignees": { + "name": "task_assignees", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "taskId": { + "name": "taskId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agentPageId": { + "name": "agentPageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_assignees_task_id_idx": { + "name": "task_assignees_task_id_idx", + "columns": [ + { + "expression": "taskId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_assignees_user_id_idx": { + "name": "task_assignees_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_assignees_agent_page_id_idx": { + "name": "task_assignees_agent_page_id_idx", + "columns": [ + { + "expression": "agentPageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_assignees_taskId_task_items_id_fk": { + "name": "task_assignees_taskId_task_items_id_fk", + "tableFrom": "task_assignees", + "tableTo": "task_items", + "columnsFrom": [ + "taskId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_assignees_userId_users_id_fk": { + "name": "task_assignees_userId_users_id_fk", + "tableFrom": "task_assignees", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_assignees_agentPageId_pages_id_fk": { + "name": "task_assignees_agentPageId_pages_id_fk", + "tableFrom": "task_assignees", + "tableTo": "pages", + "columnsFrom": [ + "agentPageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_assignees_task_user": { + "name": "task_assignees_task_user", + "nullsNotDistinct": false, + "columns": [ + "taskId", + "userId" + ] + }, + "task_assignees_task_agent": { + "name": "task_assignees_task_agent", + "nullsNotDistinct": false, + "columns": [ + "taskId", + "agentPageId" + ] + } + } + }, + "public.task_items": { + "name": "task_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "assigneeId": { + "name": "assigneeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "assigneeAgentId": { + "name": "assigneeAgentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "priority": { + "name": "priority", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'medium'" + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "dueDate": { + "name": "dueDate", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "completedAt": { + "name": "completedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_items_assignee_id_idx": { + "name": "task_items_assignee_id_idx", + "columns": [ + { + "expression": "assigneeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_items_assignee_agent_id_idx": { + "name": "task_items_assignee_agent_id_idx", + "columns": [ + { + "expression": "assigneeAgentId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_items_page_id_idx": { + "name": "task_items_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_items_due_date_idx": { + "name": "task_items_due_date_idx", + "columns": [ + { + "expression": "dueDate", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_items_userId_users_id_fk": { + "name": "task_items_userId_users_id_fk", + "tableFrom": "task_items", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_items_assigneeId_users_id_fk": { + "name": "task_items_assigneeId_users_id_fk", + "tableFrom": "task_items", + "tableTo": "users", + "columnsFrom": [ + "assigneeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_items_assigneeAgentId_pages_id_fk": { + "name": "task_items_assigneeAgentId_pages_id_fk", + "tableFrom": "task_items", + "tableTo": "pages", + "columnsFrom": [ + "assigneeAgentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_items_pageId_pages_id_fk": { + "name": "task_items_pageId_pages_id_fk", + "tableFrom": "task_items", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_items_pageId_unique": { + "name": "task_items_pageId_unique", + "nullsNotDistinct": false, + "columns": [ + "pageId" + ] + } + } + }, + "public.task_lists": { + "name": "task_lists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_lists_page_id_idx": { + "name": "task_lists_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_lists_conversation_id_idx": { + "name": "task_lists_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_lists_user_id_idx": { + "name": "task_lists_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_lists_userId_users_id_fk": { + "name": "task_lists_userId_users_id_fk", + "tableFrom": "task_lists", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_lists_pageId_pages_id_fk": { + "name": "task_lists_pageId_pages_id_fk", + "tableFrom": "task_lists", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.task_status_configs": { + "name": "task_status_configs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "taskListId": { + "name": "taskListId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group": { + "name": "group", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_status_configs_task_list_id_idx": { + "name": "task_status_configs_task_list_id_idx", + "columns": [ + { + "expression": "taskListId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_status_configs_taskListId_task_lists_id_fk": { + "name": "task_status_configs_taskListId_task_lists_id_fk", + "tableFrom": "task_status_configs", + "tableTo": "task_lists", + "columnsFrom": [ + "taskListId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_status_configs_task_list_slug": { + "name": "task_status_configs_task_list_slug", + "nullsNotDistinct": false, + "columns": [ + "taskListId", + "slug" + ] + } + } + }, + "public.security_audit_log": { + "name": "security_audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "service_id": { + "name": "service_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "geo_location": { + "name": "geo_location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "risk_score": { + "name": "risk_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "anomaly_flags": { + "name": "anomaly_flags", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "timestamp": { + "name": "timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "chain_seq": { + "name": "chain_seq", + "type": "bigserial", + "primaryKey": false, + "notNull": true + }, + "previous_hash": { + "name": "previous_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_hash": { + "name": "event_hash", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_security_audit_timestamp": { + "name": "idx_security_audit_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_user_timestamp": { + "name": "idx_security_audit_user_timestamp", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_event_type": { + "name": "idx_security_audit_event_type", + "columns": [ + { + "expression": "event_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_resource": { + "name": "idx_security_audit_resource", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_ip": { + "name": "idx_security_audit_ip", + "columns": [ + { + "expression": "ip_address", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_event_hash": { + "name": "idx_security_audit_event_hash", + "columns": [ + { + "expression": "event_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_chain_seq": { + "name": "idx_security_audit_chain_seq", + "columns": [ + { + "expression": "chain_seq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_risk_score": { + "name": "idx_security_audit_risk_score", + "columns": [ + { + "expression": "risk_score", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_security_audit_session": { + "name": "idx_security_audit_session", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "security_audit_log_user_id_users_id_fk": { + "name": "security_audit_log_user_id_users_id_fk", + "tableFrom": "security_audit_log", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_page_views": { + "name": "user_page_views", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "viewedAt": { + "name": "viewedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_page_views_user_id_idx": { + "name": "user_page_views_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_page_views_page_id_idx": { + "name": "user_page_views_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_page_views_user_page_idx": { + "name": "user_page_views_user_page_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_page_views_userId_users_id_fk": { + "name": "user_page_views_userId_users_id_fk", + "tableFrom": "user_page_views", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_page_views_pageId_pages_id_fk": { + "name": "user_page_views_pageId_pages_id_fk", + "tableFrom": "user_page_views", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_page_views_userId_pageId_pk": { + "name": "user_page_views_userId_pageId_pk", + "columns": [ + "userId", + "pageId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.user_hotkey_preferences": { + "name": "user_hotkey_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hotkeyId": { + "name": "hotkeyId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "binding": { + "name": "binding", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_hotkey_preferences_user_hotkey_idx": { + "name": "user_hotkey_preferences_user_hotkey_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "hotkeyId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_hotkey_preferences_user_idx": { + "name": "user_hotkey_preferences_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_hotkey_preferences_userId_users_id_fk": { + "name": "user_hotkey_preferences_userId_users_id_fk", + "tableFrom": "user_hotkey_preferences", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.push_notification_tokens": { + "name": "push_notification_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "platform": { + "name": "platform", + "type": "PushPlatformType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "deviceId": { + "name": "deviceId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deviceName": { + "name": "deviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isActive": { + "name": "isActive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "webPushSubscription": { + "name": "webPushSubscription", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "lastUsedAt": { + "name": "lastUsedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failedAttempts": { + "name": "failedAttempts", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "lastFailedAt": { + "name": "lastFailedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "push_notification_tokens_user_id_idx": { + "name": "push_notification_tokens_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "push_notification_tokens_token_idx": { + "name": "push_notification_tokens_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "push_notification_tokens_platform_idx": { + "name": "push_notification_tokens_platform_idx", + "columns": [ + { + "expression": "platform", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "push_notification_tokens_active_idx": { + "name": "push_notification_tokens_active_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isActive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "push_notification_tokens_userId_users_id_fk": { + "name": "push_notification_tokens_userId_users_id_fk", + "tableFrom": "push_notification_tokens", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.global_assistant_config": { + "name": "global_assistant_config", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled_user_integrations": { + "name": "enabled_user_integrations", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "drive_overrides": { + "name": "drive_overrides", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "inherit_drive_integrations": { + "name": "inherit_drive_integrations", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "global_assistant_config_user_id_users_id_fk": { + "name": "global_assistant_config_user_id_users_id_fk", + "tableFrom": "global_assistant_config", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "global_assistant_config_user_id_unique": { + "name": "global_assistant_config_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + } + }, + "public.integration_audit_log": { + "name": "integration_audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "input_summary": { + "name": "input_summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "response_code": { + "name": "response_code", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "error_type": { + "name": "error_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "integration_audit_log_drive_id_idx": { + "name": "integration_audit_log_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_audit_log_connection_id_idx": { + "name": "integration_audit_log_connection_id_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_audit_log_created_at_idx": { + "name": "integration_audit_log_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_audit_log_drive_created_at_idx": { + "name": "integration_audit_log_drive_created_at_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "integration_audit_log_drive_id_drives_id_fk": { + "name": "integration_audit_log_drive_id_drives_id_fk", + "tableFrom": "integration_audit_log", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_audit_log_agent_id_pages_id_fk": { + "name": "integration_audit_log_agent_id_pages_id_fk", + "tableFrom": "integration_audit_log", + "tableTo": "pages", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "integration_audit_log_user_id_users_id_fk": { + "name": "integration_audit_log_user_id_users_id_fk", + "tableFrom": "integration_audit_log", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "integration_audit_log_connection_id_integration_connections_id_fk": { + "name": "integration_audit_log_connection_id_integration_connections_id_fk", + "tableFrom": "integration_audit_log", + "tableTo": "integration_connections", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.integration_connections": { + "name": "integration_connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "integration_connection_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "status_message": { + "name": "status_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credentials": { + "name": "credentials", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "base_url_override": { + "name": "base_url_override", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config_overrides": { + "name": "config_overrides", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "account_metadata": { + "name": "account_metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "visibility": { + "name": "visibility", + "type": "integration_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'owned_drives'" + }, + "oauth_state": { + "name": "oauth_state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connected_by": { + "name": "connected_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connected_at": { + "name": "connected_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_health_check": { + "name": "last_health_check", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "integration_connections_provider_id_idx": { + "name": "integration_connections_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_connections_user_id_idx": { + "name": "integration_connections_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_connections_drive_id_idx": { + "name": "integration_connections_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "integration_connections_provider_id_integration_providers_id_fk": { + "name": "integration_connections_provider_id_integration_providers_id_fk", + "tableFrom": "integration_connections", + "tableTo": "integration_providers", + "columnsFrom": [ + "provider_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_connections_user_id_users_id_fk": { + "name": "integration_connections_user_id_users_id_fk", + "tableFrom": "integration_connections", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_connections_drive_id_drives_id_fk": { + "name": "integration_connections_drive_id_drives_id_fk", + "tableFrom": "integration_connections", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_connections_connected_by_users_id_fk": { + "name": "integration_connections_connected_by_users_id_fk", + "tableFrom": "integration_connections", + "tableTo": "users", + "columnsFrom": [ + "connected_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "integration_connections_user_provider": { + "name": "integration_connections_user_provider", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "provider_id" + ] + }, + "integration_connections_drive_provider": { + "name": "integration_connections_drive_provider", + "nullsNotDistinct": false, + "columns": [ + "drive_id", + "provider_id" + ] + } + } + }, + "public.integration_providers": { + "name": "integration_providers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon_url": { + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "documentation_url": { + "name": "documentation_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_type": { + "name": "provider_type", + "type": "integration_provider_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "openapi_spec": { + "name": "openapi_spec", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_system": { + "name": "is_system", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "integration_providers_slug_idx": { + "name": "integration_providers_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_providers_drive_id_idx": { + "name": "integration_providers_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "integration_providers_created_by_users_id_fk": { + "name": "integration_providers_created_by_users_id_fk", + "tableFrom": "integration_providers", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "integration_providers_drive_id_drives_id_fk": { + "name": "integration_providers_drive_id_drives_id_fk", + "tableFrom": "integration_providers", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "integration_providers_slug_unique": { + "name": "integration_providers_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + } + }, + "public.integration_tool_grants": { + "name": "integration_tool_grants", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allowed_tools": { + "name": "allowed_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "denied_tools": { + "name": "denied_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "read_only": { + "name": "read_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "rate_limit_override": { + "name": "rate_limit_override", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "integration_tool_grants_agent_id_idx": { + "name": "integration_tool_grants_agent_id_idx", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_tool_grants_connection_id_idx": { + "name": "integration_tool_grants_connection_id_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "integration_tool_grants_agent_id_pages_id_fk": { + "name": "integration_tool_grants_agent_id_pages_id_fk", + "tableFrom": "integration_tool_grants", + "tableTo": "pages", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_tool_grants_connection_id_integration_connections_id_fk": { + "name": "integration_tool_grants_connection_id_integration_connections_id_fk", + "tableFrom": "integration_tool_grants", + "tableTo": "integration_connections", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "integration_tool_grants_agent_connection": { + "name": "integration_tool_grants_agent_connection", + "nullsNotDistinct": false, + "columns": [ + "agent_id", + "connection_id" + ] + } + } + }, + "public.user_personalization": { + "name": "user_personalization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "writingStyle": { + "name": "writingStyle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rules": { + "name": "rules", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_personalization_user_idx": { + "name": "user_personalization_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_personalization_userId_users_id_fk": { + "name": "user_personalization_userId_users_id_fk", + "tableFrom": "user_personalization", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_automation_preferences": { + "name": "user_automation_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pulseEnabled": { + "name": "pulseEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_automation_preferences_user_idx": { + "name": "user_automation_preferences_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_automation_preferences_userId_users_id_fk": { + "name": "user_automation_preferences_userId_users_id_fk", + "tableFrom": "user_automation_preferences", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.calendar_event_drives": { + "name": "calendar_event_drives", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "eventId": { + "name": "eventId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sharedBy": { + "name": "sharedBy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sharedAt": { + "name": "sharedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "calendar_event_drives_event_id_idx": { + "name": "calendar_event_drives_event_id_idx", + "columns": [ + { + "expression": "eventId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_event_drives_drive_id_idx": { + "name": "calendar_event_drives_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "calendar_event_drives_eventId_calendar_events_id_fk": { + "name": "calendar_event_drives_eventId_calendar_events_id_fk", + "tableFrom": "calendar_event_drives", + "tableTo": "calendar_events", + "columnsFrom": [ + "eventId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_event_drives_driveId_drives_id_fk": { + "name": "calendar_event_drives_driveId_drives_id_fk", + "tableFrom": "calendar_event_drives", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_event_drives_sharedBy_users_id_fk": { + "name": "calendar_event_drives_sharedBy_users_id_fk", + "tableFrom": "calendar_event_drives", + "tableTo": "users", + "columnsFrom": [ + "sharedBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "calendar_event_drives_event_drive_key": { + "name": "calendar_event_drives_event_drive_key", + "nullsNotDistinct": false, + "columns": [ + "eventId", + "driveId" + ] + } + } + }, + "public.calendar_events": { + "name": "calendar_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdById": { + "name": "createdById", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pageId": { + "name": "pageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "startAt": { + "name": "startAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "endAt": { + "name": "endAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "allDay": { + "name": "allDay", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "recurrenceRule": { + "name": "recurrenceRule", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "recurrenceExceptions": { + "name": "recurrenceExceptions", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "recurringEventId": { + "name": "recurringEventId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "originalStartAt": { + "name": "originalStartAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "visibility": { + "name": "visibility", + "type": "EventVisibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRIVE'" + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'default'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "isTrashed": { + "name": "isTrashed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trashedAt": { + "name": "trashedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "googleEventId": { + "name": "googleEventId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "googleCalendarId": { + "name": "googleCalendarId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "syncedFromGoogle": { + "name": "syncedFromGoogle", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "lastGoogleSync": { + "name": "lastGoogleSync", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "googleSyncReadOnly": { + "name": "googleSyncReadOnly", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "calendar_events_drive_id_idx": { + "name": "calendar_events_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_created_by_id_idx": { + "name": "calendar_events_created_by_id_idx", + "columns": [ + { + "expression": "createdById", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_page_id_idx": { + "name": "calendar_events_page_id_idx", + "columns": [ + { + "expression": "pageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_start_at_idx": { + "name": "calendar_events_start_at_idx", + "columns": [ + { + "expression": "startAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_end_at_idx": { + "name": "calendar_events_end_at_idx", + "columns": [ + { + "expression": "endAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_drive_id_start_at_idx": { + "name": "calendar_events_drive_id_start_at_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "startAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_recurring_event_id_idx": { + "name": "calendar_events_recurring_event_id_idx", + "columns": [ + { + "expression": "recurringEventId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_is_trashed_idx": { + "name": "calendar_events_is_trashed_idx", + "columns": [ + { + "expression": "isTrashed", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_google_event_id_idx": { + "name": "calendar_events_google_event_id_idx", + "columns": [ + { + "expression": "googleEventId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_events_synced_from_google_idx": { + "name": "calendar_events_synced_from_google_idx", + "columns": [ + { + "expression": "syncedFromGoogle", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "calendar_events_driveId_drives_id_fk": { + "name": "calendar_events_driveId_drives_id_fk", + "tableFrom": "calendar_events", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_events_createdById_users_id_fk": { + "name": "calendar_events_createdById_users_id_fk", + "tableFrom": "calendar_events", + "tableTo": "users", + "columnsFrom": [ + "createdById" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_events_pageId_pages_id_fk": { + "name": "calendar_events_pageId_pages_id_fk", + "tableFrom": "calendar_events", + "tableTo": "pages", + "columnsFrom": [ + "pageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "calendar_events_google_source_per_user_key": { + "name": "calendar_events_google_source_per_user_key", + "nullsNotDistinct": false, + "columns": [ + "createdById", + "googleCalendarId", + "googleEventId" + ] + } + } + }, + "public.event_attendees": { + "name": "event_attendees", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "eventId": { + "name": "eventId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "AttendeeStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "responseNote": { + "name": "responseNote", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isOrganizer": { + "name": "isOrganizer", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "isOptional": { + "name": "isOptional", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "invitedAt": { + "name": "invitedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "respondedAt": { + "name": "respondedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "event_attendees_event_id_idx": { + "name": "event_attendees_event_id_idx", + "columns": [ + { + "expression": "eventId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "event_attendees_user_id_idx": { + "name": "event_attendees_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "event_attendees_status_idx": { + "name": "event_attendees_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "event_attendees_user_id_status_idx": { + "name": "event_attendees_user_id_status_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "event_attendees_eventId_calendar_events_id_fk": { + "name": "event_attendees_eventId_calendar_events_id_fk", + "tableFrom": "event_attendees", + "tableTo": "calendar_events", + "columnsFrom": [ + "eventId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_attendees_userId_users_id_fk": { + "name": "event_attendees_userId_users_id_fk", + "tableFrom": "event_attendees", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "event_attendees_event_user_key": { + "name": "event_attendees_event_user_key", + "nullsNotDistinct": false, + "columns": [ + "eventId", + "userId" + ] + } + } + }, + "public.google_calendar_connections": { + "name": "google_calendar_connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessToken": { + "name": "accessToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tokenExpiresAt": { + "name": "tokenExpiresAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "googleEmail": { + "name": "googleEmail", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "googleAccountId": { + "name": "googleAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "GoogleCalendarConnectionStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "statusMessage": { + "name": "statusMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "targetDriveId": { + "name": "targetDriveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selectedCalendars": { + "name": "selectedCalendars", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "syncFrequencyMinutes": { + "name": "syncFrequencyMinutes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 15 + }, + "markAsReadOnly": { + "name": "markAsReadOnly", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "lastSyncAt": { + "name": "lastSyncAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "lastSyncError": { + "name": "lastSyncError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "syncCursor": { + "name": "syncCursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "webhookChannels": { + "name": "webhookChannels", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "google_calendar_connections_user_id_idx": { + "name": "google_calendar_connections_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "google_calendar_connections_status_idx": { + "name": "google_calendar_connections_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "google_calendar_connections_target_drive_id_idx": { + "name": "google_calendar_connections_target_drive_id_idx", + "columns": [ + { + "expression": "targetDriveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "google_calendar_connections_userId_users_id_fk": { + "name": "google_calendar_connections_userId_users_id_fk", + "tableFrom": "google_calendar_connections", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "google_calendar_connections_targetDriveId_drives_id_fk": { + "name": "google_calendar_connections_targetDriveId_drives_id_fk", + "tableFrom": "google_calendar_connections", + "tableTo": "drives", + "columnsFrom": [ + "targetDriveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "google_calendar_connections_userId_unique": { + "name": "google_calendar_connections_userId_unique", + "nullsNotDistinct": false, + "columns": [ + "userId" + ] + } + } + }, + "public.calendar_triggers": { + "name": "calendar_triggers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflowId": { + "name": "workflowId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "calendarEventId": { + "name": "calendarEventId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scheduledById": { + "name": "scheduledById", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "triggerAt": { + "name": "triggerAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "occurrenceDate": { + "name": "occurrenceDate", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "'1970-01-01T00:00:00.000Z'" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "calendar_triggers_trigger_at_idx": { + "name": "calendar_triggers_trigger_at_idx", + "columns": [ + { + "expression": "triggerAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_triggers_scheduled_by_idx": { + "name": "calendar_triggers_scheduled_by_idx", + "columns": [ + { + "expression": "scheduledById", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_triggers_calendar_event_idx": { + "name": "calendar_triggers_calendar_event_idx", + "columns": [ + { + "expression": "calendarEventId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "calendar_triggers_workflow_id_idx": { + "name": "calendar_triggers_workflow_id_idx", + "columns": [ + { + "expression": "workflowId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "calendar_triggers_workflowId_workflows_id_fk": { + "name": "calendar_triggers_workflowId_workflows_id_fk", + "tableFrom": "calendar_triggers", + "tableTo": "workflows", + "columnsFrom": [ + "workflowId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_triggers_calendarEventId_calendar_events_id_fk": { + "name": "calendar_triggers_calendarEventId_calendar_events_id_fk", + "tableFrom": "calendar_triggers", + "tableTo": "calendar_events", + "columnsFrom": [ + "calendarEventId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_triggers_driveId_drives_id_fk": { + "name": "calendar_triggers_driveId_drives_id_fk", + "tableFrom": "calendar_triggers", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "calendar_triggers_scheduledById_users_id_fk": { + "name": "calendar_triggers_scheduledById_users_id_fk", + "tableFrom": "calendar_triggers", + "tableTo": "users", + "columnsFrom": [ + "scheduledById" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "calendar_triggers_event_occurrence_key": { + "name": "calendar_triggers_event_occurrence_key", + "nullsNotDistinct": false, + "columns": [ + "calendarEventId", + "occurrenceDate" + ] + } + } + }, + "public.workflows": { + "name": "workflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdBy": { + "name": "createdBy", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agentPageId": { + "name": "agentPageId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "contextPageIds": { + "name": "contextPageIds", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "cronExpression": { + "name": "cronExpression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "triggerType": { + "name": "triggerType", + "type": "WorkflowTriggerType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cron'" + }, + "eventTriggers": { + "name": "eventTriggers", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "watchedFolderIds": { + "name": "watchedFolderIds", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "eventDebounceSecs": { + "name": "eventDebounceSecs", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30 + }, + "instructionPageId": { + "name": "instructionPageId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isEnabled": { + "name": "isEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "nextRunAt": { + "name": "nextRunAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "workflows_drive_id_idx": { + "name": "workflows_drive_id_idx", + "columns": [ + { + "expression": "driveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflows_created_by_idx": { + "name": "workflows_created_by_idx", + "columns": [ + { + "expression": "createdBy", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflows_agent_page_id_idx": { + "name": "workflows_agent_page_id_idx", + "columns": [ + { + "expression": "agentPageId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflows_enabled_next_run_idx": { + "name": "workflows_enabled_next_run_idx", + "columns": [ + { + "expression": "isEnabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "nextRunAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflows_enabled_trigger_type_idx": { + "name": "workflows_enabled_trigger_type_idx", + "columns": [ + { + "expression": "isEnabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "triggerType", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflows_driveId_drives_id_fk": { + "name": "workflows_driveId_drives_id_fk", + "tableFrom": "workflows", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflows_createdBy_users_id_fk": { + "name": "workflows_createdBy_users_id_fk", + "tableFrom": "workflows", + "tableTo": "users", + "columnsFrom": [ + "createdBy" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflows_agentPageId_pages_id_fk": { + "name": "workflows_agentPageId_pages_id_fk", + "tableFrom": "workflows", + "tableTo": "pages", + "columnsFrom": [ + "agentPageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflows_instructionPageId_pages_id_fk": { + "name": "workflows_instructionPageId_pages_id_fk", + "tableFrom": "workflows", + "tableTo": "pages", + "columnsFrom": [ + "instructionPageId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.workflow_runs": { + "name": "workflow_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflowId": { + "name": "workflowId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sourceTable": { + "name": "sourceTable", + "type": "WorkflowRunSourceTable", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "sourceId": { + "name": "sourceId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "triggerAt": { + "name": "triggerAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "startedAt": { + "name": "startedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "endedAt": { + "name": "endedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "WorkflowRunStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "durationMs": { + "name": "durationMs", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_runs_workflow_started_at_idx": { + "name": "workflow_runs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflowId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "startedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_runs_source_lookup_idx": { + "name": "workflow_runs_source_lookup_idx", + "columns": [ + { + "expression": "sourceTable", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sourceId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_runs_stuck_run_idx": { + "name": "workflow_runs_stuck_run_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "startedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_runs_running_claim_idx": { + "name": "workflow_runs_running_claim_idx", + "columns": [ + { + "expression": "workflowId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_runs\".\"status\" = 'running'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_runs_workflowId_workflows_id_fk": { + "name": "workflow_runs_workflowId_workflows_id_fk", + "tableFrom": "workflow_runs", + "tableTo": "workflows", + "columnsFrom": [ + "workflowId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.task_triggers": { + "name": "task_triggers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflowId": { + "name": "workflowId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "taskItemId": { + "name": "taskItemId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "triggerType": { + "name": "triggerType", + "type": "TaskTriggerType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "nextRunAt": { + "name": "nextRunAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastFiredAt": { + "name": "lastFiredAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastFireError": { + "name": "lastFireError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isEnabled": { + "name": "isEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "task_triggers_workflow_id_idx": { + "name": "task_triggers_workflow_id_idx", + "columns": [ + { + "expression": "workflowId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_triggers_task_item_id_idx": { + "name": "task_triggers_task_item_id_idx", + "columns": [ + { + "expression": "taskItemId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_triggers_enabled_next_run_idx": { + "name": "task_triggers_enabled_next_run_idx", + "columns": [ + { + "expression": "isEnabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "nextRunAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_triggers_workflowId_workflows_id_fk": { + "name": "task_triggers_workflowId_workflows_id_fk", + "tableFrom": "task_triggers", + "tableTo": "workflows", + "columnsFrom": [ + "workflowId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_triggers_taskItemId_task_items_id_fk": { + "name": "task_triggers_taskItemId_task_items_id_fk", + "tableFrom": "task_triggers", + "tableTo": "task_items", + "columnsFrom": [ + "taskItemId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_triggers_task_item_trigger_type_key": { + "name": "task_triggers_task_item_trigger_type_key", + "nullsNotDistinct": false, + "columns": [ + "taskItemId", + "triggerType" + ] + } + } + }, + "public.rate_limit_buckets": { + "name": "rate_limit_buckets", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "window_start": { + "name": "window_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "rate_limit_buckets_expires_at_idx": { + "name": "rate_limit_buckets_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "rate_limit_buckets_key_window_start_pk": { + "name": "rate_limit_buckets_key_window_start_pk", + "columns": [ + "key", + "window_start" + ] + } + }, + "uniqueConstraints": {} + }, + "public.revoked_service_tokens": { + "name": "revoked_service_tokens", + "schema": "", + "columns": { + "jti": { + "name": "jti", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "revoked_service_tokens_expires_at_idx": { + "name": "revoked_service_tokens_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.auth_handoff_tokens": { + "name": "auth_handoff_tokens", + "schema": "", + "columns": { + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "auth_handoff_tokens_expires_at_idx": { + "name": "auth_handoff_tokens_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "auth_handoff_tokens_kind_expires_at_idx": { + "name": "auth_handoff_tokens_kind_expires_at_idx", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "auth_handoff_tokens_token_hash_kind_pk": { + "name": "auth_handoff_tokens_token_hash_kind_pk", + "columns": [ + "token_hash", + "kind" + ] + } + }, + "uniqueConstraints": {} + }, + "public.pending_invites": { + "name": "pending_invites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "MemberRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "custom_role_id": { + "name": "custom_role_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pending_invites_drive_id_idx": { + "name": "pending_invites_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_invites_email_idx": { + "name": "pending_invites_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_invites_expires_at_idx": { + "name": "pending_invites_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_invites_custom_role_id_idx": { + "name": "pending_invites_custom_role_id_idx", + "columns": [ + { + "expression": "custom_role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_invites_active_drive_email_idx": { + "name": "pending_invites_active_drive_email_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"pending_invites\".\"consumed_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pending_invites_drive_id_drives_id_fk": { + "name": "pending_invites_drive_id_drives_id_fk", + "tableFrom": "pending_invites", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pending_invites_custom_role_id_drive_roles_id_fk": { + "name": "pending_invites_custom_role_id_drive_roles_id_fk", + "tableFrom": "pending_invites", + "tableTo": "drive_roles", + "columnsFrom": [ + "custom_role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pending_invites_invited_by_users_id_fk": { + "name": "pending_invites_invited_by_users_id_fk", + "tableFrom": "pending_invites", + "tableTo": "users", + "columnsFrom": [ + "invited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pending_invites_token_hash_unique": { + "name": "pending_invites_token_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "token_hash" + ] + } + } + }, + "public.pending_page_invites": { + "name": "pending_page_invites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pending_page_invites_page_id_idx": { + "name": "pending_page_invites_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_page_invites_email_idx": { + "name": "pending_page_invites_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_page_invites_expires_at_idx": { + "name": "pending_page_invites_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_page_invites_active_page_email_idx": { + "name": "pending_page_invites_active_page_email_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"pending_page_invites\".\"consumed_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pending_page_invites_invited_by_users_id_fk": { + "name": "pending_page_invites_invited_by_users_id_fk", + "tableFrom": "pending_page_invites", + "tableTo": "users", + "columnsFrom": [ + "invited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pending_page_invites_page_id_pages_id_fk": { + "name": "pending_page_invites_page_id_pages_id_fk", + "tableFrom": "pending_page_invites", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pending_page_invites_token_hash_unique": { + "name": "pending_page_invites_token_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "token_hash" + ] + } + } + }, + "public.pending_connection_invites": { + "name": "pending_connection_invites", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "request_message": { + "name": "request_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pending_connection_invites_invited_by_idx": { + "name": "pending_connection_invites_invited_by_idx", + "columns": [ + { + "expression": "invited_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_connection_invites_email_idx": { + "name": "pending_connection_invites_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_connection_invites_expires_at_idx": { + "name": "pending_connection_invites_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_connection_invites_active_inviter_email_idx": { + "name": "pending_connection_invites_active_inviter_email_idx", + "columns": [ + { + "expression": "invited_by", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"pending_connection_invites\".\"consumed_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pending_connection_invites_invited_by_users_id_fk": { + "name": "pending_connection_invites_invited_by_users_id_fk", + "tableFrom": "pending_connection_invites", + "tableTo": "users", + "columnsFrom": [ + "invited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pending_connection_invites_token_hash_unique": { + "name": "pending_connection_invites_token_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "token_hash" + ] + } + } + }, + "public.ai_stream_sessions": { + "name": "ai_stream_sessions", + "schema": "", + "columns": { + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Someone'" + }, + "browser_session_id": { + "name": "browser_session_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'streaming'" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "ai_stream_sessions_channel_status_idx": { + "name": "ai_stream_sessions_channel_status_idx", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.drive_share_links": { + "name": "drive_share_links", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "MemberRole", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'MEMBER'" + }, + "custom_role_id": { + "name": "custom_role_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "use_count": { + "name": "use_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": { + "drive_share_links_drive_id_idx": { + "name": "drive_share_links_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_share_links_expires_at_idx": { + "name": "drive_share_links_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_share_links_is_active_idx": { + "name": "drive_share_links_is_active_idx", + "columns": [ + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "drive_share_links_custom_role_id_idx": { + "name": "drive_share_links_custom_role_id_idx", + "columns": [ + { + "expression": "custom_role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "drive_share_links_drive_id_drives_id_fk": { + "name": "drive_share_links_drive_id_drives_id_fk", + "tableFrom": "drive_share_links", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "drive_share_links_custom_role_id_drive_roles_id_fk": { + "name": "drive_share_links_custom_role_id_drive_roles_id_fk", + "tableFrom": "drive_share_links", + "tableTo": "drive_roles", + "columnsFrom": [ + "custom_role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "drive_share_links_created_by_users_id_fk": { + "name": "drive_share_links_created_by_users_id_fk", + "tableFrom": "drive_share_links", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "drive_share_links_token_unique": { + "name": "drive_share_links_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "public.page_share_links": { + "name": "page_share_links", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "use_count": { + "name": "use_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": { + "page_share_links_page_id_idx": { + "name": "page_share_links_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_share_links_expires_at_idx": { + "name": "page_share_links_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_share_links_is_active_idx": { + "name": "page_share_links_is_active_idx", + "columns": [ + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_share_links_page_id_pages_id_fk": { + "name": "page_share_links_page_id_pages_id_fk", + "tableFrom": "page_share_links", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_share_links_created_by_users_id_fk": { + "name": "page_share_links_created_by_users_id_fk", + "tableFrom": "page_share_links", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "page_share_links_token_unique": { + "name": "page_share_links_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "public.zoom_connections": { + "name": "zoom_connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessToken": { + "name": "accessToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tokenExpiresAt": { + "name": "tokenExpiresAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "zoomUserId": { + "name": "zoomUserId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "zoomAccountId": { + "name": "zoomAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "zoomEmail": { + "name": "zoomEmail", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ZoomConnectionStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "targetDriveId": { + "name": "targetDriveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "targetFolderId": { + "name": "targetFolderId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scopeVersion": { + "name": "scopeVersion", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "includeAiSummary": { + "name": "includeAiSummary", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "includeActionItems": { + "name": "includeActionItems", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "includeTranscript": { + "name": "includeTranscript", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "zoom_connections_user_id_idx": { + "name": "zoom_connections_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "zoom_connections_status_idx": { + "name": "zoom_connections_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "zoom_connections_account_id_idx": { + "name": "zoom_connections_account_id_idx", + "columns": [ + { + "expression": "zoomAccountId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "zoom_connections_target_drive_id_idx": { + "name": "zoom_connections_target_drive_id_idx", + "columns": [ + { + "expression": "targetDriveId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "zoom_connections_userId_users_id_fk": { + "name": "zoom_connections_userId_users_id_fk", + "tableFrom": "zoom_connections", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "zoom_connections_targetDriveId_drives_id_fk": { + "name": "zoom_connections_targetDriveId_drives_id_fk", + "tableFrom": "zoom_connections", + "tableTo": "drives", + "columnsFrom": [ + "targetDriveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "zoom_connections_userId_unique": { + "name": "zoom_connections_userId_unique", + "nullsNotDistinct": false, + "columns": [ + "userId" + ] + } + } + }, + "public.webhook_triggers": { + "name": "webhook_triggers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflowId": { + "name": "workflowId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connectionId": { + "name": "connectionId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "eventType": { + "name": "eventType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isEnabled": { + "name": "isEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "lastFiredAt": { + "name": "lastFiredAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "lastFireError": { + "name": "lastFireError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "webhook_triggers_workflow_id_idx": { + "name": "webhook_triggers_workflow_id_idx", + "columns": [ + { + "expression": "workflowId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_triggers_provider_event_idx": { + "name": "webhook_triggers_provider_event_idx", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "eventType", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "isEnabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_triggers_connection_id_idx": { + "name": "webhook_triggers_connection_id_idx", + "columns": [ + { + "expression": "connectionId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_triggers_workflowId_workflows_id_fk": { + "name": "webhook_triggers_workflowId_workflows_id_fk", + "tableFrom": "webhook_triggers", + "tableTo": "workflows", + "columnsFrom": [ + "workflowId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_triggers_connectionId_zoom_connections_id_fk": { + "name": "webhook_triggers_connectionId_zoom_connections_id_fk", + "tableFrom": "webhook_triggers", + "tableTo": "zoom_connections", + "columnsFrom": [ + "connectionId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "webhook_triggers_connection_workflow_event_unique": { + "name": "webhook_triggers_connection_workflow_event_unique", + "nullsNotDistinct": false, + "columns": [ + "connectionId", + "workflowId", + "eventType" + ] + } + } + }, + "public.message_drafts": { + "name": "message_drafts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "contextKey": { + "name": "contextKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "message_drafts_user_context_key": { + "name": "message_drafts_user_context_key", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "contextKey", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "message_drafts_expires_at_idx": { + "name": "message_drafts_expires_at_idx", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "message_drafts_userId_users_id_fk": { + "name": "message_drafts_userId_users_id_fk", + "tableFrom": "message_drafts", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.sandbox_sessions": { + "name": "sandbox_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "sessionKey": { + "name": "sessionKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversationId": { + "name": "conversationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "driveId": { + "name": "driveId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tenantId": { + "name": "tenantId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sandboxId": { + "name": "sandboxId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastActiveAt": { + "name": "lastActiveAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "sandbox_sessions_conversation_id_idx": { + "name": "sandbox_sessions_conversation_id_idx", + "columns": [ + { + "expression": "conversationId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sandbox_sessions_last_active_at_idx": { + "name": "sandbox_sessions_last_active_at_idx", + "columns": [ + { + "expression": "lastActiveAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sandbox_sessions_conversationId_conversations_id_fk": { + "name": "sandbox_sessions_conversationId_conversations_id_fk", + "tableFrom": "sandbox_sessions", + "tableTo": "conversations", + "columnsFrom": [ + "conversationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sandbox_sessions_driveId_drives_id_fk": { + "name": "sandbox_sessions_driveId_drives_id_fk", + "tableFrom": "sandbox_sessions", + "tableTo": "drives", + "columnsFrom": [ + "driveId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sandbox_sessions_userId_users_id_fk": { + "name": "sandbox_sessions_userId_users_id_fk", + "tableFrom": "sandbox_sessions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sandbox_sessions_sessionKey_unique": { + "name": "sandbox_sessions_sessionKey_unique", + "nullsNotDistinct": false, + "columns": [ + "sessionKey" + ] + } + } + }, + "public.published_pages": { + "name": "published_pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "page_id": { + "name": "page_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "artifact_key": { + "name": "artifact_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "published_by": { + "name": "published_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "published_pages_drive_id_idx": { + "name": "published_pages_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "published_pages_page_id_idx": { + "name": "published_pages_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "published_pages_drive_id_drives_id_fk": { + "name": "published_pages_drive_id_drives_id_fk", + "tableFrom": "published_pages", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "published_pages_page_id_pages_id_fk": { + "name": "published_pages_page_id_pages_id_fk", + "tableFrom": "published_pages", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "published_pages_published_by_users_id_fk": { + "name": "published_pages_published_by_users_id_fk", + "tableFrom": "published_pages", + "tableTo": "users", + "columnsFrom": [ + "published_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "published_pages_page_id_key": { + "name": "published_pages_page_id_key", + "nullsNotDistinct": false, + "columns": [ + "page_id" + ] + }, + "published_pages_drive_id_path_key": { + "name": "published_pages_drive_id_path_key", + "nullsNotDistinct": false, + "columns": [ + "drive_id", + "path" + ] + } + } + }, + "public.credit_balances": { + "name": "credit_balances", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "monthlyRemainingCents": { + "name": "monthlyRemainingCents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "monthlyAllowanceCents": { + "name": "monthlyAllowanceCents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "topupRemainingCents": { + "name": "topupRemainingCents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "debtCents": { + "name": "debtCents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "pendingMillicents": { + "name": "pendingMillicents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "monthlyPeriodStart": { + "name": "monthlyPeriodStart", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "monthlyPeriodEnd": { + "name": "monthlyPeriodEnd", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "credit_balances_userId_users_id_fk": { + "name": "credit_balances_userId_users_id_fk", + "tableFrom": "credit_balances", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.credit_holds": { + "name": "credit_holds", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estCents": { + "name": "estCents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "aiUsageLogId": { + "name": "aiUsageLogId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "credit_holds_user_idx": { + "name": "credit_holds_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credit_holds_expires_idx": { + "name": "credit_holds_expires_idx", + "columns": [ + { + "expression": "expiresAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credit_holds_userId_users_id_fk": { + "name": "credit_holds_userId_users_id_fk", + "tableFrom": "credit_holds", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.credit_ledger": { + "name": "credit_ledger", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entryType": { + "name": "entryType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bucket": { + "name": "bucket", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amountCents": { + "name": "amountCents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "appliedCents": { + "name": "appliedCents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "chargeMillicents": { + "name": "chargeMillicents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "aiUsageLogId": { + "name": "aiUsageLogId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "realCostCents": { + "name": "realCostCents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "markupBps": { + "name": "markupBps", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 15000 + }, + "stripeRef": { + "name": "stripeRef", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "consumeStatus": { + "name": "consumeStatus", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "consumeError": { + "name": "consumeError", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reconcileGenerationKey": { + "name": "reconcileGenerationKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "credit_ledger_user_idx": { + "name": "credit_ledger_user_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credit_ledger_usage_log_unique": { + "name": "credit_ledger_usage_log_unique", + "columns": [ + { + "expression": "aiUsageLogId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credit_ledger\".\"aiUsageLogId\" IS NOT NULL AND \"credit_ledger\".\"entryType\" = 'usage'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credit_ledger_stripe_ref_unique": { + "name": "credit_ledger_stripe_ref_unique", + "columns": [ + { + "expression": "stripeRef", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credit_ledger\".\"stripeRef\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credit_ledger_reconcile_key_unique": { + "name": "credit_ledger_reconcile_key_unique", + "columns": [ + { + "expression": "reconcileGenerationKey", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credit_ledger\".\"reconcileGenerationKey\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credit_ledger_consume_status_idx": { + "name": "credit_ledger_consume_status_idx", + "columns": [ + { + "expression": "consumeStatus", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credit_ledger_userId_users_id_fk": { + "name": "credit_ledger_userId_users_id_fk", + "tableFrom": "credit_ledger", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.commands": { + "name": "commands", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "drive_id": { + "name": "drive_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entry_page_id": { + "name": "entry_page_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'document'" + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "commands_user_id_idx": { + "name": "commands_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "commands_drive_id_idx": { + "name": "commands_drive_id_idx", + "columns": [ + { + "expression": "drive_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "commands_entry_page_id_idx": { + "name": "commands_entry_page_id_idx", + "columns": [ + { + "expression": "entry_page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "commands_user_id_users_id_fk": { + "name": "commands_user_id_users_id_fk", + "tableFrom": "commands", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "commands_drive_id_drives_id_fk": { + "name": "commands_drive_id_drives_id_fk", + "tableFrom": "commands", + "tableTo": "drives", + "columnsFrom": [ + "drive_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "commands_created_by_id_users_id_fk": { + "name": "commands_created_by_id_users_id_fk", + "tableFrom": "commands", + "tableTo": "users", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "commands_entry_page_id_pages_id_fk": { + "name": "commands_entry_page_id_pages_id_fk", + "tableFrom": "commands", + "tableTo": "pages", + "columnsFrom": [ + "entry_page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "commands_user_trigger": { + "name": "commands_user_trigger", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "trigger" + ] + }, + "commands_drive_trigger": { + "name": "commands_drive_trigger", + "nullsNotDistinct": false, + "columns": [ + "drive_id", + "trigger" + ] + } + } + } + }, + "enums": { + "public.AuthProvider": { + "name": "AuthProvider", + "schema": "public", + "values": [ + "email", + "google", + "apple" + ] + }, + "public.PlatformType": { + "name": "PlatformType", + "schema": "public", + "values": [ + "web", + "desktop", + "ios", + "android" + ] + }, + "public.UserRole": { + "name": "UserRole", + "schema": "public", + "values": [ + "user", + "admin" + ] + }, + "public.FavoriteItemType": { + "name": "FavoriteItemType", + "schema": "public", + "values": [ + "page", + "drive" + ] + }, + "public.PageType": { + "name": "PageType", + "schema": "public", + "values": [ + "FOLDER", + "DOCUMENT", + "CHANNEL", + "AI_CHAT", + "CANVAS", + "FILE", + "SHEET", + "TASK_LIST", + "CODE", + "TERMINAL" + ] + }, + "public.PermissionAction": { + "name": "PermissionAction", + "schema": "public", + "values": [ + "VIEW", + "EDIT", + "SHARE", + "DELETE" + ] + }, + "public.SubjectType": { + "name": "SubjectType", + "schema": "public", + "values": [ + "USER" + ] + }, + "public.MemberRole": { + "name": "MemberRole", + "schema": "public", + "values": [ + "OWNER", + "ADMIN", + "MEMBER" + ] + }, + "public.pulse_summary_type": { + "name": "pulse_summary_type", + "schema": "public", + "values": [ + "scheduled", + "on_demand", + "welcome" + ] + }, + "public.NotificationType": { + "name": "NotificationType", + "schema": "public", + "values": [ + "PERMISSION_GRANTED", + "PERMISSION_REVOKED", + "PERMISSION_UPDATED", + "PAGE_SHARED", + "DRIVE_INVITED", + "DRIVE_JOINED", + "DRIVE_ROLE_CHANGED", + "CONNECTION_REQUEST", + "CONNECTION_ACCEPTED", + "CONNECTION_REJECTED", + "NEW_DIRECT_MESSAGE", + "EMAIL_VERIFICATION_REQUIRED", + "TOS_PRIVACY_UPDATED", + "MENTION", + "TASK_ASSIGNED" + ] + }, + "public.display_preference_type": { + "name": "display_preference_type", + "schema": "public", + "values": [ + "SHOW_TOKEN_COUNTS", + "SHOW_CODE_TOGGLE", + "DEFAULT_MARKDOWN_MODE" + ] + }, + "public.activity_change_group_type": { + "name": "activity_change_group_type", + "schema": "public", + "values": [ + "user", + "ai", + "automation", + "system" + ] + }, + "public.activity_resource": { + "name": "activity_resource", + "schema": "public", + "values": [ + "page", + "drive", + "permission", + "agent", + "user", + "member", + "role", + "file", + "token", + "device", + "message", + "conversation" + ] + }, + "public.content_format": { + "name": "content_format", + "schema": "public", + "values": [ + "text", + "html", + "json", + "tiptap" + ] + }, + "public.http_method": { + "name": "http_method", + "schema": "public", + "values": [ + "GET", + "POST", + "PUT", + "DELETE", + "PATCH", + "HEAD", + "OPTIONS" + ] + }, + "public.log_level": { + "name": "log_level", + "schema": "public", + "values": [ + "trace", + "debug", + "info", + "warn", + "error", + "fatal" + ] + }, + "public.drive_backup_schedule_frequency": { + "name": "drive_backup_schedule_frequency", + "schema": "public", + "values": [ + "daily", + "weekly", + "monthly" + ] + }, + "public.drive_backup_source": { + "name": "drive_backup_source", + "schema": "public", + "values": [ + "manual", + "scheduled", + "pre_restore", + "system" + ] + }, + "public.drive_backup_status": { + "name": "drive_backup_status", + "schema": "public", + "values": [ + "pending", + "ready", + "failed" + ] + }, + "public.page_version_source": { + "name": "page_version_source", + "schema": "public", + "values": [ + "manual", + "auto", + "pre_ai", + "pre_restore", + "restore", + "system" + ] + }, + "public.ConnectionStatus": { + "name": "ConnectionStatus", + "schema": "public", + "values": [ + "PENDING", + "ACCEPTED", + "BLOCKED" + ] + }, + "public.PushPlatformType": { + "name": "PushPlatformType", + "schema": "public", + "values": [ + "ios", + "android", + "web" + ] + }, + "public.integration_connection_status": { + "name": "integration_connection_status", + "schema": "public", + "values": [ + "active", + "expired", + "error", + "pending", + "revoked" + ] + }, + "public.integration_provider_type": { + "name": "integration_provider_type", + "schema": "public", + "values": [ + "builtin", + "openapi", + "custom", + "mcp", + "webhook" + ] + }, + "public.integration_visibility": { + "name": "integration_visibility", + "schema": "public", + "values": [ + "private", + "owned_drives", + "all_drives" + ] + }, + "public.AttendeeStatus": { + "name": "AttendeeStatus", + "schema": "public", + "values": [ + "PENDING", + "ACCEPTED", + "DECLINED", + "TENTATIVE" + ] + }, + "public.EventVisibility": { + "name": "EventVisibility", + "schema": "public", + "values": [ + "DRIVE", + "ATTENDEES_ONLY", + "PRIVATE" + ] + }, + "public.GoogleCalendarConnectionStatus": { + "name": "GoogleCalendarConnectionStatus", + "schema": "public", + "values": [ + "active", + "expired", + "error", + "disconnected" + ] + }, + "public.RecurrenceFrequency": { + "name": "RecurrenceFrequency", + "schema": "public", + "values": [ + "DAILY", + "WEEKLY", + "MONTHLY", + "YEARLY" + ] + }, + "public.WorkflowTriggerType": { + "name": "WorkflowTriggerType", + "schema": "public", + "values": [ + "cron", + "event" + ] + }, + "public.WorkflowRunSourceTable": { + "name": "WorkflowRunSourceTable", + "schema": "public", + "values": [ + "taskTriggers", + "calendarTriggers", + "webhookTriggers", + "cron", + "manual" + ] + }, + "public.WorkflowRunStatus": { + "name": "WorkflowRunStatus", + "schema": "public", + "values": [ + "running", + "success", + "error", + "cancelled" + ] + }, + "public.TaskTriggerType": { + "name": "TaskTriggerType", + "schema": "public", + "values": [ + "due_date", + "completion" + ] + }, + "public.ZoomConnectionStatus": { + "name": "ZoomConnectionStatus", + "schema": "public", + "values": [ + "active", + "expired", + "error", + "disconnected" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file From d03018b53eee39a7ff054a9f354f9586ae2d5feb Mon Sep 17 00:00:00 2001 From: 2witstudios <2witstudios@gmail.com> Date: Fri, 12 Jun 2026 10:03:29 -0500 Subject: [PATCH 7/7] fix(admin): address CodeRabbit review comments - Sort marginByPeriod ascending before LineChart render (was newest-first) - Check res.ok in growth page fetch before setting stale data to undefined - Type-guard alerts JSON in AdminLayoutClient before setAlerts (was untyped any) - Add marginByPeriod rows to ai-billing CSV export (was JSON-only) - Add byTier rows to unit-economics CSV export (was JSON-only) - COALESCE(lastUsedAt, createdAt) in users last-active query; remove revokedAt filter so logged-out users still show their last active date - Add error feedback in ContactSubmissionsTable PATCH (was silent failure) - Fix 13-month MAU trend (twelveMonthsAgo now 11 months back, not 12) - Generate fixed 12-month and 30-day calendar buckets for growth charts so months/days with zero activity but non-zero signups still appear Co-Authored-By: Claude Sonnet 4.6 --- .../admin/src/app/(admin)/ai-billing/page.tsx | 14 ++++---- apps/admin/src/app/(admin)/growth/page.tsx | 1 + apps/admin/src/app/AdminLayoutClient.tsx | 12 +++++-- .../src/app/api/admin/ai-billing/route.ts | 3 ++ .../src/app/api/admin/unit-economics/route.ts | 3 ++ apps/admin/src/app/api/admin/users/route.ts | 10 +++--- .../admin/ContactSubmissionsTable.tsx | 11 +++++++ apps/admin/src/lib/monitoring-queries.ts | 32 +++++++++++++------ 8 files changed, 65 insertions(+), 21 deletions(-) diff --git a/apps/admin/src/app/(admin)/ai-billing/page.tsx b/apps/admin/src/app/(admin)/ai-billing/page.tsx index cf8971da23..8c5a995ebb 100644 --- a/apps/admin/src/app/(admin)/ai-billing/page.tsx +++ b/apps/admin/src/app/(admin)/ai-billing/page.tsx @@ -298,12 +298,14 @@ export default function AdminAiBillingPage() { - ({ - period: String(r.period).slice(0, granularity === "month" ? 7 : 10), - realCost: +(r.realCostCents / 100).toFixed(2), - charged: +(r.chargedCents / 100).toFixed(2), - margin: +(r.marginCents / 100).toFixed(2), - }))} margin={{ top: 4, right: 16, left: 0, bottom: 4 }}> + String(a.period) < String(b.period) ? -1 : 1) + .map((r) => ({ + period: String(r.period).slice(0, granularity === "month" ? 7 : 10), + realCost: +(r.realCostCents / 100).toFixed(2), + charged: +(r.chargedCents / 100).toFixed(2), + margin: +(r.marginCents / 100).toFixed(2), + }))} margin={{ top: 4, right: 16, left: 0, bottom: 4 }}> `$${v}`} tick={{ fontSize: 11 }} /> diff --git a/apps/admin/src/app/(admin)/growth/page.tsx b/apps/admin/src/app/(admin)/growth/page.tsx index f40f793a10..9996569830 100644 --- a/apps/admin/src/app/(admin)/growth/page.tsx +++ b/apps/admin/src/app/(admin)/growth/page.tsx @@ -99,6 +99,7 @@ export default function GrowthPage() { setIsLoading(true); try { const res = await fetchWithAuth("/api/monitoring/growth"); + if (!res.ok) throw new Error(`HTTP ${res.status}`); const json = await res.json(); setData(json.data); } catch { diff --git a/apps/admin/src/app/AdminLayoutClient.tsx b/apps/admin/src/app/AdminLayoutClient.tsx index e04f9671c5..f28b17c029 100644 --- a/apps/admin/src/app/AdminLayoutClient.tsx +++ b/apps/admin/src/app/AdminLayoutClient.tsx @@ -13,6 +13,14 @@ interface AlertState { liveHoldsAlert: boolean; } +function isAlertState(value: unknown): value is AlertState { + if (!value || typeof value !== "object") return false; + const v = value as Record; + return typeof v.errorRateAlert === "boolean" + && typeof v.negativeMarginAlert === "boolean" + && typeof v.liveHoldsAlert === "boolean"; +} + function AlertDot() { return ( @@ -39,8 +47,8 @@ export default function AdminLayoutClient({ useEffect(() => { fetchWithAuth('/api/admin/alerts') - .then((r) => r.ok ? r.json() : null) - .then((d) => d && setAlerts(d)) + .then(async (r): Promise => (r.ok ? r.json() : null)) + .then((d) => { if (isAlertState(d)) setAlerts(d); }) .catch(() => null); }, []); diff --git a/apps/admin/src/app/api/admin/ai-billing/route.ts b/apps/admin/src/app/api/admin/ai-billing/route.ts index 6492598c1c..ccf5ee3864 100644 --- a/apps/admin/src/app/api/admin/ai-billing/route.ts +++ b/apps/admin/src/app/api/admin/ai-billing/route.ts @@ -129,6 +129,9 @@ export const GET = withAdminAuth(async (_adminUser, request) => { for (const r of negativeMargin) { rows.push(['alert_negative_margin', r.userEmail ?? r.userName ?? r.userId, '', '', '', '', r.requestCount, centsToDollars(r.realCostCents), centsToDollars(r.chargedCents), centsToDollars(r.marginCents)]); } + for (const r of marginByPeriod) { + rows.push(['margin_period', typeof r.period === 'string' ? r.period : String(r.period), '', '', '', '', r.requestCount, centsToDollars(r.realCostCents), centsToDollars(r.chargedCents), centsToDollars(r.marginCents)]); + } return new NextResponse(toCsv(rows), { status: 200, diff --git a/apps/admin/src/app/api/admin/unit-economics/route.ts b/apps/admin/src/app/api/admin/unit-economics/route.ts index 490b3e0c05..1c415a7395 100644 --- a/apps/admin/src/app/api/admin/unit-economics/route.ts +++ b/apps/admin/src/app/api/admin/unit-economics/route.ts @@ -79,6 +79,9 @@ export const GET = withAdminAuth(async (_adminUser, request) => { for (const r of debtByUser) { rows.push(['debt', r.userEmail ?? r.userName ?? r.userId, '', '', '', '', '', '', centsToDollars(r.debtCents)]); } + for (const r of byTier) { + rows.push(['tier', r.tier, centsToDollars(r.realCostCents), centsToDollars(r.chargedCents), centsToDollars(r.appliedCents), centsToDollars(r.marginCents), r.marginPct === null ? '' : r.marginPct.toFixed(2), r.requestCount, '']); + } return new NextResponse(toCsv(rows), { status: 200, diff --git a/apps/admin/src/app/api/admin/users/route.ts b/apps/admin/src/app/api/admin/users/route.ts index 9af8c1a305..2a25e1e395 100644 --- a/apps/admin/src/app/api/admin/users/route.ts +++ b/apps/admin/src/app/api/admin/users/route.ts @@ -1,5 +1,5 @@ import { db } from '@pagespace/db/db' -import { and, eq, inArray, desc, count, sql, isNull } from '@pagespace/db/operators' +import { and, eq, inArray, desc, count, sql } from '@pagespace/db/operators' import { users } from '@pagespace/db/schema/auth' import { drives, pages, chatMessages } from '@pagespace/db/schema/core' import { messages } from '@pagespace/db/schema/conversations' @@ -82,13 +82,15 @@ export const GET = withAdminAuth(async (_adminUser, _request) => { .from(messages) .where(inArray(messages.userId, userIds)) .groupBy(messages.userId), - // Last active: MAX(lastUsedAt) across non-revoked sessions per user + // Last active: across ALL sessions regardless of revoked state — a user who was + // active yesterday and then logged out still has a recent lastActiveAt. Use + // COALESCE to handle sessions where lastUsedAt was never set (fall back to createdAt). db.select({ userId: sessions.userId, - lastActiveAt: sql`MAX(${sessions.lastUsedAt})`, + lastActiveAt: sql`MAX(COALESCE(${sessions.lastUsedAt}, ${sessions.createdAt}))`, }) .from(sessions) - .where(and(inArray(sessions.userId, userIds), isNull(sessions.revokedAt))) + .where(inArray(sessions.userId, userIds)) .groupBy(sessions.userId), ]); diff --git a/apps/admin/src/components/admin/ContactSubmissionsTable.tsx b/apps/admin/src/components/admin/ContactSubmissionsTable.tsx index de32f5b784..d3997d629b 100644 --- a/apps/admin/src/components/admin/ContactSubmissionsTable.tsx +++ b/apps/admin/src/components/admin/ContactSubmissionsTable.tsx @@ -102,6 +102,7 @@ export function ContactSubmissionsTable({ const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc'); const [resolvingId, setResolvingId] = useState(null); const [localResolved, setLocalResolved] = useState>({}); + const [resolveError, setResolveError] = useState(null); const handleSearch = (value: string) => { setSearchTerm(value); @@ -132,6 +133,7 @@ export function ContactSubmissionsTable({ ? localResolved[submission.id] : submission.resolvedAt !== null; setResolvingId(submission.id); + setResolveError(null); try { const response = await fetchWithAuth(`/api/admin/contact/${submission.id}`, { method: 'PATCH', @@ -140,7 +142,11 @@ export function ContactSubmissionsTable({ }); if (response.ok) { setLocalResolved(prev => ({ ...prev, [submission.id]: !isResolved })); + } else { + setResolveError(`Failed to update submission (${response.status})`); } + } catch { + setResolveError('Network error — please try again'); } finally { setResolvingId(null); } @@ -168,6 +174,11 @@ export function ContactSubmissionsTable({ return (
+ {resolveError && ( +
+ {resolveError} +
+ )}
diff --git a/apps/admin/src/lib/monitoring-queries.ts b/apps/admin/src/lib/monitoring-queries.ts index 99f675acf2..e2d15cf7fa 100644 --- a/apps/admin/src/lib/monitoring-queries.ts +++ b/apps/admin/src/lib/monitoring-queries.ts @@ -1204,7 +1204,8 @@ export async function getGrowthMetrics(): Promise { const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); - const twelveMonthsAgo = new Date(now.getFullYear() - 1, now.getMonth(), 1); + // Start of the month exactly 11 months ago → produces exactly 12 calendar months + const twelveMonthsAgo = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 11, 1)); const [totalUsersResult] = await db.select({ count: count() }).from(users); const totalUsers = totalUsersResult?.count ?? 0; @@ -1282,11 +1283,17 @@ export async function getGrowthMetrics(): Promise { // DATE_TRUNC returns Date objects from the node-postgres driver despite the sql // annotation — normalise to ISO strings so Map key equality works across queries. const toKey = (v: unknown) => (v instanceof Date ? v.toISOString() : String(v)); + + // Build exactly 12 fixed month buckets (UTC) ending at current month, ascending. + const monthBucketKeys: string[] = Array.from({ length: 12 }, (_, i) => + new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 11 + i, 1)).toISOString() + ); + const mauByMonth = new Map(mauTrendRaw.map(r => [toKey(r.month), r.mau])); const signupsByMonth = new Map(signupsByMonthRaw.map(r => [toKey(r.month), r.signups])); - const mauTrend: MAUTrendRow[] = mauTrendRaw.map(r => ({ - period: toKey(r.month), - mau: r.mau, - newUsers: signupsByMonth.get(toKey(r.month)) ?? 0, + const mauTrend: MAUTrendRow[] = monthBucketKeys.map(key => ({ + period: key, + mau: mauByMonth.get(key) ?? 0, + newUsers: signupsByMonth.get(key) ?? 0, })); // DAU trend (last 30 days) from activity_logs @@ -1310,11 +1317,18 @@ export async function getGrowthMetrics(): Promise { .groupBy(sql`DATE_TRUNC('day', ${users.createdAt})`) .orderBy(asc(sql`DATE_TRUNC('day', ${users.createdAt})`)); + // Build exactly 30 fixed day buckets (UTC) ending at yesterday, ascending. + const dayBucketKeys: string[] = Array.from({ length: 30 }, (_, i) => { + const msAgo = (29 - i) * 24 * 60 * 60 * 1000; + const d = new Date(now.getTime() - msAgo); + return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())).toISOString(); + }); + const dauByDay = new Map(dauTrendRaw.map(r => [toKey(r.day), r.dau])); const signupsByDay = new Map(signupsByDayRaw.map(r => [toKey(r.day), r.signups])); - const dauTrend: DAUTrendRow[] = dauTrendRaw.map(r => ({ - day: toKey(r.day), - dau: r.dau, - signups: signupsByDay.get(toKey(r.day)) ?? 0, + const dauTrend: DAUTrendRow[] = dayBucketKeys.map(key => ({ + day: key, + dau: dauByDay.get(key) ?? 0, + signups: signupsByDay.get(key) ?? 0, })); // Tier breakdown