diff --git a/apps/web/app/(app)/[organization]/[connectionId]/chatbot/chatbot-page.client.tsx b/apps/web/app/(app)/[organization]/[connectionId]/chatbot/chatbot-page.client.tsx index 35f08bc5..39f1d7cb 100644 --- a/apps/web/app/(app)/[organization]/[connectionId]/chatbot/chatbot-page.client.tsx +++ b/apps/web/app/(app)/[organization]/[connectionId]/chatbot/chatbot-page.client.tsx @@ -18,18 +18,12 @@ import { CopilotActionExecutor } from './copilot/action-bridge'; type ChatBotPageContentProps = { variant?: 'sidebar' | 'compact'; - mode?: ChatMode; - copilotEnvelope?: CopilotEnvelopeV1 | null; + mode?: ChatMode; + copilotEnvelope?: CopilotEnvelopeV1 | null; onClose?: () => void; }; -export default function ChatBotPageContent({ - variant = 'sidebar', - mode = 'global', - copilotEnvelope = null, - onClose, -}: ChatBotPageContentProps) { - +export default function ChatBotPageContent({ variant = 'sidebar', mode = 'global', copilotEnvelope = null, onClose }: ChatBotPageContentProps) { const [compactMode, setCompactMode] = useState(variant === 'compact'); useEffect(() => setCompactMode(variant === 'compact'), [variant]); const t = useTranslations('Chatbot'); @@ -87,7 +81,7 @@ export default function ChatBotPageContent({ await chat.handleCreateSession(); }; - const onExecuteAction: CopilotActionExecutor = async (action) => { + const onExecuteAction: CopilotActionExecutor = async action => { if (action.type === 'sql.replace') { console.log('replace sql', action.sql); } @@ -104,13 +98,7 @@ export default function ChatBotPageContent({ {compactMode ? (
{hasSessions && sessionSelector} -
@@ -132,7 +120,7 @@ export default function ChatBotPageContent({ initialPrompt={pendingPromptRef.current} onConversationActivity={chat.handleConversationActivity} onExecuteAction={onExecuteAction} - onSessionCreated={(sessionId) => chat.setSelectedSessionId(sessionId)} + onSessionCreated={sessionId => chat.setSelectedSessionId(sessionId)} mode={mode} copilotEnvelope={copilotEnvelope} /> diff --git a/apps/web/app/(app)/[organization]/[connectionId]/chatbot/core/session-controller.ts b/apps/web/app/(app)/[organization]/[connectionId]/chatbot/core/session-controller.ts index efe0bc6b..9b597ea8 100644 --- a/apps/web/app/(app)/[organization]/[connectionId]/chatbot/core/session-controller.ts +++ b/apps/web/app/(app)/[organization]/[connectionId]/chatbot/core/session-controller.ts @@ -10,18 +10,11 @@ import posthog from 'posthog-js'; import type { ChatSessionItem, ChatMode } from './types'; import { normalizeSessionsForDisplay } from './utils'; -import { - apiCreateSession, - apiDeleteSession, - apiFetchSessionDetail, - apiFetchSessions, - apiFetchCopilotSession, - apiRenameSession, -} from './api'; +import { apiCreateSession, apiDeleteSession, apiFetchSessionDetail, apiFetchSessions, apiFetchCopilotSession, apiRenameSession } from './api'; import type { CopilotEnvelopeV1 } from '../copilot/types/copilot-envelope'; -export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: CopilotEnvelopeV1 | null }) { - const { mode, copilotEnvelope } = params; +export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: CopilotEnvelopeV1 | null; enabled?: boolean }) { + const { mode, copilotEnvelope, enabled = true } = params; const copilotTabId = copilotEnvelope?.meta?.tabId ?? null; const t = useTranslations('Chatbot'); const routeParams = useParams<{ connectionId: string }>(); @@ -80,32 +73,33 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi [mode, connectionId, t], ); - const fetchSessionDetail = useCallback(async (sessionId: string) => { - setLoadingMessages(true); - try { - const { detail, messages } = await apiFetchSessionDetail(sessionId, { errorMessage: t('Errors.FetchSessionDetail') }); + const fetchSessionDetail = useCallback( + async (sessionId: string) => { + setLoadingMessages(true); + try { + const { detail, messages } = await apiFetchSessionDetail(sessionId, { errorMessage: t('Errors.FetchSessionDetail') }); - console.log('[chat] fetch session detail', detail, messages); + console.log('[chat] fetch session detail', detail, messages); - if (detail?.session) { - setSessions(prev => { - - const exists = prev.some(item => item.id === detail.session.id); - if (!exists) return [detail.session, ...prev]; - return prev.map(item => (item.id === detail.session.id ? detail.session : item)); - }); + if (detail?.session) { + setSessions(prev => { + const exists = prev.some(item => item.id === detail.session.id); + if (!exists) return [detail.session, ...prev]; + return prev.map(item => (item.id === detail.session.id ? detail.session : item)); + }); + } + setInitialMessages(messages); + } catch (e: any) { + console.error('[chat] fetch session detail failed', e); + toast.error(e?.message || t('Errors.FetchSessionDetail')); + setInitialMessages([]); + } finally { + setLoadingMessages(false); } - setInitialMessages(messages); - } catch (e: any) { - console.error('[chat] fetch session detail failed', e); - toast.error(e?.message || t('Errors.FetchSessionDetail')); - setInitialMessages([]); - } finally { - setLoadingMessages(false); - } - }, [t]); + }, + [t], + ); - const ensureCopilotSession = useCallback(async () => { if (mode !== 'copilot') return; if (!copilotTabId) { @@ -154,23 +148,33 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi } }, [mode, copilotTabId, fetchSessionDetail, t]); - useEffect(() => { + if (!enabled) { + setLoadingSessions(false); + setLoadingMessages(false); + setSessions([]); + setSelectedSessionId(null); + setInitialMessages([]); + return; + } + if (mode === 'copilot') { ensureCopilotSession().catch(() => undefined); } else { fetchSessions().catch(() => undefined); } - }, [mode, fetchSessions, ensureCopilotSession]); + }, [enabled, mode, fetchSessions, ensureCopilotSession]); - useEffect(() => { if (!selectedSessionId) { setInitialMessages([]); return; } + if (!enabled) { + return; + } fetchSessionDetail(selectedSessionId).catch(() => undefined); - }, [selectedSessionId, fetchSessionDetail]); + }, [enabled, selectedSessionId, fetchSessionDetail]); const handleCreateSession = useCallback(async () => { if (mode === 'copilot') { @@ -196,7 +200,7 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi const handleSessionSelect = useCallback( (sessionId: string) => { - if (mode === 'copilot') return; + if (mode === 'copilot') return; setSelectedSessionId(sessionId); }, [mode], @@ -208,7 +212,6 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi fetchSessions(currentId).catch(() => undefined); }, [mode, fetchSessions]); - const handleRenameRequest = useCallback( (sessionId: string) => { if (mode === 'copilot') return toast.error(t('Errors.CopilotRenameUnsupported')); @@ -259,7 +262,6 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi } }, [mode, editingSessionId, editingSessionValue, sessions, fetchSessions, t]); - const handleDeleteRequest = useCallback( (sessionId: string) => { if (mode === 'copilot') return toast.error(t('Errors.CopilotDeleteUnsupported')); @@ -363,8 +365,6 @@ export function useChatSessions(params: { mode: ChatMode; copilotEnvelope?: Copi handleDeleteSubmit, handleNewChat, handleRefreshSessions, - - setSelectedSessionId, }; } diff --git a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-modes/sql-mode.tsx b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-modes/sql-mode.tsx index 5d375392..9c29dd54 100644 --- a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-modes/sql-mode.tsx +++ b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-modes/sql-mode.tsx @@ -4,6 +4,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useAtom, useAtomValue } from 'jotai'; import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels'; import { Check, ChevronDown, Loader2, Play, Save, Square } from 'lucide-react'; +import { usePathname, useSearchParams } from 'next/navigation'; import { Button } from '@/registry/new-york-v4/ui/button'; import { @@ -25,13 +26,10 @@ import { SaveSqlDialog } from './save-sql-dialog'; import type { SqlModeProps } from './types'; import { authFetch } from '@/lib/client/auth-fetch'; import { useTranslations } from 'next-intl'; -import { - normalizeSqlEditorSettings, - SQL_EDITOR_QUERY_LIMIT_OPTIONS, - sqlEditorSettingsAtom, -} from '@/shared/stores/sql-editor-settings.store'; - +import { normalizeSqlEditorSettings, SQL_EDITOR_QUERY_LIMIT_OPTIONS, sqlEditorSettingsAtom } from '@/shared/stores/sql-editor-settings.store'; import { currentConnectionAtom } from '@/shared/stores/app.store'; +import { authClient } from '@/lib/auth-client'; +import { AuthLinkSheet } from '@/components/auth/auth-link-sheet'; import type { SavedQueryItem } from '../saved-queries/saved-queries-sidebar'; export function SqlMode({ @@ -51,9 +49,13 @@ export function SqlMode({ onCloseChatbot, }: SqlModeProps) { const t = useTranslations('SqlConsole'); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const { data: session } = authClient.useSession(); const selectionByTab = useAtomValue(editorSelectionByTabAtom); const [editorSettings, setEditorSettings] = useAtom(sqlEditorSettingsAtom); const [saveDialogOpen, setSaveDialogOpen] = useState(false); + const [authSheetOpen, setAuthSheetOpen] = useState(false); const [savedQueries, setSavedQueries] = useState([]); const [queryLimit, setQueryLimit] = useState(editorSettings.queryLimit); const selection = activeTab?.tabId ? selectionByTab[activeTab.tabId] : null; @@ -75,7 +77,7 @@ export function SqlMode({ setEditorSettings(prev => normalizeSqlEditorSettings({ ...prev, queryLimit: next })); }; const getSqlText = useCallback( - () => editorRef.current?.getValue() ?? (activeTab?.tabType === 'sql' ? activeTab?.content ?? '' : ''), + () => editorRef.current?.getValue() ?? (activeTab?.tabType === 'sql' ? (activeTab?.content ?? '') : ''), [activeTab?.tabType === 'sql' && activeTab?.content, activeTab?.tabType, editorRef], ); const currentSqlText = getSqlText().trim(); @@ -83,6 +85,20 @@ export function SqlMode({ const runLabel = hasSelection ? t('Toolbar.RunSelected') : t('Toolbar.Run'); const runLabelWithLimit = hasSqlLimit ? `${runLabel} ( Limit: SQL )` : `${runLabel} ( Limit: ${queryLimit} )`; const isSaved = !!currentSqlText && savedQueries.some(q => q.sqlText.trim() === currentSqlText); + const requiresFullAccount = !session?.user || session.user.isAnonymous; + const callbackURL = useMemo(() => { + const query = searchParams?.toString(); + return query ? `${pathname}?${query}` : pathname || '/'; + }, [pathname, searchParams]); + + const requestSave = useCallback(() => { + if (!canSave) return; + if (requiresFullAccount) { + setAuthSheetOpen(true); + return; + } + setSaveDialogOpen(true); + }, [canSave, requiresFullAccount]); const fetchSavedQueries = useCallback(async () => { if (!connectionId) { @@ -126,18 +142,16 @@ export function SqlMode({ const isSave = event.key.toLowerCase() === 's'; const hasModifier = event.metaKey || event.ctrlKey; if (!isSave || !hasModifier) return; - if (!canSave) return; event.preventDefault(); - setSaveDialogOpen(true); + requestSave(); }; window.addEventListener('keydown', handler); return () => { window.removeEventListener('keydown', handler); }; - }, [canSave]); + }, [requestSave]); return ( -
5) setChatWidth(copilotSize); }} > - +
- - @@ -201,12 +195,7 @@ export function SqlMode({
{isRunning && activeTab ? ( - @@ -218,24 +207,14 @@ export function SqlMode({ {t('Toolbar.Saved')}
) : ( - )}
- +
@@ -253,12 +232,7 @@ export function SqlMode({
- +
- + +
); } diff --git a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-panel/index.tsx b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-panel/index.tsx index e8f27495..5c08b4f8 100644 --- a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-panel/index.tsx +++ b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/components/copilot-panel/index.tsx @@ -3,6 +3,7 @@ import React, { useMemo, useState, Activity, useCallback, useEffect } from 'react'; import { useAtom, useAtomValue } from 'jotai'; import { Loader2, X } from 'lucide-react'; +import { authClient } from '@/lib/auth-client'; import { useChatSessions } from '../../../chatbot/core/session-controller'; import type { CopilotEnvelopeV1 } from '../../../chatbot/copilot/types/copilot-envelope'; @@ -24,6 +25,7 @@ import ContextTab from './context'; // ✅ shadcn Tabs import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/registry/new-york-v4/ui/tabs'; import { ActionTab } from './action/ui'; +import { AccountRequiredSheet } from '@/components/auth/account-required-sheet'; type CopilotPanelProps = { tabs: UITabPayload[]; @@ -38,17 +40,10 @@ type CopilotPanelProps = { type SubTabKey = 'ask' | 'action' | 'context'; -export default function CopilotPanel({ - tabs, - activeTabId, - activeTab, - updateTab, - addTab, - setActiveTabId, - onClose, - editorRef, -}: CopilotPanelProps) { +export default function CopilotPanel({ tabs, activeTabId, activeTab, updateTab, addTab, setActiveTabId, onClose, editorRef }: CopilotPanelProps) { const t = useTranslations('SqlConsole'); + const { data: session } = authClient.useSession(); + const requiresFullAccount = !session?.user || session.user.isAnonymous; const activeDatabase = useAtomValue(activeDatabaseAtom); const currentConnection = useAtomValue(currentConnectionAtom); const sessionMeta = useAtomValue(currentSessionMetaAtom); @@ -60,13 +55,13 @@ export default function CopilotPanel({ const [copilotEnvelope, setCopilotEnvelope] = useState(null); const activeTabCoreFields = activeTab ? { - tabId: activeTab.tabId, - tabName: activeTab.tabName, - tabType: activeTab.tabType, - connectionId: activeTab.connectionId, - databaseName: (activeTab as any)?.databaseName, - tableName: (activeTab as any)?.tableName, - } + tabId: activeTab.tabId, + tabName: activeTab.tabName, + tabType: activeTab.tabType, + connectionId: activeTab.connectionId, + databaseName: (activeTab as any)?.databaseName, + tableName: (activeTab as any)?.tableName, + } : null; const onExecuteAction = useSqlCopilotExecutor({ @@ -85,12 +80,11 @@ export default function CopilotPanel({ const tabId = activeTab?.tabId; const tabName = activeTab?.tabName; - const tabType = (activeTab as any)?.tabType; + const tabType = (activeTab as any)?.tabType; const tabConnectionId = (activeTab as any)?.connectionId; const tabContent = (activeTab as any)?.content ?? ''; const editorSelection = tabId ? (selectionByTab[tabId] ?? null) : null; - const isSqlTab = tabType === 'sql'; useEffect(() => { @@ -119,7 +113,6 @@ export default function CopilotPanel({ }, }); - if (!cancelled) { setCopilotEnvelope(nextEnvelope); } @@ -151,9 +144,9 @@ export default function CopilotPanel({ sql: sqlTextFromResult, error: hasErrorMessage ? { - message: sessionErrorMessage!, - code: sessionErrorCode ?? null, - } + message: sessionErrorMessage!, + code: sessionErrorCode ?? null, + } : null, database: activeDatabase || null, dialect: (currentConnection as any)?.connection?.type ?? undefined, @@ -183,9 +176,7 @@ export default function CopilotPanel({ (sql: string, meta?: ApplySqlMeta) => { if (!activeTab || activeTab.tabType !== 'sql') return; - const previousSql = - (editorRef?.current?.getValue?.() as string | undefined) ?? - (typeof tabContent === 'string' ? tabContent : ''); + const previousSql = (editorRef?.current?.getValue?.() as string | undefined) ?? (typeof tabContent === 'string' ? tabContent : ''); const currentSql = previousSql ?? ''; const originalSql = meta?.originalSql; @@ -262,6 +253,7 @@ export default function CopilotPanel({ const chat = useChatSessions({ mode: 'copilot', copilotEnvelope, + enabled: !requiresFullAccount, }); const loading = chat.loadingSessions || (chat.loadingMessages && !chat.selectedSessionId); @@ -276,6 +268,10 @@ export default function CopilotPanel({ } }, [actionRequest?.id]); + if (requiresFullAccount) { + return ; + } + return (
@@ -331,7 +327,7 @@ export default function CopilotPanel({ onApplySql={handleApplySqlWithEvent} onExecuted={handleActionExecuted} autoRun={actionRequest ? { intent: actionRequest.intent, requestId: actionRequest.id } : null} - onAutoRunHandled={(requestId) => { + onAutoRunHandled={requestId => { setActionRequest(prev => (prev?.id === requestId ? null : prev)); }} /> diff --git a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/layout.tsx b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/layout.tsx index 5f4a3d86..17425e79 100644 --- a/apps/web/app/(app)/[organization]/[connectionId]/sql-console/layout.tsx +++ b/apps/web/app/(app)/[organization]/[connectionId]/sql-console/layout.tsx @@ -1,12 +1,13 @@ 'use client'; import React from 'react'; -import { useClientDBReady } from './useClientDBReady'; import { useTranslations } from 'next-intl'; +import { useClientDBReady } from './useClientDBReady'; export default function SqlConsoleLayout({ children }: React.PropsWithChildren) { const { ready, initializing, error } = useClientDBReady(); const t = useTranslations('SqlConsole'); + if (error) { return
{t('Layout.InitFailed')}
; } diff --git a/apps/web/app/(app)/[organization]/components/app-sidebar/connection-switcher/index.tsx b/apps/web/app/(app)/[organization]/components/app-sidebar/connection-switcher/index.tsx index d4a62f59..73601f06 100644 --- a/apps/web/app/(app)/[organization]/components/app-sidebar/connection-switcher/index.tsx +++ b/apps/web/app/(app)/[organization]/components/app-sidebar/connection-switcher/index.tsx @@ -159,7 +159,6 @@ export function ConnectionSwitcher() { if (connectionId) { const match = connections.find(item => item.connection.id === connectionId); - console.log('ConnectionSwitcher: sync connectionId from URL', { connectionId, match }); if (match && match.connection.id !== currentConnection?.connection?.id) { setCurrentConnection(match); } diff --git a/apps/web/app/(app)/[organization]/components/app-sidebar/nav-user.tsx b/apps/web/app/(app)/[organization]/components/app-sidebar/nav-user.tsx index 448a70ee..8809d148 100644 --- a/apps/web/app/(app)/[organization]/components/app-sidebar/nav-user.tsx +++ b/apps/web/app/(app)/[organization]/components/app-sidebar/nav-user.tsx @@ -1,34 +1,88 @@ 'use client'; -import { IconDotsVertical, IconFolder, IconLogout } from '@tabler/icons-react'; - +import { useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { useParams, usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { IconDotsVertical, IconFolder, IconLogin2, IconLogout } from '@tabler/icons-react'; import { Avatar, AvatarImage } from '@/registry/new-york-v4/ui/avatar'; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from '@/registry/new-york-v4/ui/alert-dialog'; import BoringAvatar from 'boring-avatars'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from '@/registry/new-york-v4/ui/dropdown-menu'; import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarTrigger, useSidebar } from '@/registry/new-york-v4/ui/sidebar'; -import { signOut } from '@/lib/auth-client'; -import { useParams, useRouter } from 'next/navigation'; +import { authClient, signOut } from '@/lib/auth-client'; import { ModeToggle } from '@/components/mode-toggle'; +import { AuthLinkSheet } from '@/components/auth/auth-link-sheet'; import { User } from 'better-auth'; +import { isAnonymousUser } from '@/lib/auth/anonymous-user'; export function NavUser({ user }: { user: User | null }) { const { isMobile, state } = useSidebar(); const params = useParams<{ organization: string }>(); + const pathname = usePathname(); const router = useRouter(); + const searchParams = useSearchParams(); + const t = useTranslations('AppSidebar'); const collapsed = state === 'collapsed'; const organizationSlug = params.organization; + const [confirmOpen, setConfirmOpen] = useState(false); + const [authSheetOpen, setAuthSheetOpen] = useState(false); + const [signingOut, setSigningOut] = useState(false); + const [signOutError, setSignOutError] = useState(null); + const isAnonymous = isAnonymousUser(user); + + const callbackURL = (() => { + const query = searchParams?.toString(); + return query ? `${pathname}?${query}` : pathname || '/'; + })(); + + const displayName = isAnonymous ? t('GuestSession.Name') : user?.name; + const displaySubtitle = isAnonymous ? t('GuestSession.Subtitle') : user?.email; + + function handleSignIn() { + setAuthSheetOpen(true); + } + + async function handleSignOut() { + setSigningOut(true); + setSignOutError(null); + + try { + const res = isAnonymous ? await authClient.deleteAnonymousUser() : await signOut(); + if (res.data?.success) { + router.push('/sign-in'); + return; + } + setSignOutError(t('GuestSession.DeleteFailed')); + } catch { + setSignOutError(isAnonymous ? t('GuestSession.DeleteFailed') : null); + } finally { + setSigningOut(false); + if (!isAnonymous) { + setConfirmOpen(false); + } + } + } const renderMenuContent = () => (
- - + +
- {user?.name} - {user?.email} + {displayName} + {displaySubtitle}
@@ -41,18 +95,30 @@ export function NavUser({ user }: { user: User | null }) { My Project */} + {isAnonymous ? ( + { + e.preventDefault(); + handleSignIn(); + }} + > + + {t('GuestSession.SignIn')} + + ) : null} { e.preventDefault(); - const res = await signOut(); - console.log(res); - if (res.data?.success) { - router.push('/sign-in'); + if (isAnonymous) { + setConfirmOpen(true); + return; } + + await handleSignOut(); }} > - Log out + {isAnonymous ? t('GuestSession.AbandonAction') : t('LogOut')}
); @@ -70,11 +136,11 @@ export function NavUser({ user }: { user: User | null }) { - - + +
- {user?.name} + {displayName} {/* {user?.email} */}
@@ -87,27 +153,46 @@ export function NavUser({ user }: { user: User | null }) { } return ( - - -
- - - - - - - -
- {user?.name} -
-
-
- {renderMenuContent()} -
- - -
-
-
+ <> + + +
+ + + + + + + +
+ {displayName} +
+
+
+ {renderMenuContent()} +
+ + +
+
+
+ + + + + {t('GuestSession.Title')} + {t('GuestSession.Description')} + {signOutError ?

{signOutError}

: null} +
+ + {t('GuestSession.Cancel')} + + {t('GuestSession.Confirm')} + + +
+
+ + ); } diff --git a/apps/web/app/(app)/[organization]/layout.tsx b/apps/web/app/(app)/[organization]/layout.tsx index ccb21bee..1e4bd3de 100644 --- a/apps/web/app/(app)/[organization]/layout.tsx +++ b/apps/web/app/(app)/[organization]/layout.tsx @@ -7,9 +7,9 @@ import { AppSidebar } from './components/app-sidebar/app-sidebar'; import { getSessionFromRequest } from '@/lib/auth/session'; import { getFirstOrganizationForUser, getOrganizationBySlugOrId } from '@/lib/server/organization'; import { resolveCurrentOrganizationId } from '@/lib/auth/current-organization'; +import { isAnonymousUser } from '@/lib/auth/anonymous-user'; - -export default async function TeamLayout({ children, params }: { children: React.ReactNode; params: Promise<{ organization: string } > }) { +export default async function TeamLayout({ children, params }: { children: React.ReactNode; params: Promise<{ organization: string }> }) { const cookieStore = await cookies(); const defaultOpen = cookieStore.get('sidebar_state')?.value !== 'false'; const session = await getSessionFromRequest(); @@ -26,6 +26,10 @@ export default async function TeamLayout({ children, params }: { children: React redirect(`/${fallbackOrganization.slug}/connections`); } + if (isAnonymousUser(session.user)) { + redirect('/sign-in'); + } + redirect('/create-organization'); } diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx index 22ffcc6e..b51a0bd2 100644 --- a/apps/web/app/(app)/layout.tsx +++ b/apps/web/app/(app)/layout.tsx @@ -4,12 +4,12 @@ import SWRConfigWrapper from '@/components/@dory/ui/swr-config-wrapper'; import QueryClientWrapper from '@/components/@dory/ui/query-client-wrapper/query-client-wrapper'; export default async function AppRootLayout({ children }: { children: React.ReactNode }) { - const session = await getSessionFromRequest(); - if (!session) redirect('/sign-in'); + const session = await getSessionFromRequest(); + if (!session) redirect('/sign-in'); - return ( - - {children} - - ); + return ( + + {children} + + ); } diff --git a/apps/web/app/(app)/page.tsx b/apps/web/app/(app)/page.tsx index d5a7d7d9..0350f988 100644 --- a/apps/web/app/(app)/page.tsx +++ b/apps/web/app/(app)/page.tsx @@ -2,6 +2,7 @@ import { redirect } from 'next/navigation'; import { getSessionFromRequest } from '@/lib/auth/session'; import { resolveCurrentOrganizationId } from '@/lib/auth/current-organization'; import { getFirstOrganizationForUser } from '@/lib/server/organization'; +import { isAnonymousUser } from '@/lib/auth/anonymous-user'; export default async function Page() { const session = await getSessionFromRequest(); @@ -15,6 +16,10 @@ export default async function Page() { redirect(`/${fallbackOrganization.slug}/connections`); } + if (isAnonymousUser(session.user)) { + redirect('/sign-in'); + } + redirect('/create-organization'); } diff --git a/apps/web/app/(auth)/components/SignInForm.tsx b/apps/web/app/(auth)/components/SignInForm.tsx index 79eb56cb..a687597d 100644 --- a/apps/web/app/(auth)/components/SignInForm.tsx +++ b/apps/web/app/(auth)/components/SignInForm.tsx @@ -1,5 +1,4 @@ 'use client'; -import Image from 'next/image'; import Link from 'next/link'; import { useEffect, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; @@ -11,24 +10,32 @@ import { Card, CardContent } from '@/registry/new-york-v4/ui/card'; import { Input } from '@/registry/new-york-v4/ui/input'; import { Label } from '@/registry/new-york-v4/ui/label'; import { IconBrandGithub } from '@tabler/icons-react'; -import { authClient, signInViaGithub, signInViaGoogle } from '@/lib/auth-client'; //Introducing authClient +import { authClient, signInViaGithub, signInViaGoogle } from '@/lib/auth-client'; import { InputPassword } from '@/components/originui/input-password'; import { authFetch } from '@/lib/client/auth-fetch'; import { useTranslations } from 'next-intl'; import { runtime, isDesktopRuntime } from '@/lib/runtime/runtime'; -export function SignInForm({ className, imageUrl, ...props }: React.ComponentProps<'div'> & { imageUrl?: string }) { +type SignInFormProps = React.ComponentProps<'div'> & { + imageUrl?: string; + callbackURL?: string; + onRequestSignUp?: () => void; + showGuestOption?: boolean; + showDemoOption?: boolean; +}; + +export function SignInForm({ className, imageUrl, callbackURL: callbackURLOverride, onRequestSignUp, showGuestOption = true, showDemoOption = true, ...props }: SignInFormProps) { const t = useTranslations('Auth'); const router = useRouter(); const searchParams = useSearchParams(); const isDesktop = isDesktopRuntime(); const [loading, setLoading] = useState(false); - const [demoLoading, setDemoLoading] = useState(false); const [email, setEmail] = useState(''); const [pwd, setPwd] = useState(''); const [err, setErr] = useState(null); const [msg, setMsg] = useState(null); - const callbackURL = searchParams?.get('callbackURL') || '/'; + const [guestLoading, setGuestLoading] = useState(false); + const callbackURL = callbackURLOverride || searchParams?.get('callbackURL') || '/'; useEffect(() => { if (!window.authBridge?.onCallback) return; @@ -73,7 +80,7 @@ export function SignInForm({ className, imageUrl, ...props }: React.ComponentPro setMsg(t('SignIn.SuccessRefreshing')); router.refresh(); - router.replace(`/`); + router.replace(callbackURL); } catch (e) { setErr(t('SignIn.InvalidCallback')); } @@ -82,7 +89,7 @@ export function SignInForm({ className, imageUrl, ...props }: React.ComponentPro return () => { unsubscribe?.(); }; - }, [router]); + }, [callbackURL, router, t]); async function signInViaGithubElectron() { setErr(null); @@ -173,9 +180,7 @@ export function SignInForm({ className, imageUrl, ...props }: React.ComponentPro setMsg(null); setLoading(true); try { - const redirectTo = window.authBridge?.openExternal - ? 'dory://reset-password' - : `${window.location.origin}/reset-password`; + const redirectTo = window.authBridge?.openExternal ? 'dory://reset-password' : `${window.location.origin}/reset-password`; console.log('[auth] request-password-reset start', { email, origin: window.location.origin, @@ -212,135 +217,169 @@ export function SignInForm({ className, imageUrl, ...props }: React.ComponentPro } } - async function onDemoSignIn() { + async function onGuestContinue() { setErr(null); setMsg(null); - setDemoLoading(true); + setGuestLoading(true); + try { - const res = await authFetch('/api/auth/demo', { method: 'POST' }); - if (!res.ok) { - const data = await res.json().catch(() => null); - throw new Error(data?.message ?? t('SignIn.LoginFailedRetry')); + const result = await authClient.signIn.anonymous(); + if (result?.error) { + throw new Error(result.error.message || t('SignIn.Guest.StartFailed')); } - posthog.capture('user_signed_in', { method: 'demo' }); + + const response = await fetch('/api/auth/anonymous/bootstrap', { + method: 'POST', + credentials: 'include', + }); + const payload = await response.json().catch(() => null); + + if (!response.ok || !payload?.organizationSlug) { + throw new Error(typeof payload?.error === 'string' ? payload.error : t('SignIn.Guest.StartFailed')); + } + router.refresh(); - router.push(callbackURL); - } catch (e: any) { - setErr(e?.message ?? t('SignIn.NetworkErrorRetry')); - posthog.capture('user_sign_in_failed', { method: 'demo', error: e?.message }); + router.push(`/${payload.organizationSlug}/connections`); + } catch (nextError) { + setErr(nextError instanceof Error ? nextError.message : t('SignIn.Guest.StartFailed')); } finally { - setDemoLoading(false); + setGuestLoading(false); } } return ( -
- - -
-
-
-

{t('SignIn.Title')}

-

{t('SignIn.Description')}

-
+ <> +
+ + + +
+
+

{t('SignIn.Title')}

+

{t('SignIn.Description')}

+
- {err ?
{err}
: null} - {msg ?
{msg}
: null} - -
- - setEmail(e.target.value.trim())} - autoComplete="email" - /> -
+ {err ? ( +
+ {err} +
+ ) : null} + {msg ? ( +
+ {msg} +
+ ) : null} -
-
- - +
+ + setEmail(e.target.value.trim())} + autoComplete="email" + />
- setPwd(e.target.value)} autoComplete="current-password" /> -
- +
+
+ + +
+ setPwd(e.target.value)} autoComplete="current-password" /> +
- {!isDesktop ? ( - - ) : null} -
- {t('SignIn.OrContinueWith')} -
+ {!isDesktop && (showGuestOption || showDemoOption) ? ( + + ) : null} -
- +
+ {t('SignIn.OrContinueWith')} +
- -
+
+ -
- {t('SignIn.NoAccount')}{' '} - - {t('SignIn.SignUp')} - + +
+ +
+ {t('SignIn.NoAccount')}{' '} + {onRequestSignUp ? ( + + ) : ( + + {t('SignIn.SignUp')} + + )} +
-
- - {/* + + {/*
{imageUrl && Image}
*/} - - + + -
- {t('SignIn.ContinueAgreement')} {t('SignIn.Terms')} {t('SignIn.And')} {t('SignIn.Privacy')}. +
+ {t('SignIn.ContinueAgreement')} {t('SignIn.Terms')} {t('SignIn.And')} {t('SignIn.Privacy')}. +
-
+ ); } diff --git a/apps/web/app/(auth)/components/SignUpform.tsx b/apps/web/app/(auth)/components/SignUpform.tsx index df6174f7..55e2daa8 100644 --- a/apps/web/app/(auth)/components/SignUpform.tsx +++ b/apps/web/app/(auth)/components/SignUpform.tsx @@ -1,5 +1,5 @@ 'use client'; -import { GalleryVerticalEnd, Loader2 } from 'lucide-react'; +import { Loader2 } from 'lucide-react'; import posthog from 'posthog-js'; import { cn } from '@/lib/utils'; import { Label } from '@/registry/new-york-v4/ui/label'; @@ -16,7 +16,12 @@ import { IconBrandGithub } from '@tabler/icons-react'; type Stage = 'form' | 'verify'; -export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) { +type SignUpFormProps = React.ComponentProps<'div'> & { + callbackURL?: string; + onRequestSignIn?: () => void; +}; + +export function SignUpForm({ className, callbackURL: callbackURLOverride, onRequestSignIn, ...props }: SignUpFormProps) { const t = useTranslations('Auth'); const [loading, setLoading] = useState(false); const [err, setErr] = useState(null); @@ -34,7 +39,7 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) const email = String(fd.get('email') ?? '').trim(); const password = String(fd.get('password') ?? ''); const name = String(fd.get('name') ?? (email.split('@')[0] || '')); - const callbackURL = window.authBridge?.openExternal ? 'dory://auth-complete' : '/'; + const callbackURL = callbackURLOverride || (window.authBridge?.openExternal ? 'dory://auth-complete' : '/'); const { error } = await authClient.signUp.email( { name, email, password, callbackURL }, @@ -85,9 +90,15 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) />
{t('SignUp.HasAccount')}{' '} - - {t('SignUp.GoToSignIn')} - + {onRequestSignIn ? ( + + ) : ( + + {t('SignUp.GoToSignIn')} + + )}
); @@ -95,61 +106,43 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) //--Original registration form return ( -
- - -
+
+ + +
-
- -
- -
- {t('SignUp.BrandName')} -
-

{t('SignUp.Title')}

-
- {t('SignUp.AlreadyHaveAccount')}{' '} - - {t('SignUp.SignIn')} - -
+
+

{t('SignUp.Title')}

-
-
- - -
- -
- - -
- -
- - -
- - {err && ( -

- {err} -

- )} +
+ + +
- +
+ + +
+ +
+ +
+ {err ?
{err}
: null} + + +
{t('SignUp.Or')}
@@ -163,7 +156,7 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) if (window.authBridge?.openExternal) { // void signInViaGithubElectron(); } else { - signInViaGithub(); + signInViaGithub(callbackURLOverride || '/'); } }} > @@ -180,7 +173,7 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) // TODO: add Electron Google OAuth when needed return; } - signInViaGoogle(); + signInViaGoogle(callbackURLOverride || '/'); }} > @@ -192,15 +185,26 @@ export function SignUpForm({ className, ...props }: React.ComponentProps<'div'>) {t('SignIn.LoginWithGoogle')}
+ +
+ {t('SignUp.AlreadyHaveAccount')}{' '} + {onRequestSignIn ? ( + + ) : ( + + {t('SignUp.SignIn')} + + )} +
- {t('SignUp.ContinueAgreement')}{' '} - {t('SignUp.Terms')} {t('SignUp.And')}{' '} - {t('SignUp.Privacy')}. + {t('SignUp.ContinueAgreement')} {t('SignUp.Terms')} {t('SignUp.And')} {t('SignUp.Privacy')}.
); diff --git a/apps/web/app/(auth)/sign-in/page.tsx b/apps/web/app/(auth)/sign-in/page.tsx index f4f8324c..e004f32c 100644 --- a/apps/web/app/(auth)/sign-in/page.tsx +++ b/apps/web/app/(auth)/sign-in/page.tsx @@ -40,7 +40,9 @@ export default function SignInPage() { )} > - +
+ +
{/*
*/} diff --git a/apps/web/app/(auth)/sign-up/page.tsx b/apps/web/app/(auth)/sign-up/page.tsx index 9ab2e078..4e698280 100644 --- a/apps/web/app/(auth)/sign-up/page.tsx +++ b/apps/web/app/(auth)/sign-up/page.tsx @@ -43,7 +43,9 @@ export default async function SignUpPage() { )} > - +
+ +
); diff --git a/apps/web/app/api/auth/[...all]/route.ts b/apps/web/app/api/auth/[...all]/route.ts index e21b5c2d..74c396db 100644 --- a/apps/web/app/api/auth/[...all]/route.ts +++ b/apps/web/app/api/auth/[...all]/route.ts @@ -4,6 +4,9 @@ export const dynamic = 'force-dynamic'; import { getAuth } from '@/lib/auth'; import { proxyAuthRequest, shouldProxyAuthRequest } from '@/lib/auth/auth-proxy'; +import { deleteAnonymousUserLocally } from '@/lib/auth/anonymous'; +import { buildAnonymousDeleteResponse, isLocalAnonymousDeleteRequest } from '@/lib/auth/anonymous-delete'; +import { isAnonymousUser } from '@/lib/auth/anonymous-user'; function getSetCookies(headers: Headers): string[] { const anyHeaders = headers as unknown as { getSetCookie?: () => string[] }; @@ -85,6 +88,25 @@ export async function POST(req: Request) { return proxyAuthRequest(req); } const auth = await getAuth(); + const pathname = new URL(req.url).pathname; + + if (isLocalAnonymousDeleteRequest(pathname)) { + const session = await auth.api.getSession({ + headers: req.headers, + }); + + if (!session?.user?.id) { + return Response.json({ error: 'UNAUTHORIZED' }, { status: 401 }); + } + + if (!isAnonymousUser(session.user)) { + return Response.json({ error: 'ANONYMOUS_SESSION_REQUIRED' }, { status: 403 }); + } + + await deleteAnonymousUserLocally(session.user.id); + return buildAnonymousDeleteResponse(req); + } + const res = await auth.handler(req); return rewriteAuthResponse(req, res); } diff --git a/apps/web/app/api/auth/anonymous/bootstrap/route.ts b/apps/web/app/api/auth/anonymous/bootstrap/route.ts new file mode 100644 index 00000000..86448778 --- /dev/null +++ b/apps/web/app/api/auth/anonymous/bootstrap/route.ts @@ -0,0 +1,42 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { proxyAuthRequest, shouldProxyAuthRequest } from '@/lib/auth/auth-proxy'; +import { getAuth } from '@/lib/auth'; +import { getSessionFromRequest } from '@/lib/auth/session'; +import { bootstrapAnonymousOrganization } from '@/lib/auth/anonymous'; +import { isAnonymousUser } from '@/lib/auth/anonymous-user'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +export async function POST(req: NextRequest) { + if (shouldProxyAuthRequest()) { + return proxyAuthRequest(req); + } + + const session = await getSessionFromRequest(req); + if (!session?.user?.id) { + return NextResponse.json({ error: 'UNAUTHORIZED' }, { status: 401 }); + } + + if (!isAnonymousUser(session.user)) { + return NextResponse.json({ error: 'ANONYMOUS_SESSION_REQUIRED' }, { status: 403 }); + } + + try { + const auth = await getAuth(); + const organization = await bootstrapAnonymousOrganization({ + auth, + session, + headers: req.headers, + }); + + return NextResponse.json({ + organizationId: organization.id, + organizationSlug: organization.slug ?? organization.id, + organizationName: organization.name, + }); + } catch (error) { + console.error('[auth][anonymous-bootstrap] failed', error); + return NextResponse.json({ error: 'ANONYMOUS_BOOTSTRAP_FAILED' }, { status: 500 }); + } +} diff --git a/apps/web/app/api/auth/demo/route.ts b/apps/web/app/api/auth/demo/route.ts index 0d3cb5c6..d456f456 100644 --- a/apps/web/app/api/auth/demo/route.ts +++ b/apps/web/app/api/auth/demo/route.ts @@ -2,6 +2,7 @@ import { getAuth } from '@/lib/auth'; import { getDBService } from '@/lib/database'; import { proxyAuthRequest, shouldProxyAuthRequest } from '@/lib/auth/auth-proxy'; import { ensureDemoConnection } from '@/lib/demo/ensure-demo-connection'; +import { createProvisionedOrganization } from '@/lib/auth/organization-provisioning'; import { NextRequest, NextResponse } from 'next/server'; export const runtime = 'nodejs'; @@ -40,10 +41,7 @@ function rewriteSetCookie(value: string, isSecureRequest: boolean): string { const parts = value.split(';'); const [nameValue, ...attrs] = parts; const normalizedAttrs = attrs.map(attr => attr.trim()); - const isClearingCookie = - /=\s*$/.test(nameValue) || - normalizedAttrs.some(attr => /^max-age=0$/i.test(attr)) || - normalizedAttrs.some(attr => /^expires=/i.test(attr)); + const isClearingCookie = /=\s*$/.test(nameValue) || normalizedAttrs.some(attr => /^max-age=0$/i.test(attr)) || normalizedAttrs.some(attr => /^expires=/i.test(attr)); let rewrittenNameValue = nameValue; if (!isSecureRequest && /^__Secure-/i.test(nameValue)) { @@ -149,13 +147,12 @@ export async function POST(req: NextRequest) { const existingMemberships = await db.organizations.listByUser(userId); if (existingMemberships.length === 0) { const name = `${DEMO_USER.name}'s Workspace`; - await auth.api.createOrganization({ - body: { - name, - slug: `${slugifyOrganizationName(name)}-${userId.slice(0, 8)}`, - userId, - keepCurrentActiveOrganization: false, - }, + await createProvisionedOrganization({ + auth, + userId, + name, + slug: `${slugifyOrganizationName(name)}-${userId.slice(0, 8)}`, + provisioningKind: 'manual', }); } diff --git a/apps/web/app/api/chat/route.ts b/apps/web/app/api/chat/route.ts index 46f515b9..f58cbfab 100644 --- a/apps/web/app/api/chat/route.ts +++ b/apps/web/app/api/chat/route.ts @@ -1,14 +1,6 @@ import 'server-only'; import { NextRequest } from 'next/server'; -import { - convertToModelMessages, - createUIMessageStream, - createUIMessageStreamResponse, - readUIMessageStream, - type ModelMessage, - type UIMessage, - type UIMessageChunk, -} from 'ai'; +import { convertToModelMessages, createUIMessageStream, createUIMessageStreamResponse, readUIMessageStream, type ModelMessage, type UIMessage, type UIMessageChunk } from 'ai'; import { getModelPresetOnly } from '@/lib/ai/model'; import { compileSystemPrompt } from '@/lib/ai/model/compile-system'; import { isMissingAiEnvError } from '@/lib/ai/errors'; @@ -86,14 +78,9 @@ async function handleChatRequest(req: NextRequest) { /* 1) normalize + history */ /* ------------------------------------------------------------------ */ - const uiMessages: UIMessage[] = Array.isArray(rawMessages) - ? rawMessages.map(normalizeMessage) - : []; + const uiMessages: UIMessage[] = Array.isArray(rawMessages) ? rawMessages.map(normalizeMessage) : []; - const historyMessagesForModel = - uiMessages.length > MAX_HISTORY_MESSAGES - ? uiMessages.slice(-MAX_HISTORY_MESSAGES) - : uiMessages; + const historyMessagesForModel = uiMessages.length > MAX_HISTORY_MESSAGES ? uiMessages.slice(-MAX_HISTORY_MESSAGES) : uiMessages; /* ------------------------------------------------------------------ */ /* 2) auth / context */ @@ -102,8 +89,7 @@ async function handleChatRequest(req: NextRequest) { const session = await getSessionFromRequest(req); const userId = session?.user?.id ?? null; const organizationId = resolveCurrentOrganizationId(session); - const connectionId = - connectionIdFromBody ?? req.headers.get('x-connection-id') ?? null; + const connectionId = connectionIdFromBody ?? req.headers.get('x-connection-id') ?? null; const preset = getModelPresetOnly('chat'); const providerModelName = requestedModel || preset.model; @@ -125,15 +111,15 @@ async function handleChatRequest(req: NextRequest) { const sessionMetadata = userId && (chatId || tabId) ? { - requestedModel: requestedModel ?? null, - providerModel: providerModelName, - webSearch: Boolean(webSearch), - database: database ?? null, - table: table ?? null, - connectionId: connectionId ?? null, - tabId: tabId ?? null, - copilotContext: copilotEnvelope ? toPromptContext(copilotEnvelope) : null, - } + requestedModel: requestedModel ?? null, + providerModel: providerModelName, + webSearch: Boolean(webSearch), + database: database ?? null, + table: table ?? null, + connectionId: connectionId ?? null, + tabId: tabId ?? null, + copilotContext: copilotEnvelope ? toPromptContext(copilotEnvelope) : null, + } : null; /* ------------------------------------------------------------------ */ @@ -239,68 +225,33 @@ async function handleChatRequest(req: NextRequest) { const schemaSection = schemaContext ? `Schema Context\n${schemaContext}` : typeof tableSchema === 'string' && tableSchema.trim() - ? `Database Context\n${tableSchema.trim()}` - : ''; - - const copilotContextSection = - copilotEnvelope - ? `Copilot Context\n${JSON.stringify(toPromptContext(copilotEnvelope), null, 2)}` - : ''; - - const systemPrompt = [ - compiledSystem, - SYSTEM_PROMPT, - copilotContextSection, - schemaSection, - ] - .filter(Boolean) - .join('\n\n'); - - const modelMessages = await convertToModelMessages( - historyMessagesForModel, - { tools }, - ); - - const currentUserMessage = - uiMessages.find( - m => (m as any)?.id === requestMessageId && m.role === 'user', - ) ?? - [...uiMessages].reverse().find(m => m.role === 'user'); - - const currentUserMessageId = - typeof (currentUserMessage as any)?.id === 'string' && - (currentUserMessage as any).id - ? (currentUserMessage as any).id - : requestMessageId || null; + ? `Database Context\n${tableSchema.trim()}` + : ''; + + const copilotContextSection = copilotEnvelope ? `Copilot Context\n${JSON.stringify(toPromptContext(copilotEnvelope), null, 2)}` : ''; + + const systemPrompt = [compiledSystem, SYSTEM_PROMPT, copilotContextSection, schemaSection].filter(Boolean).join('\n\n'); + + const modelMessages = await convertToModelMessages(historyMessagesForModel, { tools }); + + const currentUserMessage = uiMessages.find(m => (m as any)?.id === requestMessageId && m.role === 'user') ?? [...uiMessages].reverse().find(m => m.role === 'user'); + + const currentUserMessageId = typeof (currentUserMessage as any)?.id === 'string' && (currentUserMessage as any).id ? (currentUserMessage as any).id : requestMessageId || null; const existedMessageIds = new Set(); for (const m of uiMessages) { - const id = - typeof (m as any)?.id === 'string' && (m as any).id - ? (m as any).id - : null; + const id = typeof (m as any)?.id === 'string' && (m as any).id ? (m as any).id : null; if (!id) continue; - if ( - currentUserMessageId && - m.role === 'user' && - id === currentUserMessageId - ) { - continue; + if (currentUserMessageId && m.role === 'user' && id === currentUserMessageId) { + continue; } existedMessageIds.add(id); } - if ( - db && - userId && - organizationId && - chatId && - currentUserMessage && - currentUserMessageId - ) { + if (db && userId && organizationId && chatId && currentUserMessage && currentUserMessageId) { try { await db.chat.appendMessage({ organizationId, @@ -348,9 +299,7 @@ async function handleChatRequest(req: NextRequest) { }; const forwardedModel = baseCloudPayload.model ?? null; - let initialCloudResponse: Awaited< - ReturnType - > | null = null; + let initialCloudResponse: Awaited> | null = null; try { console.info(useCloud ? '[chat] cloud request start' : '[chat] local request start', { @@ -409,24 +358,15 @@ async function handleChatRequest(req: NextRequest) { return; } - const [streamForClient, streamForProcessing] = - cloudStream.tee(); - const [streamForMessages, streamForTools] = - streamForProcessing.tee(); + const [streamForClient, streamForProcessing] = cloudStream.tee(); + const [streamForMessages, streamForTools] = streamForProcessing.tee(); writer.merge(streamForClient); - const [assistantMessage, toolCalls] = await Promise.all([ - readFinalAssistantMessage(streamForMessages), - collectToolCalls(streamForTools), - ]); + const [assistantMessage, toolCalls] = await Promise.all([readFinalAssistantMessage(streamForMessages), collectToolCalls(streamForTools)]); if (assistantMessage && db && userId && organizationId && chatId) { - const messageId = - typeof (assistantMessage as any)?.id === 'string' && - (assistantMessage as any).id - ? (assistantMessage as any).id - : newEntityId(); + const messageId = typeof (assistantMessage as any)?.id === 'string' && (assistantMessage as any).id ? (assistantMessage as any).id : newEntityId(); if (!existedMessageIds.has(messageId)) { try { @@ -442,8 +382,7 @@ async function handleChatRequest(req: NextRequest) { connectionId: connectionId ?? null, role: assistantMessage.role as any, parts: ((assistantMessage as any).parts ?? []) as any, - metadata: - (assistantMessage as any).metadata ?? null, + metadata: (assistantMessage as any).metadata ?? null, createdAt: new Date(), }, }); @@ -468,9 +407,7 @@ async function handleChatRequest(req: NextRequest) { } executedToolCallIds.add(toolCall.toolCallId); - toolResultMessages.push( - buildToolCallModelMessage(toolCall), - ); + toolResultMessages.push(buildToolCallModelMessage(toolCall)); if (!tools[toolCall.toolName]?.execute) { const errorText = `Tool not available: ${toolCall.toolName}`; @@ -501,12 +438,9 @@ async function handleChatRequest(req: NextRequest) { let toolErrorText: string | null = null; try { - toolOutput = await tools[toolCall.toolName].execute( - toolCall.input, - ); + toolOutput = await tools[toolCall.toolName].execute(toolCall.input); } catch (err) { - toolErrorText = - err instanceof Error ? err.message : String(err); + toolErrorText = err instanceof Error ? err.message : String(err); } if (toolErrorText) { @@ -536,9 +470,7 @@ async function handleChatRequest(req: NextRequest) { toolCallId: toolCall.toolCallId, output: toolOutput, } as UIMessageChunk); - toolResultMessages.push( - buildToolResultModelMessage(toolCall, toolOutput), - ); + toolResultMessages.push(buildToolResultModelMessage(toolCall, toolOutput)); if (isManualExecutionRequiredSqlResult(toolOutput)) { shouldStopAfterToolResults = true; } @@ -548,13 +480,8 @@ async function handleChatRequest(req: NextRequest) { const toolMessageId = newEntityId(); try { const ok = - toolOutput && - typeof toolOutput === 'object' && - 'ok' in (toolOutput as Record) - ? Boolean( - (toolOutput as Record) - .ok, - ) + toolOutput && typeof toolOutput === 'object' && 'ok' in (toolOutput as Record) + ? Boolean((toolOutput as Record).ok) : toolErrorText === null; await db.chat.appendMessage({ @@ -631,9 +558,7 @@ type CollectedToolCall = { input: unknown; }; -async function collectToolCalls( - stream: ReadableStream, -): Promise { +async function collectToolCalls(stream: ReadableStream): Promise { const reader = stream.getReader(); const toolCalls: CollectedToolCall[] = []; @@ -641,11 +566,7 @@ async function collectToolCalls( const { value, done } = await reader.read(); if (done) break; - if ( - value.type === 'tool-input-available' && - !value.providerExecuted && - typeof value.toolName === 'string' - ) { + if (value.type === 'tool-input-available' && !value.providerExecuted && typeof value.toolName === 'string') { toolCalls.push({ toolCallId: value.toolCallId, toolName: value.toolName, @@ -657,9 +578,7 @@ async function collectToolCalls( return toolCalls; } -async function readFinalAssistantMessage( - stream: ReadableStream, -): Promise { +async function readFinalAssistantMessage(stream: ReadableStream): Promise { let lastMessage: UIMessage | null = null; const iterable = readUIMessageStream({ stream }); for await (const message of iterable) { @@ -669,9 +588,7 @@ async function readFinalAssistantMessage( return lastMessage; } -function buildToolCallModelMessage( - toolCall: CollectedToolCall, -): ModelMessage { +function buildToolCallModelMessage(toolCall: CollectedToolCall): ModelMessage { return { role: 'assistant', content: [ @@ -685,10 +602,7 @@ function buildToolCallModelMessage( } as ModelMessage; } -function buildToolResultModelMessage( - toolCall: CollectedToolCall, - output: unknown, -): ModelMessage { +function buildToolResultModelMessage(toolCall: CollectedToolCall, output: unknown): ModelMessage { return { role: 'tool', content: [ diff --git a/apps/web/app/api/chat/session/[sessionId]/route.ts b/apps/web/app/api/chat/session/[sessionId]/route.ts index db663458..71ef1a4a 100644 --- a/apps/web/app/api/chat/session/[sessionId]/route.ts +++ b/apps/web/app/api/chat/session/[sessionId]/route.ts @@ -51,7 +51,7 @@ function serializeMessage(message: ChatMessageRecord) { * => { session, messages } */ export async function GET(req: NextRequest, { params }: { params: Promise<{ sessionId: string }> }) { - return withUserAndOrganizationHandler(async ({ db, userId, organizationId }) => { + return withUserAndOrganizationHandler(async ({ db, session, userId, organizationId }) => { const locale = await getApiLocale(); const { sessionId } = await params; console.log('Fetching chat session detail for sessionId:', sessionId); @@ -88,7 +88,6 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ sess organizationId, sessionId, userId, - }); return NextResponse.json( @@ -123,9 +122,9 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ sess } export async function PATCH(req: NextRequest, { params }: { params: Promise<{ sessionId: string }> }) { - return withUserAndOrganizationHandler(async ({ db, userId, organizationId }) => { + return withUserAndOrganizationHandler(async ({ db, session, userId, organizationId }) => { const locale = await getApiLocale(); - const { sessionId } = await params + const { sessionId } = await params; if (!sessionId) { return NextResponse.json( ResponseUtil.error({ @@ -221,9 +220,9 @@ export async function PATCH(req: NextRequest, { params }: { params: Promise<{ se } export async function DELETE(req: NextRequest, { params }: { params: Promise<{ sessionId: string }> }) { - return withUserAndOrganizationHandler(async ({ db, userId, organizationId }) => { + return withUserAndOrganizationHandler(async ({ db, session, userId, organizationId }) => { const locale = await getApiLocale(); - const { sessionId } = await params + const { sessionId } = await params; if (!sessionId) { return NextResponse.json( ResponseUtil.error({ @@ -237,11 +236,9 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ s try { if (!db?.chat) throw new Error('Chat repository not available'); - if (typeof (db.chat as any).archiveSession === 'function') { await (db.chat as any).archiveSession({ organizationId, sessionId, userId }); } else { - await (db.chat as any).deleteSession({ organizationId, sessionId, userId }); } diff --git a/apps/web/app/api/chat/session/copilot/route.ts b/apps/web/app/api/chat/session/copilot/route.ts index adf84c94..00898225 100644 --- a/apps/web/app/api/chat/session/copilot/route.ts +++ b/apps/web/app/api/chat/session/copilot/route.ts @@ -36,7 +36,7 @@ function serializeSession(session: ChatSessionRecord) { /** * POST /api/chat/session/copilot */ -export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, organizationId }) => { +export const POST = withUserAndOrganizationHandler(async ({ req, db, session, userId, organizationId }) => { const locale = await getApiLocale(); let payload: any = null; try { @@ -58,18 +58,16 @@ export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, org } const context = envelope?.context && typeof envelope.context === 'object' ? envelope.context : null; - const connectionId = - typeof envelope?.meta?.connectionId === 'string' ? envelope.meta.connectionId : null; + const connectionId = typeof envelope?.meta?.connectionId === 'string' ? envelope.meta.connectionId : null; const activeDatabase = envelope?.surface === 'sql' ? typeof context?.baseline?.database === 'string' ? context.baseline.database : null : typeof context?.database === 'string' - ? context.database - : null; - const activeSchema = - envelope?.surface === 'table' && typeof context?.table?.schema === 'string' ? context.table.schema : null; + ? context.database + : null; + const activeSchema = envelope?.surface === 'table' && typeof context?.table?.schema === 'string' ? context.table.schema : null; try { if (!db?.chat) throw new Error('Chat repository not available'); @@ -82,10 +80,7 @@ export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, org activeDatabase, activeSchema, metadata: envelope ? { copilotEnvelope: envelope } : null, - title: - envelope?.surface === 'table' && typeof context?.table?.name === 'string' && context.table.name.trim() - ? context.table.name.trim() - : null, + title: envelope?.surface === 'table' && typeof context?.table?.name === 'string' && context.table.name.trim() ? context.table.name.trim() : null, }); return NextResponse.json( @@ -99,12 +94,7 @@ export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, org const status = error.code === 403 ? 403 : error.code === 404 ? 404 : 500; return NextResponse.json( ResponseUtil.error({ - code: - status === 403 - ? ErrorCodes.UNAUTHORIZED - : status === 404 - ? ErrorCodes.NOT_FOUND - : ErrorCodes.DATABASE_ERROR, + code: status === 403 ? ErrorCodes.UNAUTHORIZED : status === 404 ? ErrorCodes.NOT_FOUND : ErrorCodes.DATABASE_ERROR, message: error.message, }), { status }, @@ -125,7 +115,7 @@ export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, org /** * GET /api/chat/session/copilot?tabId=... */ -export const GET = withUserAndOrganizationHandler(async ({ req, db, userId, organizationId }) => { +export const GET = withUserAndOrganizationHandler(async ({ req, db, session, userId, organizationId }) => { const locale = await getApiLocale(); const { searchParams } = new URL(req.url); const tabId = (searchParams.get('tabId') ?? '').trim(); @@ -154,12 +144,7 @@ export const GET = withUserAndOrganizationHandler(async ({ req, db, userId, orga const status = error.code === 403 ? 403 : error.code === 404 ? 404 : 500; return NextResponse.json( ResponseUtil.error({ - code: - status === 403 - ? ErrorCodes.UNAUTHORIZED - : status === 404 - ? ErrorCodes.NOT_FOUND - : ErrorCodes.DATABASE_ERROR, + code: status === 403 ? ErrorCodes.UNAUTHORIZED : status === 404 ? ErrorCodes.NOT_FOUND : ErrorCodes.DATABASE_ERROR, message: error.message, }), { status }, diff --git a/apps/web/app/api/chat/sessions/route.ts b/apps/web/app/api/chat/sessions/route.ts index 85fe51e3..89b3b458 100644 --- a/apps/web/app/api/chat/sessions/route.ts +++ b/apps/web/app/api/chat/sessions/route.ts @@ -5,7 +5,6 @@ import type { ChatSessionRecord, ChatSessionType } from '@/types'; import { withUserAndOrganizationHandler } from '@/app/api/utils/with-organization-handler'; import { getApiLocale, translateApi } from '@/app/api/utils/i18n'; - function serializeSession(session: ChatSessionRecord) { const toIso = (value: Date | number | null | undefined) => { if (!value) return null; @@ -32,7 +31,7 @@ function serializeSession(session: ChatSessionRecord) { /** * GET /api/chat/sessions?type=global|copilot */ -export const GET = withUserAndOrganizationHandler(async ({ req, db, userId, organizationId }) => { +export const GET = withUserAndOrganizationHandler(async ({ req, db, session, userId, organizationId }) => { const locale = await getApiLocale(); const { searchParams } = new URL(req.url); const type = (searchParams.get('type') as ChatSessionType | null) ?? 'global'; @@ -89,7 +88,7 @@ export const GET = withUserAndOrganizationHandler(async ({ req, db, userId, orga /** * POST /api/chat/sessions */ -export const POST = withUserAndOrganizationHandler(async ({ req, db, userId, organizationId }) => { +export const POST = withUserAndOrganizationHandler(async ({ req, db, session, userId, organizationId }) => { const locale = await getApiLocale(); console.log('POST /api/chat/sessions called', userId, organizationId); diff --git a/apps/web/app/api/organizations/create/route.ts b/apps/web/app/api/organizations/create/route.ts new file mode 100644 index 00000000..a99b3c17 --- /dev/null +++ b/apps/web/app/api/organizations/create/route.ts @@ -0,0 +1,39 @@ +import { NextResponse } from 'next/server'; +import { z } from 'zod'; +import { getAuth } from '@/lib/auth'; +import { createProvisionedOrganization } from '@/lib/auth/organization-provisioning'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +const createOrganizationSchema = z.object({ + name: z.string().trim().min(1), + slug: z.string().trim().min(1), +}); + +export async function POST(req: Request) { + const auth = await getAuth(); + const session = await auth.api.getSession({ headers: req.headers }).catch(() => null); + + if (!session?.user?.id) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); + } + + const payload = await req.json().catch(() => null); + const parsed = createOrganizationSchema.safeParse(payload); + + if (!parsed.success) { + return NextResponse.json({ message: 'Invalid organization payload' }, { status: 400 }); + } + + const organization = await createProvisionedOrganization({ + auth, + headers: req.headers, + userId: session.user.id, + name: parsed.data.name, + slug: parsed.data.slug, + provisioningKind: 'manual', + }); + + return NextResponse.json(organization); +} diff --git a/apps/web/app/api/utils/full-account.ts b/apps/web/app/api/utils/full-account.ts new file mode 100644 index 00000000..116b397d --- /dev/null +++ b/apps/web/app/api/utils/full-account.ts @@ -0,0 +1,24 @@ +import { NextResponse } from 'next/server'; +import { ResponseUtil } from '@/lib/result'; +import { ErrorCodes } from '@/lib/errors'; +import { Locale } from '@/lib/i18n/routing'; +import { translateApi } from './i18n'; + +type SessionLike = { + user?: Record | null; +} | null; + +export function requireFullAccount(session: SessionLike, locale: Locale) { + const isAnonymous = Boolean((session?.user as { isAnonymous?: boolean | null } | null | undefined)?.isAnonymous); + if (session?.user && !isAnonymous) { + return null; + } + + return NextResponse.json( + ResponseUtil.error({ + code: ErrorCodes.FORBIDDEN, + message: translateApi('Api.Chat.Errors.FullAccountRequired', undefined, locale), + }), + { status: 403 }, + ); +} diff --git a/apps/web/app/welcome/page.client.tsx b/apps/web/app/welcome/page.client.tsx new file mode 100644 index 00000000..ac2b56ad --- /dev/null +++ b/apps/web/app/welcome/page.client.tsx @@ -0,0 +1,106 @@ +'use client'; + +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { Loader2, Sparkles, ArrowRight } from 'lucide-react'; +import { useTranslations } from 'next-intl'; +import { authClient } from '@/lib/auth-client'; +import { Button } from '@/registry/new-york-v4/ui/button'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/registry/new-york-v4/ui/card'; +import { HeroBackground } from '../(auth)/components/bg'; + +type WelcomePageClientProps = { + resumeAnonymousSession?: boolean; +}; + +export default function WelcomePageClient({ resumeAnonymousSession = false }: WelcomePageClientProps) { + const t = useTranslations('Welcome'); + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + async function handleStart() { + setError(null); + setLoading(true); + + try { + if (!resumeAnonymousSession) { + const result = await authClient.signIn.anonymous(); + if (result?.error) { + throw new Error(result.error.message || t('Errors.StartFailed')); + } + } + + const response = await fetch('/api/auth/anonymous/bootstrap', { + method: 'POST', + credentials: 'include', + }); + const payload = await response.json().catch(() => null); + + if (!response.ok || !payload?.organizationSlug) { + throw new Error(typeof payload?.error === 'string' ? payload.error : t('Errors.StartFailed')); + } + + router.refresh(); + router.push(`/${payload.organizationSlug}/connections`); + } catch (nextError) { + setError(nextError instanceof Error ? nextError.message : t('Errors.StartFailed')); + } finally { + setLoading(false); + } + } + + return ( +
+ +
+
+
+ + {t('Badge')} +
+
+

{t('Title')}

+

{t('Description')}

+
+
+
{t('Highlights.Instant')}
+
{t('Highlights.Private')}
+
{t('Highlights.Upgrade')}
+
+
+ + + + {t('CardTitle')} + {t('CardDescription')} + + + {error ?
{error}
: null} + +
{t('Hint')}
+
+ {t('HaveAccount')} + + {t('SignIn')} + +
+
+
+
+
+ ); +} diff --git a/apps/web/app/welcome/page.tsx b/apps/web/app/welcome/page.tsx new file mode 100644 index 00000000..c92f27f4 --- /dev/null +++ b/apps/web/app/welcome/page.tsx @@ -0,0 +1,4 @@ +export default async function WelcomePage() { + const { redirect } = await import('next/navigation'); + redirect('/sign-in'); +} diff --git a/apps/web/components/auth/account-required-sheet.tsx b/apps/web/components/auth/account-required-sheet.tsx new file mode 100644 index 00000000..3a2822df --- /dev/null +++ b/apps/web/components/auth/account-required-sheet.tsx @@ -0,0 +1,59 @@ +'use client'; + +import { useEffect, useMemo, useState } from 'react'; +import { usePathname, useSearchParams } from 'next/navigation'; +import { Lock, MessageSquareText } from 'lucide-react'; +import { useTranslations } from 'next-intl'; +import { authClient } from '@/lib/auth-client'; +import { Button } from '@/registry/new-york-v4/ui/button'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/registry/new-york-v4/ui/card'; +import { AuthLinkSheet } from './auth-link-sheet'; + +type AccountRequiredSheetProps = { + compact?: boolean; +}; + +export function AccountRequiredSheet({ compact = false }: AccountRequiredSheetProps) { + const t = useTranslations('Chatbot'); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const { data: session } = authClient.useSession(); + const [open, setOpen] = useState(false); + + const callbackURL = useMemo(() => { + const query = searchParams?.toString(); + return query ? `${pathname}?${query}` : pathname || '/'; + }, [pathname, searchParams]); + + useEffect(() => { + if (session?.user && !session.user.isAnonymous) { + setOpen(false); + } + }, [session]); + + const card = ( + + +
+ +
+ {t('AuthRequired.Title')} + {t('AuthRequired.Description')} +
+ + +

{t('AuthRequired.Hint')}

+
+
+ ); + + return ( + <> +
{card}
+ + + ); +} diff --git a/apps/web/components/auth/auth-link-sheet.tsx b/apps/web/components/auth/auth-link-sheet.tsx new file mode 100644 index 00000000..f5b7d1eb --- /dev/null +++ b/apps/web/components/auth/auth-link-sheet.tsx @@ -0,0 +1,52 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { authClient } from '@/lib/auth-client'; +import { SignInForm } from '@/app/(auth)/components/SignInForm'; +import { SignUpForm } from '@/app/(auth)/components/SignUpform'; +import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/registry/new-york-v4/ui/sheet'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/registry/new-york-v4/ui/tabs'; + +type AuthLinkSheetProps = { + open: boolean; + onOpenChange: (open: boolean) => void; + callbackURL: string; +}; + +export function AuthLinkSheet({ open, onOpenChange, callbackURL }: AuthLinkSheetProps) { + const t = useTranslations('Chatbot'); + const { data: session } = authClient.useSession(); + const [tab, setTab] = useState<'sign-in' | 'sign-up'>('sign-in'); + + useEffect(() => { + if (session?.user && !session.user.isAnonymous) { + onOpenChange(false); + } + }, [onOpenChange, session]); + + return ( + + +
+ + {t('AuthRequired.SheetTitle')} + {t('AuthRequired.SheetDescription')} + + setTab(value as 'sign-in' | 'sign-up')} className="pb-8 pt-4"> + + {t('AuthRequired.SignInTab')} + {t('AuthRequired.SignUpTab')} + + + setTab('sign-up')} showDemoOption={false} showGuestOption={false} /> + + + setTab('sign-in')} /> + + +
+
+
+ ); +} diff --git a/apps/web/lib/auth-client.ts b/apps/web/lib/auth-client.ts index 7f63c0f0..a16588b9 100644 --- a/apps/web/lib/auth-client.ts +++ b/apps/web/lib/auth-client.ts @@ -3,7 +3,7 @@ import { dashClient, sentinelClient } from '@better-auth/infra/client'; import { stripeClient } from '@better-auth/stripe/client'; import { createAuthClient } from 'better-auth/react'; -import { inferOrgAdditionalFields, organizationClient } from 'better-auth/client/plugins'; +import { anonymousClient, inferOrgAdditionalFields, organizationClient } from 'better-auth/client/plugins'; import { translate } from '@/lib/i18n/i18n'; import { getClientLocale } from '@/lib/i18n/client-locale'; import { getAuthBaseUrl } from '@/lib/client/auth-runtime'; @@ -21,6 +21,7 @@ export const authClient = createAuthClient({ sentinelClient({ autoSolveChallenge: true, }), + anonymousClient(), organizationClient({ ac: organizationAc, roles: organizationRoles, diff --git a/apps/web/lib/auth.ts b/apps/web/lib/auth.ts index f2c7a8c0..ca5ba1f3 100644 --- a/apps/web/lib/auth.ts +++ b/apps/web/lib/auth.ts @@ -1,6 +1,6 @@ import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; -import { jwt, organization } from 'better-auth/plugins'; +import { anonymous, jwt, organization } from 'better-auth/plugins'; import { stripe as stripePlugin } from '@better-auth/stripe'; import { dash, sentinel } from '@better-auth/infra'; import Stripe from 'stripe'; @@ -13,16 +13,20 @@ import { getDatabaseProvider } from './database/provider'; import { schema } from './database/schema'; import { sendEmail } from './email'; import { resolveOrganizationIdForSession, shouldCreateDefaultOrganization } from './auth/migration-state'; +import { createProvisionedOrganization } from './auth/organization-provisioning'; import { translate } from './i18n/i18n'; import { getServerLocale } from './i18n/server-locale'; import { isBillingEnabledForServer, isDesktopRuntime } from './runtime/runtime'; import { organizationAc, organizationRoles } from './auth/organization-ac'; import { canManageOrganizationBilling } from './billing/authz'; +import { buildDefaultOrganizationValues, linkAnonymousOrganizationToUser } from './auth/anonymous'; +import { isAnonymousUser } from './auth/anonymous-user'; type AuthUser = { id: string; email: string | null; emailVerified: boolean; + isAnonymous?: boolean; }; type SessionWithActiveOrganization = { @@ -30,16 +34,6 @@ type SessionWithActiveOrganization = { activeOrganizationId?: string | null; }; -function slugifyOrganizationName(name: string) { - const normalized = name - .toLowerCase() - .trim() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-+|-+$/g, ''); - - return normalized || 'workspace'; -} - function createAuth() { return (async () => { const db = (await getClient()) as PostgresDBClient; @@ -166,17 +160,13 @@ function createAuth() { return; } - const locale = await getServerLocale(); - const t = (key: string, values?: Record) => translate(locale, key, values); - const name = t('Auth.TeamName', { name: email ?? t('Auth.TeamDefaultName') }); - - const created = await auth.api.createOrganization({ - body: { - name, - slug: `${slugifyOrganizationName(name)}-${userId.slice(0, 8)}`, - userId, - keepCurrentActiveOrganization: false, - }, + const defaults = await buildDefaultOrganizationValues(userId, email); + const created = await createProvisionedOrganization({ + auth, + userId, + name: defaults.name, + slug: defaults.slug, + provisioningKind: 'system_default', }); const organizationId = created?.id ?? null; @@ -195,6 +185,19 @@ function createAuth() { database: drizzleAdapter(db, { provider, schema }), plugins: [ ...authPlugins, + anonymous({ + emailDomainName: 'anon.getdory.dev', + generateName: () => 'Guest', + onLinkAccount: async ({ anonymousUser, newUser }) => { + await linkAnonymousOrganizationToUser({ + anonymousUserId: anonymousUser.user.id, + anonymousActiveOrganizationId: anonymousUser.session.activeOrganizationId ?? null, + newUserId: newUser.user.id, + newSessionToken: newUser.session.token, + newActiveOrganizationId: newUser.session.activeOrganizationId ?? null, + }); + }, + }), organization({ ac: organizationAc, roles: organizationRoles, @@ -223,6 +226,11 @@ function createAuth() { required: false, input: false, }, + provisioningKind: { + type: 'string', + required: false, + input: false, + }, }, }, member: { @@ -319,7 +327,7 @@ function createAuth() { }), ...(stripeBillingEnabled ? [ - stripePlugin({ + stripePlugin({ stripeClient: stripeClient!, stripeWebhookSecret, createCustomerOnSignUp: false, @@ -440,6 +448,10 @@ function createAuth() { after: async rawUser => { const user = rawUser as AuthUser; + if (isAnonymousUser(user)) { + return; + } + // Skip if the user is already attached to an organization. const existingOrganizationId = await findInitialOrganizationId(user.id); @@ -577,6 +589,17 @@ function createAuth() { return; } + if (request?.headers) { + const anonymousSession = await auth.api + .getSession({ + headers: request.headers, + }) + .catch(() => null); + if (isAnonymousUser(anonymousSession?.user)) { + return; + } + } + await ensureDefaultOrganizationForUser(auth as any, user.id, user.email); console.log(`[auth] user ${user.email} verified by email, default organization created via afterEmailVerification`); }, diff --git a/apps/web/lib/auth/anonymous-delete.ts b/apps/web/lib/auth/anonymous-delete.ts new file mode 100644 index 00000000..08325cfa --- /dev/null +++ b/apps/web/lib/auth/anonymous-delete.ts @@ -0,0 +1,22 @@ +import { NextResponse } from 'next/server'; + +export function isLocalAnonymousDeleteRequest(pathname: string) { + return pathname.endsWith('/delete-anonymous-user'); +} + +export function buildAnonymousDeleteResponse(req: Request) { + const response = NextResponse.json({ success: true }); + const isSecureRequest = new URL(req.url).protocol === 'https:'; + const cookieOptions = { + path: '/', + maxAge: 0, + httpOnly: true, + sameSite: 'lax' as const, + secure: isSecureRequest, + }; + + response.cookies.set('better-auth.session_token', '', cookieOptions); + response.cookies.set('__Secure-better-auth.session_token', '', cookieOptions); + + return response; +} diff --git a/apps/web/lib/auth/anonymous-lifecycle/bootstrap.ts b/apps/web/lib/auth/anonymous-lifecycle/bootstrap.ts new file mode 100644 index 00000000..6accfbaa --- /dev/null +++ b/apps/web/lib/auth/anonymous-lifecycle/bootstrap.ts @@ -0,0 +1,58 @@ +import { eq } from 'drizzle-orm'; +import { createProvisionedOrganization } from '@/lib/auth/organization-provisioning'; +import { schema } from '@/lib/database/schema'; +import { AuthSessionLike, buildAnonymousOrganizationValues, findFirstActiveOrganizationIdForUser, getDb } from './common'; + +export async function bootstrapAnonymousOrganization(params: { auth: any; session: AuthSessionLike; headers?: Headers }) { + const db = await getDb(); + const userId = params.session.user?.id ?? null; + const sessionToken = params.session.session?.token ?? null; + + if (!userId || !sessionToken) { + throw new Error('missing_anonymous_session'); + } + + let organizationId = params.session.session?.activeOrganizationId ?? (await findFirstActiveOrganizationIdForUser(db, userId)); + + if (!organizationId) { + const defaults = await buildAnonymousOrganizationValues(userId); + const created = await createProvisionedOrganization({ + auth: params.auth, + headers: params.headers, + userId, + name: defaults.name, + slug: defaults.slug, + provisioningKind: 'anonymous', + }); + + organizationId = created?.id ?? null; + if (!organizationId) { + throw new Error(`failed_to_create_default_organization_for_${userId}`); + } + } + + const [organization] = await db + .select({ + id: schema.organizations.id, + slug: schema.organizations.slug, + name: schema.organizations.name, + provisioningKind: schema.organizations.provisioningKind, + }) + .from(schema.organizations) + .where(eq(schema.organizations.id, organizationId)) + .limit(1); + + if (!organization) { + throw new Error(`organization_not_found_for_${organizationId}`); + } + + await db + .update(schema.session) + .set({ + activeOrganizationId: organization.id, + updatedAt: new Date(), + }) + .where(eq(schema.session.token, sessionToken)); + + return organization; +} diff --git a/apps/web/lib/auth/anonymous-lifecycle/common.ts b/apps/web/lib/auth/anonymous-lifecycle/common.ts new file mode 100644 index 00000000..526ffea6 --- /dev/null +++ b/apps/web/lib/auth/anonymous-lifecycle/common.ts @@ -0,0 +1,113 @@ +import { and, eq, inArray, isNull, or } from 'drizzle-orm'; +import type { PostgresDBClient } from '@/types'; +import { getServerLocale } from '@/lib/i18n/server-locale'; +import { translate } from '@/lib/i18n/i18n'; +import { getClient } from '@/lib/database/postgres/client'; +import type { OrganizationProvisioningKind } from '@/lib/database/postgres/schemas'; +import { schema } from '@/lib/database/schema'; + +export type AuthSessionLike = { + session?: { + token?: string | null; + activeOrganizationId?: string | null; + } | null; + user?: { + id?: string | null; + email?: string | null; + isAnonymous?: boolean | null; + } | null; +}; + +export type AnonymousOrganizationRow = { + id: string; + slug: string | null; + name: string; + provisioningKind: OrganizationProvisioningKind | null; +}; + +function slugifyOrganizationName(name: string) { + const normalized = name + .toLowerCase() + .trim() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); + + return normalized || 'workspace'; +} + +export async function buildAnonymousOrganizationValues(userId: string) { + const locale = await getServerLocale(); + const t = (key: string, values?: Record) => translate(locale, key, values); + const name = t('Auth.AnonymousWorkspace.Name'); + + return { + name, + slug: `${slugifyOrganizationName(name)}-${userId.slice(0, 8)}`, + }; +} + +export async function buildDefaultOrganizationValues(userId: string, email: string | null | undefined) { + const locale = await getServerLocale(); + const t = (key: string, values?: Record) => translate(locale, key, values); + const name = t('Auth.TeamName', { name: email ?? t('Auth.TeamDefaultName') }); + + return { + name, + slug: `${slugifyOrganizationName(name)}-${userId.slice(0, 8)}`, + }; +} + +export async function getDb() { + return (await getClient()) as PostgresDBClient; +} + +export async function findFirstActiveOrganizationIdForUser(db: PostgresDBClient, userId: string) { + const [membership] = await db + .select({ organizationId: schema.organizationMembers.organizationId }) + .from(schema.organizationMembers) + .where(and(eq(schema.organizationMembers.userId, userId), or(eq(schema.organizationMembers.status, 'active'), isNull(schema.organizationMembers.status)))) + .limit(1); + + return membership?.organizationId ?? null; +} + +export async function findOwnedOrganizationIdsForUser(db: Pick, userId: string) { + const organizations = await db.select({ id: schema.organizations.id }).from(schema.organizations).where(eq(schema.organizations.ownerUserId, userId)); + + return organizations.map(organization => organization.id); +} + +export async function findAnonymousOrganizationIdsForLink( + db: PostgresDBClient, + params: { + anonymousUserId: string; + anonymousActiveOrganizationId?: string | null; + }, +) { + const organizationIds = [ + params.anonymousActiveOrganizationId ?? null, + await findFirstActiveOrganizationIdForUser(db, params.anonymousUserId), + ...(await findOwnedOrganizationIdsForUser(db, params.anonymousUserId)), + ].filter((organizationId): organizationId is string => Boolean(organizationId)); + + return [...new Set(organizationIds)]; +} + +export async function normalizeAnonymousSourceOrganizations(tx: Pick, organizations: AnonymousOrganizationRow[]) { + const organizationIdsToBackfill = organizations.filter(organization => organization.provisioningKind == null).map(organization => organization.id); + + if (organizationIdsToBackfill.length > 0) { + await tx + .update(schema.organizations) + .set({ + provisioningKind: 'anonymous', + updatedAt: new Date(), + }) + .where(inArray(schema.organizations.id, organizationIdsToBackfill)); + } + + return organizations.map(organization => ({ + ...organization, + provisioningKind: organization.provisioningKind ?? 'anonymous', + })); +} diff --git a/apps/web/lib/auth/anonymous-lifecycle/delete.ts b/apps/web/lib/auth/anonymous-lifecycle/delete.ts new file mode 100644 index 00000000..b48f01e2 --- /dev/null +++ b/apps/web/lib/auth/anonymous-lifecycle/delete.ts @@ -0,0 +1,114 @@ +import { and, eq, inArray } from 'drizzle-orm'; +import { schema } from '@/lib/database/schema'; +import type { PostgresDBClient } from '@/types'; +import { findOwnedOrganizationIdsForUser, getDb } from './common'; + +export const anonymousDeleteCleanupTableCoverage = { + connectionIdentityScoped: ['connectionIdentitySecrets'], + connectionScoped: ['connectionSsh', 'tabs', 'aiSchemaCache', 'syncOperations'], + organizationScoped: [ + 'chatMessages', + 'chatSessionState', + 'chatSessions', + 'savedQueries', + 'savedQueryFolders', + 'queryAudit', + 'aiUsageEvents', + 'aiUsageTraces', + 'invitation', + 'organizationMembers', + 'connectionIdentities', + 'connections', + 'organizations', + ], +} as const; + +export const anonymousMergeCleanupTableCoverage = { + organizationScoped: ['queryAudit', 'aiUsageEvents', 'aiUsageTraces', 'invitation'], +} as const; + +type DeleteAnonymousUserResult = { + organizationIds: string[]; + deletedOrganizations: number; +}; + +export async function cleanupNonMigratedAnonymousOrganizations( + tx: Pick, + organizationIds: string[], +) { + if (organizationIds.length === 0) { + return; + } + + await tx.delete(schema.queryAudit).where(inArray(schema.queryAudit.organizationId, organizationIds)); + await tx.delete(schema.aiUsageEvents).where(inArray(schema.aiUsageEvents.organizationId, organizationIds)); + await tx.delete(schema.aiUsageTraces).where(inArray(schema.aiUsageTraces.organizationId, organizationIds)); + await tx.delete(schema.invitation).where(inArray(schema.invitation.organizationId, organizationIds)); +} + +async function cleanupAnonymousOrganizationsWithTx( + tx: Pick, + userId: string, +): Promise { + const organizationIds = await findOwnedOrganizationIdsForUser(tx, userId); + + if (organizationIds.length === 0) { + return { organizationIds: [], deletedOrganizations: 0 }; + } + + const connections = await tx.select({ id: schema.connections.id }).from(schema.connections).where(inArray(schema.connections.organizationId, organizationIds)); + const connectionIds = connections.map(connection => connection.id); + + const connectionIdentities = connectionIds.length + ? await tx.select({ id: schema.connectionIdentities.id }).from(schema.connectionIdentities).where(inArray(schema.connectionIdentities.connectionId, connectionIds)) + : []; + const connectionIdentityIds = connectionIdentities.map(identity => identity.id); + + if (connectionIdentityIds.length > 0) { + await tx.delete(schema.connectionIdentitySecrets).where(inArray(schema.connectionIdentitySecrets.identityId, connectionIdentityIds)); + } + + if (connectionIds.length > 0) { + await tx.delete(schema.connectionSsh).where(inArray(schema.connectionSsh.connectionId, connectionIds)); + await tx.delete(schema.tabs).where(inArray(schema.tabs.connectionId, connectionIds)); + await tx.delete(schema.aiSchemaCache).where(inArray(schema.aiSchemaCache.connectionId, connectionIds)); + await tx.delete(schema.syncOperations).where(and(eq(schema.syncOperations.entityType, 'connection'), inArray(schema.syncOperations.entityId, connectionIds))); + } + + if (connectionIdentityIds.length > 0) { + await tx + .delete(schema.syncOperations) + .where(and(eq(schema.syncOperations.entityType, 'connection_identity'), inArray(schema.syncOperations.entityId, connectionIdentityIds))); + } + + await tx.delete(schema.chatMessages).where(inArray(schema.chatMessages.organizationId, organizationIds)); + await tx.delete(schema.chatSessionState).where(inArray(schema.chatSessionState.organizationId, organizationIds)); + await tx.delete(schema.chatSessions).where(inArray(schema.chatSessions.organizationId, organizationIds)); + await tx.delete(schema.savedQueries).where(inArray(schema.savedQueries.organizationId, organizationIds)); + await tx.delete(schema.savedQueryFolders).where(inArray(schema.savedQueryFolders.organizationId, organizationIds)); + await cleanupNonMigratedAnonymousOrganizations(tx, organizationIds); + await tx.delete(schema.organizationMembers).where(inArray(schema.organizationMembers.organizationId, organizationIds)); + await tx.delete(schema.connectionIdentities).where(inArray(schema.connectionIdentities.organizationId, organizationIds)); + await tx.delete(schema.connections).where(inArray(schema.connections.organizationId, organizationIds)); + await tx.delete(schema.organizations).where(inArray(schema.organizations.id, organizationIds)); + + return { + organizationIds, + deletedOrganizations: organizationIds.length, + }; +} + +export async function cleanupAnonymousUserOrganizations(userId: string) { + const db = await getDb(); + return db.transaction(async tx => cleanupAnonymousOrganizationsWithTx(tx, userId)); +} + +export async function deleteAnonymousUserLocally(userId: string) { + const db = await getDb(); + + return db.transaction(async tx => { + const cleanupResult = await cleanupAnonymousOrganizationsWithTx(tx, userId); + await tx.delete(schema.user).where(eq(schema.user.id, userId)); + return cleanupResult; + }); +} diff --git a/apps/web/lib/auth/anonymous-lifecycle/link.ts b/apps/web/lib/auth/anonymous-lifecycle/link.ts new file mode 100644 index 00000000..1473456f --- /dev/null +++ b/apps/web/lib/auth/anonymous-lifecycle/link.ts @@ -0,0 +1,187 @@ +import { and, eq, inArray, isNull, or } from 'drizzle-orm'; +import { schema } from '@/lib/database/schema'; +import { mergeAnonymousOrganizationIntoExistingOrganization, migrateAnonymousOrganizationOwnership } from '@/lib/database/postgres/impl/organization/anonymous-resource-merge'; +import { resolveAnonymousOrganizationLinkDecision } from '../anonymous-link-strategy'; +import { + findAnonymousOrganizationIdsForLink, + getDb, + normalizeAnonymousSourceOrganizations, +} from './common'; +import { cleanupNonMigratedAnonymousOrganizations } from './delete'; + +export async function linkAnonymousOrganizationToUser(params: { + anonymousUserId: string; + anonymousActiveOrganizationId?: string | null; + newUserId: string; + newSessionToken?: string | null; + newActiveOrganizationId?: string | null; +}) { + const db = await getDb(); + const sourceOrganizationIds = await findAnonymousOrganizationIdsForLink(db, { + anonymousUserId: params.anonymousUserId, + anonymousActiveOrganizationId: params.anonymousActiveOrganizationId, + }); + + if (sourceOrganizationIds.length === 0) { + return null; + } + + const primarySourceOrganizationId = sourceOrganizationIds[0]; + + const resultOrganization = await db.transaction(async tx => { + const preexistingMemberships = await tx + .select({ organizationId: schema.organizationMembers.organizationId }) + .from(schema.organizationMembers) + .where(and(eq(schema.organizationMembers.userId, params.newUserId), or(eq(schema.organizationMembers.status, 'active'), isNull(schema.organizationMembers.status)))); + + const sourceOrganizationsRaw = await tx + .select({ + id: schema.organizations.id, + slug: schema.organizations.slug, + name: schema.organizations.name, + provisioningKind: schema.organizations.provisioningKind, + }) + .from(schema.organizations) + .where(inArray(schema.organizations.id, sourceOrganizationIds)); + + const sourceOrganizationOrder = new Map(sourceOrganizationIds.map((organizationId, index) => [organizationId, index])); + const sourceOrganizations = (await normalizeAnonymousSourceOrganizations(tx, sourceOrganizationsRaw)).sort( + (left, right) => (sourceOrganizationOrder.get(left.id) ?? Number.MAX_SAFE_INTEGER) - (sourceOrganizationOrder.get(right.id) ?? Number.MAX_SAFE_INTEGER), + ); + + if (sourceOrganizations.length === 0) { + return null; + } + + const primarySourceOrganization = sourceOrganizations.find(organization => organization.id === primarySourceOrganizationId) ?? sourceOrganizations[0]!; + const targetCandidateOrganizationIds = [...new Set(preexistingMemberships.map(membership => membership.organizationId))]; + const targetCandidateOrganizations = targetCandidateOrganizationIds.length + ? await tx + .select({ + id: schema.organizations.id, + slug: schema.organizations.slug, + name: schema.organizations.name, + provisioningKind: schema.organizations.provisioningKind, + }) + .from(schema.organizations) + .where(inArray(schema.organizations.id, targetCandidateOrganizationIds)) + : []; + + const linkDecision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations, + userOrganizations: targetCandidateOrganizations, + newActiveOrganizationId: params.newActiveOrganizationId, + }); + + if (!linkDecision) { + return null; + } + + if (linkDecision.action === 'merge' && linkDecision.targetOrganizationId) { + const mergeResults = []; + + for (const sourceOrganization of sourceOrganizations) { + const mergeResult = await mergeAnonymousOrganizationIntoExistingOrganization(tx, { + sourceOrganizationId: sourceOrganization.id, + targetOrganizationId: linkDecision.targetOrganizationId, + anonymousUserId: params.anonymousUserId, + newUserId: params.newUserId, + }); + + await cleanupNonMigratedAnonymousOrganizations(tx, [sourceOrganization.id]); + await tx.delete(schema.organizationMembers).where(eq(schema.organizationMembers.organizationId, sourceOrganization.id)); + await tx.delete(schema.organizations).where(eq(schema.organizations.id, sourceOrganization.id)); + + mergeResults.push(mergeResult); + } + + if (params.newSessionToken) { + await tx + .update(schema.session) + .set({ + activeOrganizationId: linkDecision.targetOrganizationId, + updatedAt: new Date(), + }) + .where(eq(schema.session.token, params.newSessionToken)); + } + + console.log('[auth] merged guest organizations into existing organization', mergeResults); + + const [targetOrganization] = await tx + .select({ + id: schema.organizations.id, + slug: schema.organizations.slug, + name: schema.organizations.name, + provisioningKind: schema.organizations.provisioningKind, + }) + .from(schema.organizations) + .where(eq(schema.organizations.id, linkDecision.targetOrganizationId)) + .limit(1); + + return targetOrganization ?? null; + } + + const migrationResults = []; + + for (const sourceOrganization of sourceOrganizations) { + await tx + .update(schema.organizations) + .set({ + ownerUserId: params.newUserId, + provisioningKind: 'anonymous_promoted', + updatedAt: new Date(), + }) + .where(eq(schema.organizations.id, sourceOrganization.id)); + + const [existingMembership] = await tx + .select({ id: schema.organizationMembers.id }) + .from(schema.organizationMembers) + .where(and(eq(schema.organizationMembers.organizationId, sourceOrganization.id), eq(schema.organizationMembers.userId, params.newUserId))) + .limit(1); + + if (existingMembership) { + await tx + .update(schema.organizationMembers) + .set({ + role: 'owner', + status: 'active', + joinedAt: new Date(), + }) + .where(eq(schema.organizationMembers.id, existingMembership.id)); + } else { + await tx.insert(schema.organizationMembers).values({ + userId: params.newUserId, + organizationId: sourceOrganization.id, + role: 'owner', + status: 'active', + joinedAt: new Date(), + }); + } + + const migrationResult = await migrateAnonymousOrganizationOwnership(tx, { + sourceOrganizationId: sourceOrganization.id, + targetOrganizationId: sourceOrganization.id, + anonymousUserId: params.anonymousUserId, + newUserId: params.newUserId, + }); + + migrationResults.push(migrationResult); + } + + if (params.newSessionToken) { + await tx + .update(schema.session) + .set({ + activeOrganizationId: linkDecision.primarySourceOrganizationId, + updatedAt: new Date(), + }) + .where(eq(schema.session.token, params.newSessionToken)); + } + + console.log('[auth] reassigned guest organization ownership to linked user', migrationResults); + + return sourceOrganizations.find(sourceOrganization => sourceOrganization.id === linkDecision.primarySourceOrganizationId) ?? primarySourceOrganization; + }); + + return resultOrganization; +} diff --git a/apps/web/lib/auth/anonymous-link-strategy.ts b/apps/web/lib/auth/anonymous-link-strategy.ts new file mode 100644 index 00000000..39a64c6a --- /dev/null +++ b/apps/web/lib/auth/anonymous-link-strategy.ts @@ -0,0 +1,60 @@ +import type { OrganizationProvisioningKind } from '@/lib/database/postgres/schemas'; + +export type AnonymousLinkOrganizationRecord = { + id: string; + provisioningKind: OrganizationProvisioningKind | null; +}; + +export type AnonymousOrganizationLinkDecision = { + action: 'merge' | 'promote'; + primarySourceOrganizationId: string; + sourceOrganizationIds: string[]; + targetOrganizationId: string | null; +}; + +export function resolveAnonymousOrganizationLinkDecision(input: { + sourceOrganizations: AnonymousLinkOrganizationRecord[]; + userOrganizations: AnonymousLinkOrganizationRecord[]; + newActiveOrganizationId?: string | null; +}): AnonymousOrganizationLinkDecision | null { + const sourceOrganizations = input.sourceOrganizations.filter(organization => organization.provisioningKind === 'anonymous'); + + if (sourceOrganizations.length === 0) { + return null; + } + + const sourceOrganizationIds = sourceOrganizations.map(organization => organization.id); + const sourceOrganizationIdSet = new Set(sourceOrganizationIds); + const primarySourceOrganizationId = sourceOrganizationIds[0]!; + const userOrganizations = input.userOrganizations.filter(organization => !sourceOrganizationIdSet.has(organization.id)); + + const explicitActiveOrganization = input.newActiveOrganizationId ? (userOrganizations.find(organization => organization.id === input.newActiveOrganizationId) ?? null) : null; + + if (explicitActiveOrganization) { + return { + action: 'merge', + primarySourceOrganizationId, + sourceOrganizationIds, + targetOrganizationId: explicitActiveOrganization.id, + }; + } + + const systemDefaultOrganizations = userOrganizations.filter(organization => organization.provisioningKind === 'system_default'); + const hasBlockingOrganizations = userOrganizations.some(organization => organization.provisioningKind !== 'system_default'); + + if (systemDefaultOrganizations.length === 1 && !hasBlockingOrganizations) { + return { + action: 'merge', + primarySourceOrganizationId, + sourceOrganizationIds, + targetOrganizationId: systemDefaultOrganizations[0]!.id, + }; + } + + return { + action: 'promote', + primarySourceOrganizationId, + sourceOrganizationIds, + targetOrganizationId: null, + }; +} diff --git a/apps/web/lib/auth/anonymous-user.ts b/apps/web/lib/auth/anonymous-user.ts new file mode 100644 index 00000000..15649f5f --- /dev/null +++ b/apps/web/lib/auth/anonymous-user.ts @@ -0,0 +1,4 @@ +export function isAnonymousUser(user: unknown) { + const candidate = user as { isAnonymous?: boolean | null } | null | undefined; + return Boolean(candidate?.isAnonymous); +} diff --git a/apps/web/lib/auth/anonymous.ts b/apps/web/lib/auth/anonymous.ts new file mode 100644 index 00000000..e8663d5d --- /dev/null +++ b/apps/web/lib/auth/anonymous.ts @@ -0,0 +1,10 @@ +export { bootstrapAnonymousOrganization } from './anonymous-lifecycle/bootstrap'; +export { buildDefaultOrganizationValues } from './anonymous-lifecycle/common'; +export { + anonymousDeleteCleanupTableCoverage, + anonymousMergeCleanupTableCoverage, + cleanupAnonymousUserOrganizations, + cleanupNonMigratedAnonymousOrganizations, + deleteAnonymousUserLocally, +} from './anonymous-lifecycle/delete'; +export { linkAnonymousOrganizationToUser } from './anonymous-lifecycle/link'; diff --git a/apps/web/lib/auth/migration-state.ts b/apps/web/lib/auth/migration-state.ts index b951746c..2e3bad9b 100644 --- a/apps/web/lib/auth/migration-state.ts +++ b/apps/web/lib/auth/migration-state.ts @@ -9,6 +9,7 @@ type TicketUserInput = { name: string | null; image: string | null; emailVerified: boolean; + isAnonymous?: boolean; activeOrganizationId?: string | null; }; @@ -16,11 +17,7 @@ export function resolveOrganizationIdForSession(input: OrganizationResolutionInp return input.activeOrganizationId ?? input.membershipOrganizationId ?? null; } -export function shouldCreateDefaultOrganization(input: { - isDesktop: boolean; - existingOrganizationId?: string | null; - emailVerified: boolean; -}): boolean { +export function shouldCreateDefaultOrganization(input: { isDesktop: boolean; existingOrganizationId?: string | null; emailVerified: boolean }): boolean { if (input.isDesktop) { return false; } @@ -32,9 +29,7 @@ export function shouldCreateDefaultOrganization(input: { return input.emailVerified; } -export function resolveOrganizationIdFromTicket(input: { - activeOrganizationId?: string | null; -}): string | null { +export function resolveOrganizationIdFromTicket(input: { activeOrganizationId?: string | null }): string | null { return input.activeOrganizationId ?? null; } @@ -47,13 +42,12 @@ export function buildElectronTicketUser(input: TicketUserInput) { name: input.name, image: input.image, emailVerified: input.emailVerified, + isAnonymous: input.isAnonymous ?? false, activeOrganizationId, }; } -export function buildSessionOrganizationPatch(input: { - activeOrganizationId?: string | null; -}) { +export function buildSessionOrganizationPatch(input: { activeOrganizationId?: string | null }) { const activeOrganizationId = resolveOrganizationIdFromTicket(input); return activeOrganizationId ? { activeOrganizationId } : null; } diff --git a/apps/web/lib/auth/organization-provisioning.ts b/apps/web/lib/auth/organization-provisioning.ts new file mode 100644 index 00000000..3474de62 --- /dev/null +++ b/apps/web/lib/auth/organization-provisioning.ts @@ -0,0 +1,63 @@ +import { eq } from 'drizzle-orm'; +import { getClient } from '@/lib/database/postgres/client'; +import { schema } from '@/lib/database/schema'; +import type { PostgresDBClient } from '@/types'; +import type { OrganizationProvisioningKind } from '@/lib/database/postgres/schemas'; + +type CreateProvisionedOrganizationParams = { + auth: any; + userId: string; + name: string; + slug: string; + provisioningKind: OrganizationProvisioningKind; + headers?: Headers; + keepCurrentActiveOrganization?: boolean; +}; + +async function getDb() { + return (await getClient()) as PostgresDBClient; +} + +export async function createProvisionedOrganization(params: CreateProvisionedOrganizationParams) { + const created = await params.auth.api.createOrganization({ + headers: params.headers ?? new Headers(), + body: { + name: params.name, + slug: params.slug, + userId: params.userId, + keepCurrentActiveOrganization: params.keepCurrentActiveOrganization ?? false, + }, + }); + + const organizationId = created?.id ?? null; + if (!organizationId) { + throw new Error(`failed_to_create_organization_for_${params.userId}`); + } + + const db = await getDb(); + await db + .update(schema.organizations) + .set({ + provisioningKind: params.provisioningKind, + updatedAt: new Date(), + }) + .where(eq(schema.organizations.id, organizationId)); + + const [organization] = await db + .select({ + id: schema.organizations.id, + slug: schema.organizations.slug, + name: schema.organizations.name, + createdAt: schema.organizations.createdAt, + provisioningKind: schema.organizations.provisioningKind, + }) + .from(schema.organizations) + .where(eq(schema.organizations.id, organizationId)) + .limit(1); + + if (!organization) { + throw new Error(`organization_not_found_for_${organizationId}`); + } + + return organization; +} diff --git a/apps/web/lib/database/pglite/migrations.json b/apps/web/lib/database/pglite/migrations.json index 1608b9a2..7292531c 100644 --- a/apps/web/lib/database/pglite/migrations.json +++ b/apps/web/lib/database/pglite/migrations.json @@ -133,6 +133,14 @@ "folderMillis": 1774367010423, "hash": "9a2a9241dd708fa08461678f152ff3f1f62efc0331b467ff8eafb45bc3712a92" }, + { + "sql": [ + "ALTER TABLE \"user\" ADD COLUMN \"is_anonymous\" boolean DEFAULT false NOT NULL;\n" + ], + "bps": true, + "folderMillis": 1774538755994, + "hash": "651a13178dfa1d12a979e0fae46abc2c081ace29c9f3f36864d2242a8f64fead" + }, { "sql": [ "ALTER TABLE \"connections\" ALTER COLUMN \"host\" DROP NOT NULL;", @@ -140,7 +148,15 @@ "\nALTER TABLE \"connections\" ADD COLUMN \"path\" text;" ], "bps": true, - "folderMillis": 1774596423872, + "folderMillis": 1775056342854, "hash": "0f8ec7eeaecfacbe82ec3e05e43a0b2da8b8cba8f122e9bb401d794c10a5191e" + }, + { + "sql": [ + "ALTER TABLE \"organizations\" ADD COLUMN \"provisioning_kind\" text;" + ], + "bps": true, + "folderMillis": 1775064413388, + "hash": "c645e6c65c2200c70cc36b161acf697d63796db70e2b376a4427f131bd6337bb" } ] \ No newline at end of file diff --git a/apps/web/lib/database/pglite/migrations/0005_good_vector.sql b/apps/web/lib/database/pglite/migrations/0005_good_vector.sql new file mode 100644 index 00000000..d45df687 --- /dev/null +++ b/apps/web/lib/database/pglite/migrations/0005_good_vector.sql @@ -0,0 +1 @@ +ALTER TABLE "user" ADD COLUMN "is_anonymous" boolean DEFAULT false NOT NULL; diff --git a/apps/web/lib/database/pglite/migrations/0006_aberrant_texas_twister.sql b/apps/web/lib/database/pglite/migrations/0006_aberrant_texas_twister.sql new file mode 100644 index 00000000..0862566b --- /dev/null +++ b/apps/web/lib/database/pglite/migrations/0006_aberrant_texas_twister.sql @@ -0,0 +1,3 @@ +ALTER TABLE "connections" ALTER COLUMN "host" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "connections" ALTER COLUMN "port" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "connections" ADD COLUMN "path" text; \ No newline at end of file diff --git a/apps/web/lib/database/pglite/migrations/0007_empty_supernaut.sql b/apps/web/lib/database/pglite/migrations/0007_empty_supernaut.sql new file mode 100644 index 00000000..25144bdd --- /dev/null +++ b/apps/web/lib/database/pglite/migrations/0007_empty_supernaut.sql @@ -0,0 +1 @@ +ALTER TABLE "organizations" ADD COLUMN "provisioning_kind" text; \ No newline at end of file diff --git a/apps/web/lib/database/pglite/migrations/meta/0005_snapshot.json b/apps/web/lib/database/pglite/migrations/meta/0005_snapshot.json index 174bbff8..6575a84e 100644 --- a/apps/web/lib/database/pglite/migrations/meta/0005_snapshot.json +++ b/apps/web/lib/database/pglite/migrations/meta/0005_snapshot.json @@ -1,3654 +1,3628 @@ { - "id": "856812aa-7a03-4dcb-9ec7-95ea819dee90", - "prevId": "9d513f21-35a1-4e5b-a6be-a508eee18912", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.tabs": { - "name": "tabs", - "schema": "", - "columns": { - "tab_id": { - "name": "tab_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "tab_type": { - "name": "tab_type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'sql'" - }, - "tab_name": { - "name": "tab_name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'New Query'" - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "database_name": { - "name": "database_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "table_name": { - "name": "table_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_sub_tab": { - "name": "active_sub_tab", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'data'" - }, - "content": { - "name": "content", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "state": { - "name": "state", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "result_meta": { - "name": "result_meta", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "order_index": { - "name": "order_index", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.account": { - "name": "account", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "account_id": { - "name": "account_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token_expires_at": { - "name": "access_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "refresh_token_expires_at": { - "name": "refresh_token_expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "account_user_id_user_id_fk": { - "name": "account_user_id_user_id_fk", - "tableFrom": "account", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invitation": { - "name": "invitation", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "inviter_id": { - "name": "inviter_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": { - "idx_invitation_organization_id": { - "name": "idx_invitation_organization_id", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_invitation_email": { - "name": "idx_invitation_email", - "columns": [ - { - "expression": "email", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_invitation_status": { - "name": "idx_invitation_status", - "columns": [ - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.jwks": { - "name": "jwks", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "alg": { - "name": "alg", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "crv": { - "name": "crv", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "public_key": { - "name": "public_key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "private_key": { - "name": "private_key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.session": { - "name": "session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "active_organization_id": { - "name": "active_organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "session_token_unique": { - "name": "session_token_unique", - "nullsNotDistinct": false, - "columns": [ - "token" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.subscription": { - "name": "subscription", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "plan": { - "name": "plan", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "reference_id": { - "name": "reference_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "stripe_customer_id": { - "name": "stripe_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_subscription_id": { - "name": "stripe_subscription_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'incomplete'" - }, - "period_start": { - "name": "period_start", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "period_end": { - "name": "period_end", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "trial_start": { - "name": "trial_start", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "trial_end": { - "name": "trial_end", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "cancel_at_period_end": { - "name": "cancel_at_period_end", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "cancel_at": { - "name": "cancel_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "canceled_at": { - "name": "canceled_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "ended_at": { - "name": "ended_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "seats": { - "name": "seats", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "billing_interval": { - "name": "billing_interval", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_schedule_id": { - "name": "stripe_schedule_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "idx_subscription_reference_id": { - "name": "idx_subscription_reference_id", - "columns": [ - { - "expression": "reference_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_subscription_stripe_subscription_id": { - "name": "idx_subscription_stripe_subscription_id", - "columns": [ - { - "expression": "stripe_subscription_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_subscription_stripe_customer_id": { - "name": "idx_subscription_stripe_customer_id", - "columns": [ - { - "expression": "stripe_customer_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.user": { - "name": "user", - "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 - }, - "email_verified": { - "name": "email_verified", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_customer_id": { - "name": "stripe_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_active_at": { - "name": "last_active_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.verification": { - "name": "verification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "text", - "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()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_messages": { - "name": "chat_messages", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "session_id": { - "name": "session_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "parts": { - "name": "parts", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "idx_chat_messages_session_time": { - "name": "idx_chat_messages_session_time", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "id": "a2d3cc57-e0b5-44fd-ac4c-9e639b42cdf6", + "prevId": "9d513f21-35a1-4e5b-a6be-a508eee18912", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "session_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_messages_session_id": { - "name": "idx_chat_messages_session_id", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } }, - { - "expression": "session_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } }, - { - "expression": "id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_messages_organization_conn_time": { - "name": "idx_chat_messages_organization_conn_time", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_session_state": { - "name": "chat_session_state", - "schema": "", - "columns": { - "session_id": { - "name": "session_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_tab_id": { - "name": "active_tab_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_database": { - "name": "active_database", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_schema": { - "name": "active_schema", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "editor_context": { - "name": "editor_context", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "last_run_summary": { - "name": "last_run_summary", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "stable_context": { - "name": "stable_context", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "revision": { - "name": "revision", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - } - }, - "indexes": { - "idx_chat_state_organization_conn": { - "name": "idx_chat_state_organization_conn", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_state_organization_tab": { - "name": "idx_chat_state_organization_tab", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } }, - { - "expression": "active_tab_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_state_organization_updated": { - "name": "idx_chat_state_organization_updated", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } }, - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.chat_sessions": { - "name": "chat_sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'copilot'" - }, - "tab_id": { - "name": "tab_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_database": { - "name": "active_database", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_schema": { - "name": "active_schema", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "settings": { - "name": "settings", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "archived_at": { - "name": "archived_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "last_message_at": { - "name": "last_message_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "idx_chat_sessions_list": { - "name": "idx_chat_sessions_list", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "archived_at", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "last_message_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_sessions_organization_user_type": { - "name": "idx_chat_sessions_organization_user_type", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "type", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_sessions_organization_conn": { - "name": "idx_chat_sessions_organization_conn", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_chat_sessions_organization_db": { - "name": "idx_chat_sessions_organization_db", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "active_database", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "uidx_chat_sessions_copilot_tab": { - "name": "uidx_chat_sessions_copilot_tab", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "tab_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"chat_sessions\".\"type\" = 'copilot'", - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "uq_chat_sessions_id_organization": { - "name": "uq_chat_sessions_id_organization", - "nullsNotDistinct": false, - "columns": [ - "id", - "organization_id" - ] - } - }, - "policies": {}, - "checkConstraints": { - "ck_chat_sessions_type_tab": { - "name": "ck_chat_sessions_type_tab", - "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" - } - }, - "isRLSEnabled": false - }, - "public.query_audit": { - "name": "query_audit", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "tab_id": { - "name": "tab_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source": { - "name": "source", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "connection_name": { - "name": "connection_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "database_name": { - "name": "database_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "query_id": { - "name": "query_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "sql_text": { - "name": "sql_text", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "error_message": { - "name": "error_message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "duration_ms": { - "name": "duration_ms", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "rows_read": { - "name": "rows_read", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "bytes_read": { - "name": "bytes_read", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "rows_written": { - "name": "rows_written", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "extra_json": { - "name": "extra_json", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "idx_organization_created": { - "name": "idx_organization_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_source_created": { - "name": "idx_source_created", - "columns": [ - { - "expression": "source", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_query_id": { - "name": "idx_query_id", - "columns": [ - { - "expression": "query_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.members": { - "name": "members", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'member'" - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "joined_at": { - "name": "joined_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "members_organization_id_user_id_unique": { - "name": "members_organization_id_user_id_unique", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": ["id", "organization_id"] + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_members_organization": { - "name": "idx_members_organization", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_members_user": { - "name": "idx_members_user", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "members_user_id_user_id_fk": { - "name": "members_user_id_user_id_fk", - "tableFrom": "members", - "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "members_organization_id_organizations_id_fk": { - "name": "members_organization_id_organizations_id_fk", - "tableFrom": "members", - "tableTo": "organizations", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organizations": { - "name": "organizations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "owner_user_id": { - "name": "owner_user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "logo": { - "name": "logo", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripe_customer_id": { - "name": "stripe_customer_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "organizations_slug_unique": { - "name": "organizations_slug_unique", - "columns": [ - { - "expression": "slug", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "organizations_owner_user_id_user_id_fk": { - "name": "organizations_owner_user_id_user_id_fk", - "tableFrom": "organizations", - "tableTo": "user", - "columnsFrom": [ - "owner_user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.connection_identities": { - "name": "connection_identities", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_by_user_id": { - "name": "created_by_user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source": { - "name": "source", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'local'" - }, - "cloud_id": { - "name": "cloud_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "sync_status": { - "name": "sync_status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'local_only'" - }, - "last_synced_at": { - "name": "last_synced_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "remote_updated_at": { - "name": "remote_updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "sync_error": { - "name": "sync_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "is_default": { - "name": "is_default", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "database": { - "name": "database", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'active'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "uniq_conn_identity_connection_name": { - "name": "uniq_conn_identity_connection_name", - "columns": [ - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } }, - { - "expression": "name", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"connection_identities\".\"deleted_at\" IS NULL", - "concurrently": false, - "method": "btree", - "with": {} - }, - "uniq_conn_identity_cloud_id": { - "name": "uniq_conn_identity_cloud_id", - "columns": [ - { - "expression": "cloud_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", - "concurrently": false, - "method": "btree", - "with": {} - }, - "uniq_conn_identity_default_per_connection": { - "name": "uniq_conn_identity_default_per_connection", - "columns": [ - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_connection_id": { - "name": "idx_conn_identity_connection_id", - "columns": [ - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_created_by_user_id": { - "name": "idx_conn_identity_created_by_user_id", - "columns": [ - { - "expression": "created_by_user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_organization_id": { - "name": "idx_conn_identity_organization_id", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_enabled": { - "name": "idx_conn_identity_enabled", - "columns": [ - { - "expression": "enabled", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_sync_status": { - "name": "idx_conn_identity_sync_status", - "columns": [ - { - "expression": "sync_status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_conn_identity_organization_cloud_id": { - "name": "idx_conn_identity_organization_cloud_id", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "cloud_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.connection_identity_secrets": { - "name": "connection_identity_secrets", - "schema": "", - "columns": { - "identity_id": { - "name": "identity_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "password_encrypted": { - "name": "password_encrypted", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "vault_ref": { - "name": "vault_ref", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret_ref": { - "name": "secret_ref", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.connection_ssh": { - "name": "connection_ssh", - "schema": "", - "columns": { - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "host": { - "name": "host", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "port": { - "name": "port", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "auth_method": { - "name": "auth_method", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password_encrypted": { - "name": "password_encrypted", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "private_key_encrypted": { - "name": "private_key_encrypted", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "passphrase_encrypted": { - "name": "passphrase_encrypted", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "chk_connection_ssh_port": { - "name": "chk_connection_ssh_port", - "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" - } - }, - "isRLSEnabled": false - }, - "public.connections": { - "name": "connections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "created_by_user_id": { - "name": "created_by_user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "source": { - "name": "source", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'local'" - }, - "cloud_id": { - "name": "cloud_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "sync_status": { - "name": "sync_status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'local_only'" - }, - "last_synced_at": { - "name": "last_synced_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "remote_updated_at": { - "name": "remote_updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "sync_error": { - "name": "sync_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "engine": { - "name": "engine", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'Untitled connection'" - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "host": { - "name": "host", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "port": { - "name": "port", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "http_port": { - "name": "http_port", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "database": { - "name": "database", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "path": { - "name": "path", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "options": { - "name": "options", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "config_version": { - "name": "config_version", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "validation_errors": { - "name": "validation_errors", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'{}'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "last_used_at": { - "name": "last_used_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "last_check_status": { - "name": "last_check_status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'unknown'" - }, - "last_check_at": { - "name": "last_check_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "last_check_latency_ms": { - "name": "last_check_latency_ms", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_check_error": { - "name": "last_check_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "environment": { - "name": "environment", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "tags": { - "name": "tags", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - } - }, - "indexes": { - "uniq_connections_organization_name": { - "name": "uniq_connections_organization_name", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "name", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"connections\".\"deleted_at\" IS NULL", - "concurrently": false, - "method": "btree", - "with": {} - }, - "uniq_connections_cloud_id": { - "name": "uniq_connections_cloud_id", - "columns": [ - { - "expression": "cloud_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "where": "\"connections\".\"cloud_id\" IS NOT NULL", - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_connections_organization_id_status": { - "name": "idx_connections_organization_id_status", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_connections_created_by_user_id": { - "name": "idx_connections_created_by_user_id", - "columns": [ - { - "expression": "created_by_user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_connections_sync_status": { - "name": "idx_connections_sync_status", - "columns": [ - { - "expression": "sync_status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_connections_organization_cloud_id": { - "name": "idx_connections_organization_cloud_id", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "cloud_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_connections_organization_env": { - "name": "idx_connections_organization_env", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } }, - { - "expression": "environment", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "chk_connections_port": { - "name": "chk_connections_port", - "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" - }, - "chk_connections_http_port": { - "name": "chk_connections_http_port", - "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" - } - }, - "isRLSEnabled": false - }, - "public.ai_schema_cache": { - "name": "ai_schema_cache", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "catalog": { - "name": "catalog", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'default'" - }, - "database_name": { - "name": "database_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "table_name": { - "name": "table_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature": { - "name": "feature", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "db_type": { - "name": "db_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "schema_hash": { - "name": "schema_hash", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "model": { - "name": "model", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "prompt_version": { - "name": "prompt_version", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "payload": { - "name": "payload", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { - "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "catalog", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": ["owner_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } }, - { - "expression": "feature", - "isExpression": false, - "asc": true, - "nulls": "last" + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "schema_hash", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "model", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } }, - { - "expression": "prompt_version", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_cache_organization_conn": { - "name": "idx_ai_cache_organization_conn", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } }, - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_cache_catalog_db_table": { - "name": "idx_ai_cache_catalog_db_table", - "columns": [ - { - "expression": "catalog", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } }, - { - "expression": "database_name", - "isExpression": false, - "asc": true, - "nulls": "last" + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } }, - { - "expression": "table_name", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_cache_schema_hash": { - "name": "idx_ai_cache_schema_hash", - "columns": [ - { - "expression": "schema_hash", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.saved_queries": { - "name": "saved_queries", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "title": { - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "sql_text": { - "name": "sql_text", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "context": { - "name": "context", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{}'::jsonb" - }, - "tags": { - "name": "tags", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "'{}'::text[]" - }, - "folder_id": { - "name": "folder_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "position": { - "name": "position", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "work_id": { - "name": "work_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "archived_at": { - "name": "archived_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "idx_saved_queries_organization_user": { - "name": "idx_saved_queries_organization_user", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_saved_queries_updated_at": { - "name": "idx_saved_queries_updated_at", - "columns": [ - { - "expression": "updated_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_saved_queries_folder_id": { - "name": "idx_saved_queries_folder_id", - "columns": [ - { - "expression": "folder_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.saved_query_folders": { - "name": "saved_query_folders", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "connection_id": { - "name": "connection_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "position": { - "name": "position", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "idx_saved_query_folders_organization_user": { - "name": "idx_saved_query_folders_organization_user", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_saved_query_folders_connection_id": { - "name": "idx_saved_query_folders_connection_id", - "columns": [ - { - "expression": "connection_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.ai_usage_events": { - "name": "ai_usage_events", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature": { - "name": "feature", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "model": { - "name": "model", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prompt_version": { - "name": "prompt_version", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "algo_version": { - "name": "algo_version", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'ok'" - }, - "error_code": { - "name": "error_code", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "error_message": { - "name": "error_message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gateway": { - "name": "gateway", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cost_micros": { - "name": "cost_micros", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "trace_id": { - "name": "trace_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "span_id": { - "name": "span_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "input_tokens": { - "name": "input_tokens", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "output_tokens": { - "name": "output_tokens", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "reasoning_tokens": { - "name": "reasoning_tokens", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "cached_input_tokens": { - "name": "cached_input_tokens", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "total_tokens": { - "name": "total_tokens", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "usage_json": { - "name": "usage_json", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "latency_ms": { - "name": "latency_ms", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "from_cache": { - "name": "from_cache", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "uidx_ai_usage_events_request_id": { - "name": "uidx_ai_usage_events_request_id", - "columns": [ - { - "expression": "request_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_events_organization_created": { - "name": "idx_ai_usage_events_organization_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_events_organization_created_total": { - "name": "idx_ai_usage_events_organization_created_total", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } }, - { - "expression": "total_tokens", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_events_organization_user_created": { - "name": "idx_ai_usage_events_organization_user_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_events_feature_created": { - "name": "idx_ai_usage_events_feature_created", - "columns": [ - { - "expression": "feature", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_events_organization_feature_created": { - "name": "idx_ai_usage_events_organization_feature_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } }, - { - "expression": "feature", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": { - "ck_ai_usage_events_status": { - "name": "ck_ai_usage_events_status", - "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" - } - }, - "isRLSEnabled": false - }, - "public.ai_usage_traces": { - "name": "ai_usage_traces", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "request_id": { - "name": "request_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "feature": { - "name": "feature", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "model": { - "name": "model", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "input_text": { - "name": "input_text", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "output_text": { - "name": "output_text", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "input_json": { - "name": "input_json", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "output_json": { - "name": "output_json", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "redacted": { - "name": "redacted", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now() + interval '180 days'" - } - }, - "indexes": { - "uidx_ai_usage_traces_request_id": { - "name": "uidx_ai_usage_traces_request_id", - "columns": [ - { - "expression": "request_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_traces_organization_created": { - "name": "idx_ai_usage_traces_organization_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_traces_organization_user_created": { - "name": "idx_ai_usage_traces_organization_user_created", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } }, - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_ai_usage_traces_expires_at": { - "name": "idx_ai_usage_traces_expires_at", - "columns": [ - { - "expression": "expires_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.sync_operations": { - "name": "sync_operations", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "entity_type": { - "name": "entity_type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'connection'" - }, - "entity_id": { - "name": "entity_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "operation": { - "name": "operation", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "payload": { - "name": "payload", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'{}'" - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "retry_count": { - "name": "retry_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "last_attempt_at": { - "name": "last_attempt_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "synced_at": { - "name": "synced_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "error_message": { - "name": "error_message", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - } - }, - "indexes": { - "idx_sync_operations_organization_status": { - "name": "idx_sync_operations_organization_status", - "columns": [ - { - "expression": "organization_id", - "isExpression": false, - "asc": true, - "nulls": "last" + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } }, - { - "expression": "status", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_sync_operations_entity": { - "name": "idx_sync_operations_entity", - "columns": [ - { - "expression": "entity_type", - "isExpression": false, - "asc": true, - "nulls": "last" + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } }, - { - "expression": "entity_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - }, - "idx_sync_operations_created_at": { - "name": "idx_sync_operations_created_at", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": {}, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, + }, + "enums": {}, "schemas": {}, - "tables": {} - } -} \ No newline at end of file + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/apps/web/lib/database/pglite/migrations/meta/0006_snapshot.json b/apps/web/lib/database/pglite/migrations/meta/0006_snapshot.json new file mode 100644 index 00000000..1dec4c3e --- /dev/null +++ b/apps/web/lib/database/pglite/migrations/meta/0006_snapshot.json @@ -0,0 +1,3661 @@ +{ + "id": "4a78a33d-4b06-4620-91f5-3f99360fa0cf", + "prevId": "a2d3cc57-e0b5-44fd-ac4c-9e639b42cdf6", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } + }, + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } + }, + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } + }, + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/web/lib/database/pglite/migrations/meta/0007_snapshot.json b/apps/web/lib/database/pglite/migrations/meta/0007_snapshot.json new file mode 100644 index 00000000..00f46ac4 --- /dev/null +++ b/apps/web/lib/database/pglite/migrations/meta/0007_snapshot.json @@ -0,0 +1,3667 @@ +{ + "id": "456685d5-a9c0-4a7d-8b48-b9c3dbfebb88", + "prevId": "4a78a33d-4b06-4620-91f5-3f99360fa0cf", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } + }, + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provisioning_kind": { + "name": "provisioning_kind", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } + }, + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } + }, + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/web/lib/database/pglite/migrations/meta/_journal.json b/apps/web/lib/database/pglite/migrations/meta/_journal.json index b286cd40..b17a4574 100644 --- a/apps/web/lib/database/pglite/migrations/meta/_journal.json +++ b/apps/web/lib/database/pglite/migrations/meta/_journal.json @@ -40,8 +40,22 @@ { "idx": 5, "version": "7", - "when": 1774596423872, - "tag": "0005_wet_jack_power", + "when": 1774538755994, + "tag": "0005_good_vector", + "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1775056342854, + "tag": "0006_aberrant_texas_twister", + "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1775064413388, + "tag": "0007_empty_supernaut", "breakpoints": true } ] diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/chat.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/chat.ts new file mode 100644 index 00000000..fac0c44d --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/chat.ts @@ -0,0 +1,64 @@ +import { and, eq } from 'drizzle-orm'; +import { schema } from '@/lib/database/schema'; +import type { AnonymousOwnershipMigration } from './types'; + +const tables = ['chatSessions', 'chatMessages', 'chatSessionState']; + +export const chatAnonymousOwnershipMigration: AnonymousOwnershipMigration = { + id: 'chat', + tables, + async migrate(tx, params) { + const movedSessions = await tx + .update(schema.chatSessions) + .set({ + organizationId: params.targetOrganizationId, + userId: params.newUserId, + updatedAt: new Date(), + }) + .where( + and( + eq(schema.chatSessions.organizationId, params.sourceOrganizationId), + eq(schema.chatSessions.userId, params.anonymousUserId), + ), + ) + .returning({ id: schema.chatSessions.id }); + + const movedMessages = await tx + .update(schema.chatMessages) + .set({ + organizationId: params.targetOrganizationId, + userId: params.newUserId, + }) + .where( + and( + eq(schema.chatMessages.organizationId, params.sourceOrganizationId), + eq(schema.chatMessages.userId, params.anonymousUserId), + ), + ) + .returning({ id: schema.chatMessages.id }); + + let chatSessionStateMoved = 0; + if (params.sourceOrganizationId !== params.targetOrganizationId) { + const movedSessionState = await tx + .update(schema.chatSessionState) + .set({ + organizationId: params.targetOrganizationId, + updatedAt: new Date(), + }) + .where(eq(schema.chatSessionState.organizationId, params.sourceOrganizationId)) + .returning({ sessionId: schema.chatSessionState.sessionId }); + + chatSessionStateMoved = movedSessionState.length; + } + + return { + id: 'chat', + tables, + counts: { + chatSessionsMoved: movedSessions.length, + chatMessagesMoved: movedMessages.length, + chatSessionStateMoved, + }, + }; + }, +}; diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/connections.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/connections.ts new file mode 100644 index 00000000..ab496a3d --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/connections.ts @@ -0,0 +1,200 @@ +import { and, eq, inArray, isNull, or } from 'drizzle-orm'; +import { schema } from '@/lib/database/schema'; +import type { AnonymousOwnershipMigration } from './types'; + +const tables = ['connections', 'connectionIdentities', 'tabs', 'aiSchemaCache', 'syncOperations']; + +function buildImportedConnectionName(baseName: string, occupiedNames: Set) { + const normalizedBaseName = baseName.trim() || 'Imported connection'; + let candidate = normalizedBaseName; + let counter = 2; + + while (occupiedNames.has(candidate)) { + candidate = `${normalizedBaseName} (${counter})`; + counter += 1; + } + + occupiedNames.add(candidate); + return candidate; +} + +export const connectionsAnonymousOwnershipMigration: AnonymousOwnershipMigration = { + id: 'connections', + tables, + async migrate(tx, params) { + const sourceConnections = await tx + .select({ + id: schema.connections.id, + name: schema.connections.name, + }) + .from(schema.connections) + .where(and(eq(schema.connections.organizationId, params.sourceOrganizationId), isNull(schema.connections.deletedAt))); + + const renamedConnections: Array<{ + id: string; + from: string; + to: string; + }> = []; + + if (params.sourceOrganizationId !== params.targetOrganizationId) { + const targetConnections = await tx + .select({ + id: schema.connections.id, + name: schema.connections.name, + }) + .from(schema.connections) + .where(and(eq(schema.connections.organizationId, params.targetOrganizationId), isNull(schema.connections.deletedAt))); + + const occupiedConnectionNames = new Set(targetConnections.map(connection => connection.name)); + for (const sourceConnection of sourceConnections) { + if (!occupiedConnectionNames.has(sourceConnection.name)) { + occupiedConnectionNames.add(sourceConnection.name); + continue; + } + + const renamedConnection = buildImportedConnectionName(sourceConnection.name, occupiedConnectionNames); + await tx + .update(schema.connections) + .set({ + name: renamedConnection, + updatedAt: new Date(), + }) + .where(eq(schema.connections.id, sourceConnection.id)); + + renamedConnections.push({ + id: sourceConnection.id, + from: sourceConnection.name, + to: renamedConnection, + }); + } + } + + const connectionIds = sourceConnections.map(connection => connection.id); + + let connectionsMoved = 0; + if (params.sourceOrganizationId !== params.targetOrganizationId && connectionIds.length > 0) { + const movedConnections = await tx + .update(schema.connections) + .set({ + organizationId: params.targetOrganizationId, + createdByUserId: params.newUserId, + updatedAt: new Date(), + }) + .where(eq(schema.connections.organizationId, params.sourceOrganizationId)) + .returning({ id: schema.connections.id }); + + connectionsMoved = movedConnections.length; + } else if (connectionIds.length > 0) { + await tx + .update(schema.connections) + .set({ + createdByUserId: params.newUserId, + updatedAt: new Date(), + }) + .where(eq(schema.connections.organizationId, params.sourceOrganizationId)); + } + + const sourceIdentities = + connectionIds.length > 0 + ? await tx + .select({ id: schema.connectionIdentities.id }) + .from(schema.connectionIdentities) + .where(inArray(schema.connectionIdentities.connectionId, connectionIds)) + : []; + + const identityIds = sourceIdentities.map(identity => identity.id); + + let connectionIdentitiesMoved = 0; + if (params.sourceOrganizationId !== params.targetOrganizationId && connectionIds.length > 0) { + const movedIdentities = await tx + .update(schema.connectionIdentities) + .set({ + organizationId: params.targetOrganizationId, + createdByUserId: params.newUserId, + updatedAt: new Date(), + }) + .where(inArray(schema.connectionIdentities.connectionId, connectionIds)) + .returning({ id: schema.connectionIdentities.id }); + + connectionIdentitiesMoved = movedIdentities.length; + } else if (connectionIds.length > 0) { + await tx + .update(schema.connectionIdentities) + .set({ + createdByUserId: params.newUserId, + updatedAt: new Date(), + }) + .where(eq(schema.connectionIdentities.organizationId, params.sourceOrganizationId)); + } + + let tabsMoved = 0; + if (connectionIds.length > 0) { + const movedTabs = await tx + .update(schema.tabs) + .set({ + userId: params.newUserId, + updatedAt: new Date(), + }) + .where(and(eq(schema.tabs.userId, params.anonymousUserId), inArray(schema.tabs.connectionId, connectionIds))) + .returning({ tabId: schema.tabs.tabId }); + + tabsMoved = movedTabs.length; + } + + let aiSchemaCacheMoved = 0; + if (params.sourceOrganizationId !== params.targetOrganizationId && connectionIds.length > 0) { + const movedCaches = await tx + .update(schema.aiSchemaCache) + .set({ + organizationId: params.targetOrganizationId, + updatedAt: new Date().toISOString(), + }) + .where( + and( + eq(schema.aiSchemaCache.organizationId, params.sourceOrganizationId), + inArray(schema.aiSchemaCache.connectionId, connectionIds), + ), + ) + .returning({ id: schema.aiSchemaCache.id }); + + aiSchemaCacheMoved = movedCaches.length; + } + + let syncOperationsMoved = 0; + if (params.sourceOrganizationId !== params.targetOrganizationId && (connectionIds.length > 0 || identityIds.length > 0)) { + const syncConditions: any[] = []; + if (connectionIds.length > 0) { + syncConditions.push(and(eq(schema.syncOperations.entityType, 'connection'), inArray(schema.syncOperations.entityId, connectionIds))); + } + if (identityIds.length > 0) { + syncConditions.push(and(eq(schema.syncOperations.entityType, 'connection_identity'), inArray(schema.syncOperations.entityId, identityIds))); + } + + const movedSyncOperations = await tx + .update(schema.syncOperations) + .set({ + organizationId: params.targetOrganizationId, + updatedAt: new Date(), + }) + .where(and(eq(schema.syncOperations.organizationId, params.sourceOrganizationId), or(...syncConditions))) + .returning({ id: schema.syncOperations.id }); + + syncOperationsMoved = movedSyncOperations.length; + } + + return { + id: 'connections', + tables, + counts: { + connectionsMoved, + connectionIdentitiesMoved, + tabsMoved, + aiSchemaCacheMoved, + syncOperationsMoved, + }, + details: { + renamedConnections, + }, + }; + }, +}; diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/registry.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/registry.ts new file mode 100644 index 00000000..72ff051a --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/registry.ts @@ -0,0 +1,61 @@ +import { chatAnonymousOwnershipMigration } from './chat'; +import { connectionsAnonymousOwnershipMigration } from './connections'; +import { savedQueriesAnonymousOwnershipMigration } from './saved-queries'; +import type { AnonymousOwnershipMigration, AnonymousOwnershipTablePolicy } from './types'; + +export const anonymousOwnershipMigrations: AnonymousOwnershipMigration[] = [ + savedQueriesAnonymousOwnershipMigration, + chatAnonymousOwnershipMigration, + connectionsAnonymousOwnershipMigration, +]; + +export const anonymousOwnershipNoMigratePolicies: AnonymousOwnershipTablePolicy[] = [ + { + table: 'account', + strategy: 'no-migrate', + reason: 'Auth account bindings are handled by better-auth and are not organization-scoped business resources.', + }, + { + table: 'invitation', + strategy: 'no-migrate', + reason: 'Anonymous workspaces do not transfer invitation rows during account linking.', + }, + { + table: 'session', + strategy: 'no-migrate', + reason: 'Session ownership is handled by auth flows outside the anonymous resource migration registry.', + }, + { + table: 'queryAudit', + strategy: 'no-migrate', + reason: 'Audit history remains immutable and is not rewritten during anonymous account upgrades.', + }, + { + table: 'organizationMembers', + strategy: 'no-migrate', + reason: 'Organization membership changes are handled by the surrounding auth linking workflow.', + }, + { + table: 'aiUsageEvents', + strategy: 'no-migrate', + reason: 'AI usage telemetry is not reassigned during anonymous account upgrades.', + }, + { + table: 'aiUsageTraces', + strategy: 'no-migrate', + reason: 'AI trace telemetry is not reassigned during anonymous account upgrades.', + }, +]; + +export function getAnonymousOwnershipTablePolicies(): AnonymousOwnershipTablePolicy[] { + return [ + ...anonymousOwnershipMigrations.flatMap(migration => + migration.tables.map(table => ({ + table, + strategy: 'migrate' as const, + migrationId: migration.id, + })), + ), + ...anonymousOwnershipNoMigratePolicies, + ]; +} diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/saved-queries.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/saved-queries.ts new file mode 100644 index 00000000..d679d01a --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/saved-queries.ts @@ -0,0 +1,50 @@ +import { and, eq } from 'drizzle-orm'; +import { schema } from '@/lib/database/schema'; +import type { AnonymousOwnershipMigration } from './types'; + +const tables = ['savedQueryFolders', 'savedQueries']; + +export const savedQueriesAnonymousOwnershipMigration: AnonymousOwnershipMigration = { + id: 'saved-queries', + tables, + async migrate(tx, params) { + const movedFolders = await tx + .update(schema.savedQueryFolders) + .set({ + organizationId: params.targetOrganizationId, + userId: params.newUserId, + updatedAt: new Date(), + }) + .where( + and( + eq(schema.savedQueryFolders.organizationId, params.sourceOrganizationId), + eq(schema.savedQueryFolders.userId, params.anonymousUserId), + ), + ) + .returning({ id: schema.savedQueryFolders.id }); + + const movedQueries = await tx + .update(schema.savedQueries) + .set({ + organizationId: params.targetOrganizationId, + userId: params.newUserId, + updatedAt: new Date(), + }) + .where( + and( + eq(schema.savedQueries.organizationId, params.sourceOrganizationId), + eq(schema.savedQueries.userId, params.anonymousUserId), + ), + ) + .returning({ id: schema.savedQueries.id }); + + return { + id: 'saved-queries', + tables, + counts: { + savedQueryFoldersMoved: movedFolders.length, + savedQueriesMoved: movedQueries.length, + }, + }; + }, +}; diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/types.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/types.ts new file mode 100644 index 00000000..b4680770 --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-migrations/types.ts @@ -0,0 +1,30 @@ +import type { PostgresDBClient } from '@/types'; + +export type AnonymousOwnershipMigrationTx = Pick; + +export type AnonymousOwnershipMigrationParams = { + sourceOrganizationId: string; + targetOrganizationId: string; + anonymousUserId: string; + newUserId: string; +}; + +export type AnonymousOwnershipMigrationResult = { + id: string; + tables: string[]; + counts: Record; + details?: Record; +}; + +export type AnonymousOwnershipMigration = { + id: string; + tables: string[]; + migrate: (tx: AnonymousOwnershipMigrationTx, params: AnonymousOwnershipMigrationParams) => Promise; +}; + +export type AnonymousOwnershipTablePolicy = { + table: string; + strategy: 'migrate' | 'no-migrate'; + migrationId?: string; + reason?: string; +}; diff --git a/apps/web/lib/database/postgres/impl/organization/anonymous-resource-merge.ts b/apps/web/lib/database/postgres/impl/organization/anonymous-resource-merge.ts new file mode 100644 index 00000000..07c8d21b --- /dev/null +++ b/apps/web/lib/database/postgres/impl/organization/anonymous-resource-merge.ts @@ -0,0 +1,80 @@ +import { anonymousOwnershipMigrations, anonymousOwnershipNoMigratePolicies, getAnonymousOwnershipTablePolicies } from './anonymous-migrations/registry'; +import type { AnonymousOwnershipMigrationParams, AnonymousOwnershipMigrationResult, AnonymousOwnershipMigrationTx } from './anonymous-migrations/types'; + +export type AnonymousOrganizationOwnershipMigrationResult = { + sourceOrganizationId: string; + targetOrganizationId: string; + renamedConnections: Array<{ + id: string; + from: string; + to: string; + }>; + tabsMoved: number; + chatSessionsMoved: number; + chatMessagesMoved: number; + chatSessionStateMoved: number; + savedQueriesMoved: number; + savedQueryFoldersMoved: number; + connectionsMoved: number; + connectionIdentitiesMoved: number; + aiSchemaCacheMoved: number; + syncOperationsMoved: number; + migrationResults: AnonymousOwnershipMigrationResult[]; + skippedTables: string[]; +}; + +export type AnonymousOrganizationMergeResult = AnonymousOrganizationOwnershipMigrationResult; + +function sumCount(results: AnonymousOwnershipMigrationResult[], key: string) { + return results.reduce((total, result) => total + (result.counts[key] ?? 0), 0); +} + +function getRenamedConnections(results: AnonymousOwnershipMigrationResult[]) { + const connectionResult = results.find(result => result.id === 'connections'); + const renamedConnections = connectionResult?.details?.renamedConnections; + return Array.isArray(renamedConnections) + ? (renamedConnections as Array<{ + id: string; + from: string; + to: string; + }>) + : []; +} + +export async function migrateAnonymousOrganizationOwnership( + tx: AnonymousOwnershipMigrationTx, + params: AnonymousOwnershipMigrationParams, +): Promise { + const migrationResults: AnonymousOwnershipMigrationResult[] = []; + + for (const migration of anonymousOwnershipMigrations) { + migrationResults.push(await migration.migrate(tx, params)); + } + + return { + sourceOrganizationId: params.sourceOrganizationId, + targetOrganizationId: params.targetOrganizationId, + renamedConnections: getRenamedConnections(migrationResults), + tabsMoved: sumCount(migrationResults, 'tabsMoved'), + chatSessionsMoved: sumCount(migrationResults, 'chatSessionsMoved'), + chatMessagesMoved: sumCount(migrationResults, 'chatMessagesMoved'), + chatSessionStateMoved: sumCount(migrationResults, 'chatSessionStateMoved'), + savedQueriesMoved: sumCount(migrationResults, 'savedQueriesMoved'), + savedQueryFoldersMoved: sumCount(migrationResults, 'savedQueryFoldersMoved'), + connectionsMoved: sumCount(migrationResults, 'connectionsMoved'), + connectionIdentitiesMoved: sumCount(migrationResults, 'connectionIdentitiesMoved'), + aiSchemaCacheMoved: sumCount(migrationResults, 'aiSchemaCacheMoved'), + syncOperationsMoved: sumCount(migrationResults, 'syncOperationsMoved'), + migrationResults, + skippedTables: anonymousOwnershipNoMigratePolicies.map(policy => policy.table), + }; +} + +export async function mergeAnonymousOrganizationIntoExistingOrganization( + tx: AnonymousOwnershipMigrationTx, + params: AnonymousOwnershipMigrationParams, +): Promise { + return migrateAnonymousOrganizationOwnership(tx, params); +} + +export { anonymousOwnershipMigrations, anonymousOwnershipNoMigratePolicies, getAnonymousOwnershipTablePolicies }; diff --git a/apps/web/lib/database/postgres/migrations/0005_medical_moonstone.sql b/apps/web/lib/database/postgres/migrations/0005_medical_moonstone.sql new file mode 100644 index 00000000..d45df687 --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/0005_medical_moonstone.sql @@ -0,0 +1 @@ +ALTER TABLE "user" ADD COLUMN "is_anonymous" boolean DEFAULT false NOT NULL; diff --git a/apps/web/lib/database/postgres/migrations/0006_tan_iron_man.sql b/apps/web/lib/database/postgres/migrations/0006_tan_iron_man.sql new file mode 100644 index 00000000..0862566b --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/0006_tan_iron_man.sql @@ -0,0 +1,3 @@ +ALTER TABLE "connections" ALTER COLUMN "host" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "connections" ALTER COLUMN "port" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "connections" ADD COLUMN "path" text; \ No newline at end of file diff --git a/apps/web/lib/database/postgres/migrations/0007_flippant_dark_beast.sql b/apps/web/lib/database/postgres/migrations/0007_flippant_dark_beast.sql new file mode 100644 index 00000000..25144bdd --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/0007_flippant_dark_beast.sql @@ -0,0 +1 @@ +ALTER TABLE "organizations" ADD COLUMN "provisioning_kind" text; \ No newline at end of file diff --git a/apps/web/lib/database/postgres/migrations/meta/0005_snapshot.json b/apps/web/lib/database/postgres/migrations/meta/0005_snapshot.json new file mode 100644 index 00000000..a6886f6b --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/meta/0005_snapshot.json @@ -0,0 +1,3628 @@ +{ + "id": "97b3ab9f-71a1-4964-851e-ad071f287fd8", + "prevId": "b623b1fd-8d87-4402-80b5-8f4c6892d75d", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": ["id", "organization_id"] + } + }, + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } + }, + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": ["owner_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } + }, + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } + }, + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/apps/web/lib/database/postgres/migrations/meta/0006_snapshot.json b/apps/web/lib/database/postgres/migrations/meta/0006_snapshot.json new file mode 100644 index 00000000..08f8d64a --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/meta/0006_snapshot.json @@ -0,0 +1,3661 @@ +{ + "id": "dc4786a1-e892-4560-b39f-e4f1c8b1a918", + "prevId": "97b3ab9f-71a1-4964-851e-ad071f287fd8", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } + }, + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } + }, + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } + }, + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/web/lib/database/postgres/migrations/meta/0007_snapshot.json b/apps/web/lib/database/postgres/migrations/meta/0007_snapshot.json new file mode 100644 index 00000000..78ba4905 --- /dev/null +++ b/apps/web/lib/database/postgres/migrations/meta/0007_snapshot.json @@ -0,0 +1,3667 @@ +{ + "id": "c3cef7b9-c128-4a2c-80c7-ca46f0f61b7e", + "prevId": "dc4786a1-e892-4560-b39f-e4f1c8b1a918", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.tabs": { + "name": "tabs", + "schema": "", + "columns": { + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sql'" + }, + "tab_name": { + "name": "tab_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'New Query'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_sub_tab": { + "name": "active_sub_tab", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'data'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_meta": { + "name": "result_meta", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "order_index": { + "name": "order_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_invitation_organization_id": { + "name": "idx_invitation_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_email": { + "name": "idx_invitation_email", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_invitation_status": { + "name": "idx_invitation_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "alg": { + "name": "alg", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "crv": { + "name": "crv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_subscription_reference_id": { + "name": "idx_subscription_reference_id", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_subscription_id": { + "name": "idx_subscription_stripe_subscription_id", + "columns": [ + { + "expression": "stripe_subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_subscription_stripe_customer_id": { + "name": "idx_subscription_stripe_customer_id", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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 + }, + "is_anonymous": { + "name": "is_anonymous", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "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()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parts": { + "name": "parts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_chat_messages_session_time": { + "name": "idx_chat_messages_session_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_session_id": { + "name": "idx_chat_messages_session_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_messages_organization_conn_time": { + "name": "idx_chat_messages_organization_conn_time", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_session_state": { + "name": "chat_session_state", + "schema": "", + "columns": { + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_tab_id": { + "name": "active_tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "editor_context": { + "name": "editor_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "last_run_summary": { + "name": "last_run_summary", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stable_context": { + "name": "stable_context", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_chat_state_organization_conn": { + "name": "idx_chat_state_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_tab": { + "name": "idx_chat_state_organization_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_state_organization_updated": { + "name": "idx_chat_state_organization_updated", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_database": { + "name": "active_database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_schema": { + "name": "active_schema", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_chat_sessions_list": { + "name": "idx_chat_sessions_list", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_message_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_user_type": { + "name": "idx_chat_sessions_organization_user_type", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_conn": { + "name": "idx_chat_sessions_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_sessions_organization_db": { + "name": "idx_chat_sessions_organization_db", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "active_database", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "uidx_chat_sessions_copilot_tab": { + "name": "uidx_chat_sessions_copilot_tab", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tab_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat_sessions\".\"type\" = 'copilot'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "uq_chat_sessions_id_organization": { + "name": "uq_chat_sessions_id_organization", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "ck_chat_sessions_type_tab": { + "name": "ck_chat_sessions_type_tab", + "value": "((\"chat_sessions\".\"type\" = 'copilot' AND \"chat_sessions\".\"tab_id\" IS NOT NULL) OR (\"chat_sessions\".\"type\" <> 'copilot' AND \"chat_sessions\".\"tab_id\" IS NULL))" + } + }, + "isRLSEnabled": false + }, + "public.query_audit": { + "name": "query_audit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_id": { + "name": "tab_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_name": { + "name": "connection_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_read": { + "name": "rows_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "bytes_read": { + "name": "bytes_read", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rows_written": { + "name": "rows_written", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "extra_json": { + "name": "extra_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_organization_created": { + "name": "idx_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_source_created": { + "name": "idx_source_created", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_query_id": { + "name": "idx_query_id", + "columns": [ + { + "expression": "query_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.members": { + "name": "members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "members_organization_id_user_id_unique": { + "name": "members_organization_id_user_id_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_organization": { + "name": "idx_members_organization", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_members_user": { + "name": "idx_members_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_user_id_user_id_fk": { + "name": "members_user_id_user_id_fk", + "tableFrom": "members", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provisioning_kind": { + "name": "provisioning_kind", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organizations_owner_user_id_user_id_fk": { + "name": "organizations_owner_user_id_user_id_fk", + "tableFrom": "organizations", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identities": { + "name": "connection_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "uniq_conn_identity_connection_name": { + "name": "uniq_conn_identity_connection_name", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_cloud_id": { + "name": "uniq_conn_identity_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_conn_identity_default_per_connection": { + "name": "uniq_conn_identity_default_per_connection", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connection_identities\".\"is_default\" = true AND \"connection_identities\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_connection_id": { + "name": "idx_conn_identity_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_created_by_user_id": { + "name": "idx_conn_identity_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_id": { + "name": "idx_conn_identity_organization_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_enabled": { + "name": "idx_conn_identity_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_sync_status": { + "name": "idx_conn_identity_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_conn_identity_organization_cloud_id": { + "name": "idx_conn_identity_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_identity_secrets": { + "name": "connection_identity_secrets", + "schema": "", + "columns": { + "identity_id": { + "name": "identity_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "vault_ref": { + "name": "vault_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_ref": { + "name": "secret_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connection_ssh": { + "name": "connection_ssh", + "schema": "", + "columns": { + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password_encrypted": { + "name": "password_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key_encrypted": { + "name": "private_key_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "passphrase_encrypted": { + "name": "passphrase_encrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connection_ssh_port": { + "name": "chk_connection_ssh_port", + "value": "\"connection_ssh\".\"port\" IS NULL OR (\"connection_ssh\".\"port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "cloud_id": { + "name": "cloud_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_status": { + "name": "sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local_only'" + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "remote_updated_at": { + "name": "remote_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "engine": { + "name": "engine", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Untitled connection'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "http_port": { + "name": "http_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "config_version": { + "name": "config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "validation_errors": { + "name": "validation_errors", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_status": { + "name": "last_check_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'unknown'" + }, + "last_check_at": { + "name": "last_check_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_check_latency_ms": { + "name": "last_check_latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_check_error": { + "name": "last_check_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment": { + "name": "environment", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": { + "uniq_connections_organization_name": { + "name": "uniq_connections_organization_name", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "uniq_connections_cloud_id": { + "name": "uniq_connections_cloud_id", + "columns": [ + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"cloud_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_id_status": { + "name": "idx_connections_organization_id_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_created_by_user_id": { + "name": "idx_connections_created_by_user_id", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_sync_status": { + "name": "idx_connections_sync_status", + "columns": [ + { + "expression": "sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_cloud_id": { + "name": "idx_connections_organization_cloud_id", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cloud_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_connections_organization_env": { + "name": "idx_connections_organization_env", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "chk_connections_port": { + "name": "chk_connections_port", + "value": "\"connections\".\"port\" IS NULL OR (\"connections\".\"port\" BETWEEN 1 AND 65535)" + }, + "chk_connections_http_port": { + "name": "chk_connections_http_port", + "value": "\"connections\".\"http_port\" IS NULL OR (\"connections\".\"http_port\" BETWEEN 1 AND 65535)" + } + }, + "isRLSEnabled": false + }, + "public.ai_schema_cache": { + "name": "ai_schema_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "catalog": { + "name": "catalog", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "database_name": { + "name": "database_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "table_name": { + "name": "table_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "db_type": { + "name": "db_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema_hash": { + "name": "schema_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt": { + "name": "uniq_ai_cache_organization_conn_catalog_feature_schema_model_prompt", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_organization_conn": { + "name": "idx_ai_cache_organization_conn", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_catalog_db_table": { + "name": "idx_ai_cache_catalog_db_table", + "columns": [ + { + "expression": "catalog", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "database_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_cache_schema_hash": { + "name": "idx_ai_cache_schema_hash", + "columns": [ + { + "expression": "schema_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_queries": { + "name": "saved_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sql_text": { + "name": "sql_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "work_id": { + "name": "work_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_saved_queries_organization_user": { + "name": "idx_saved_queries_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_updated_at": { + "name": "idx_saved_queries_updated_at", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_queries_folder_id": { + "name": "idx_saved_queries_folder_id", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.saved_query_folders": { + "name": "saved_query_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idx_saved_query_folders_organization_user": { + "name": "idx_saved_query_folders_organization_user", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_saved_query_folders_connection_id": { + "name": "idx_saved_query_folders_connection_id", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_usage_events": { + "name": "ai_usage_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt_version": { + "name": "prompt_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "algo_version": { + "name": "algo_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ok'" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gateway": { + "name": "gateway", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cost_micros": { + "name": "cost_micros", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reasoning_tokens": { + "name": "reasoning_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cached_input_tokens": { + "name": "cached_input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "total_tokens": { + "name": "total_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "usage_json": { + "name": "usage_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "latency_ms": { + "name": "latency_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "from_cache": { + "name": "from_cache", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "uidx_ai_usage_events_request_id": { + "name": "uidx_ai_usage_events_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created": { + "name": "idx_ai_usage_events_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_created_total": { + "name": "idx_ai_usage_events_organization_created_total", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_user_created": { + "name": "idx_ai_usage_events_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_feature_created": { + "name": "idx_ai_usage_events_feature_created", + "columns": [ + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_events_organization_feature_created": { + "name": "idx_ai_usage_events_organization_feature_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ck_ai_usage_events_status": { + "name": "ck_ai_usage_events_status", + "value": "\"ai_usage_events\".\"status\" in ('ok', 'error', 'aborted')" + } + }, + "isRLSEnabled": false + }, + "public.ai_usage_traces": { + "name": "ai_usage_traces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_text": { + "name": "input_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output_text": { + "name": "output_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "input_json": { + "name": "input_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "output_json": { + "name": "output_json", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "redacted": { + "name": "redacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now() + interval '180 days'" + } + }, + "indexes": { + "uidx_ai_usage_traces_request_id": { + "name": "uidx_ai_usage_traces_request_id", + "columns": [ + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_created": { + "name": "idx_ai_usage_traces_organization_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_organization_user_created": { + "name": "idx_ai_usage_traces_organization_user_created", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_usage_traces_expires_at": { + "name": "idx_ai_usage_traces_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_operations": { + "name": "sync_operations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connection'" + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_sync_operations_organization_status": { + "name": "idx_sync_operations_organization_status", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_entity": { + "name": "idx_sync_operations_entity", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_operations_created_at": { + "name": "idx_sync_operations_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/web/lib/database/postgres/migrations/meta/_journal.json b/apps/web/lib/database/postgres/migrations/meta/_journal.json index a3fea3c0..8db23df2 100644 --- a/apps/web/lib/database/postgres/migrations/meta/_journal.json +++ b/apps/web/lib/database/postgres/migrations/meta/_journal.json @@ -40,9 +40,23 @@ { "idx": 5, "version": "7", - "when": 1775000000000, - "tag": "0005_free_sqlite_path", + "when": 1774538755586, + "tag": "0005_medical_moonstone", + "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1775056629462, + "tag": "0006_tan_iron_man", + "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1775064411912, + "tag": "0007_flippant_dark_beast", "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/apps/web/lib/database/postgres/schemas/auth-schema.ts b/apps/web/lib/database/postgres/schemas/auth-schema.ts index 603af011..eb9a75a0 100644 --- a/apps/web/lib/database/postgres/schemas/auth-schema.ts +++ b/apps/web/lib/database/postgres/schemas/auth-schema.ts @@ -10,6 +10,7 @@ export const user = pgTable('user', { .$defaultFn(() => newEntityId()), name: text('name').notNull(), email: text('email').notNull().unique(), + isAnonymous: boolean('is_anonymous').default(false).notNull(), emailVerified: boolean('email_verified') .$defaultFn(() => false) diff --git a/apps/web/lib/database/postgres/schemas/organizations/organizations.ts b/apps/web/lib/database/postgres/schemas/organizations/organizations.ts index 448e65fd..5b31dd42 100644 --- a/apps/web/lib/database/postgres/schemas/organizations/organizations.ts +++ b/apps/web/lib/database/postgres/schemas/organizations/organizations.ts @@ -3,6 +3,8 @@ import { pgTable, text, timestamp, uniqueIndex } from 'drizzle-orm/pg-core'; import { newEntityId } from '@/lib/id'; import { user } from '../auth-schema'; +export type OrganizationProvisioningKind = 'anonymous' | 'system_default' | 'manual' | 'anonymous_promoted'; + export const organizations = pgTable( 'organizations', { @@ -18,6 +20,7 @@ export const organizations = pgTable( // URL /organization/:slug slug: text('slug'), + provisioningKind: text('provisioning_kind').$type(), logo: text('logo'), metadata: text('metadata'), stripeCustomerId: text('stripe_customer_id'), diff --git a/apps/web/lib/organization/api.ts b/apps/web/lib/organization/api.ts index 7167ac5a..9383505d 100644 --- a/apps/web/lib/organization/api.ts +++ b/apps/web/lib/organization/api.ts @@ -91,6 +91,7 @@ export type OrganizationSummary = { logo?: string | null; metadata?: Record | null; createdAt: string | Date; + provisioningKind?: string | null; }; export type OrganizationMember = { @@ -161,12 +162,11 @@ export async function listOrganizations() { } export async function createOrganization(input: { name: string; slug: string }) { - return authOrganizationRequest('/organization/create', { + return appApiRequest('/api/organizations/create', { method: 'POST', body: { name: input.name, slug: input.slug || 'workspace', - keepCurrentActiveOrganization: false, }, }); } diff --git a/apps/web/public/locales/en.json b/apps/web/public/locales/en.json index 2468db0a..d8f8a968 100644 --- a/apps/web/public/locales/en.json +++ b/apps/web/public/locales/en.json @@ -98,13 +98,22 @@ "ForgotPassword": "Forgot your password?", "Submitting": "Signing in…", "Submit": "Login", - "DemoEnter": "Enter as Demo", + "DemoEnter": "Continue as guest", "OrContinueWith": "Or continue with", "LoginWithGithub": "Login with Github", "LoginWithGoogle": "Login with Google", "LoginWithMeta": "Login with Meta", "NoAccount": "Don't have an account?", "SignUp": "Sign up", + "Guest": { + "Action": "Continue as guest", + "Tooltip": "Best for first-time visitors. If you later sign in, we will keep your current guest workspace with your account.", + "ConfirmTitle": "Create a temporary workspace?", + "ConfirmDescription": "We will create a guest workspace for you right away. If you later sign in, we will keep this workspace with your account.", + "Confirm": "Create guest workspace", + "Cancel": "Back", + "StartFailed": "Failed to start guest workspace" + }, "ContinueAgreement": "By clicking continue, you agree to our", "Terms": "Terms of Service", "And": "and", @@ -126,6 +135,10 @@ }, "TeamName": "{name}'s organization", "TeamDefaultName": "Default", + "AnonymousWorkspace": { + "Name": "Guest workspace", + "LinkedName": "Imported guest workspace" + }, "Emails": { "ResetPassword": { "Subject": "Reset your password", @@ -759,6 +772,17 @@ "TableSummary": "Summary of all tables with row counts" } }, + "AuthRequired": { + "Title": "Sign in to use Chatbot", + "Description": "Guest workspaces can browse the app, but Chatbot requires a full account.", + "Hint": "After sign-in, your current workspace and organization stay with you.", + "WorkspaceNotice": "When you sign in, your current guest workspace will be kept with your account.", + "SignIn": "Sign in to continue", + "SheetTitle": "Continue with an account", + "SheetDescription": "Link this guest workspace to a full Dory account.", + "SignInTab": "Sign in", + "SignUpTab": "Create account" + }, "Typing": "Generating", "Input": { "GlobalPlaceholder": "@ mention tables to ask about the database, Shift + Enter for a new line", @@ -830,6 +854,27 @@ "Heading": "Tables" } }, + "Welcome": { + "Badge": "Anonymous mode", + "Title": "Start with an anonymous workspace, upgrade only when you need Chatbot.", + "Description": "Explore Dory immediately without creating an account. We will create a temporary workspace for you and keep your organization data when you later sign in.", + "CardTitle": "Enter Dory instantly", + "CardDescription": "Create an anonymous account and a personal workspace with one click.", + "Start": "Start with anonymous account", + "Resume": "Continue anonymous workspace", + "Starting": "Preparing workspace…", + "Hint": "You can keep browsing anonymously. When you need Chatbot, sign in and we will link this workspace to your real account.", + "HaveAccount": "Already have an account?", + "SignIn": "Sign in", + "Highlights": { + "Instant": "No signup wall before first use.", + "Private": "Temporary workspace scoped to your session.", + "Upgrade": "Sign in later without losing your organization." + }, + "Errors": { + "StartFailed": "Failed to start anonymous workspace. Please try again." + } + }, "Monitoring": { "Tabs": { "Overview": "Overview", @@ -1265,6 +1310,11 @@ "SaveQuery": "Save Query", "Stop": "Stop" }, + "AnonymousWorkspaceAlert": { + "Title": "You're not signed in, so workspace content can't be saved", + "Description": "This is a guest workspace. Sign in or create an account to save queries and other workspace content while keeping your current guest data.", + "Action": "Sign in to continue" + }, "Refresh": "Refresh", "Sidebar": { "Tables": "Tables", @@ -1740,7 +1790,8 @@ "ConnectionIdRequired": "Connection ID is required", "ListSessionsFailed": "Failed to fetch sessions", "CopilotCreationNotAllowed": "Copilot sessions cannot be created via this endpoint", - "CreateSessionFailed": "Failed to create session" + "CreateSessionFailed": "Failed to create session", + "FullAccountRequired": "Please sign in to use Chatbot." }, "Tools": { "Rag": { @@ -2356,11 +2407,23 @@ "StarNotificationDescription": "Give the project a GitHub star to help more people discover it.", "StarNotificationAction": "Star on GitHub", "DismissStarNotification": "Dismiss GitHub star prompt", + "LogOut": "Log out", "Update": "Update", "Updating": "Updating...", "UpdateVersion": "Version {version}", "UpdateTooltip": "Click to restart the app and upgrade to {version}", - "UpdateTooltipUnknown": "Click to restart the app and upgrade to the latest version" + "UpdateTooltipUnknown": "Click to restart the app and upgrade to the latest version", + "GuestSession": { + "Name": "Guest", + "Subtitle": "Temporary workspace", + "Title": "Abandon guest session?", + "Description": "If you abandon this guest session now, we will delete this temporary account and workspace. The next time you start, you will get a new guest account.", + "SignIn": "Sign in", + "AbandonAction": "Abandon guest session", + "Confirm": "Abandon session", + "Cancel": "Keep session", + "DeleteFailed": "Failed to delete guest session. Please try again." + } }, "OrganizationSettings": { "Title": "Organization settings", diff --git a/apps/web/public/locales/es.json b/apps/web/public/locales/es.json index 2b5fd0ea..7a5e09ca 100644 --- a/apps/web/public/locales/es.json +++ b/apps/web/public/locales/es.json @@ -98,13 +98,22 @@ "ForgotPassword": "¿Olvidaste tu contraseña?", "Submitting": "Iniciando sesión…", "Submit": "Entrar", - "DemoEnter": "Entrar como demo", + "DemoEnter": "Continuar como invitado", "OrContinueWith": "O continuar con", "LoginWithGithub": "Entrar con GitHub", "LoginWithGoogle": "Entrar con Google", "LoginWithMeta": "Entrar con Meta", "NoAccount": "¿No tienes una cuenta?", "SignUp": "Registrarse", + "Guest": { + "Action": "Continuar como invitado", + "Tooltip": "Ideal para quienes visitan por primera vez. Si más tarde inicias sesión, mantendremos tu espacio de trabajo de invitado actual en tu cuenta.", + "ConfirmTitle": "¿Crear un espacio de trabajo temporal?", + "ConfirmDescription": "Crearemos un espacio de trabajo de invitado para ti de inmediato. Si más tarde inicias sesión, mantendremos este espacio de trabajo en tu cuenta.", + "Confirm": "Crear espacio de trabajo de invitado", + "Cancel": "Volver", + "StartFailed": "No se pudo iniciar el espacio de trabajo de invitado" + }, "ContinueAgreement": "Al hacer clic en continuar, aceptas nuestros", "Terms": "Términos del servicio", "And": "y", @@ -126,6 +135,10 @@ }, "TeamName": "Organización de {name}", "TeamDefaultName": "Predeterminado", + "AnonymousWorkspace": { + "Name": "Espacio de trabajo de invitado", + "LinkedName": "Espacio de trabajo de invitado importado" + }, "Emails": { "ResetPassword": { "Subject": "Restablece tu contraseña", @@ -749,6 +762,17 @@ "Chatbot": { "Close": "Cerrar", "EmptyState": "Selecciona una sesión o crea una nueva.", + "AuthRequired": { + "Title": "Inicia sesión para usar Chatbot", + "Description": "Los espacios de trabajo de invitado permiten explorar la app, pero Chatbot requiere una cuenta completa.", + "Hint": "Después de iniciar sesión, tu espacio de trabajo y tu organización actuales seguirán contigo.", + "WorkspaceNotice": "Cuando inicies sesión, tu espacio de trabajo de invitado actual se mantendrá en tu cuenta.", + "SignIn": "Inicia sesión para continuar", + "SheetTitle": "Continuar con una cuenta", + "SheetDescription": "Vincula este espacio de trabajo de invitado a una cuenta completa de Dory.", + "SignInTab": "Iniciar sesión", + "SignUpTab": "Crear cuenta" + }, "Typing": "Generando", "Input": { "GlobalPlaceholder": "Usa @ para mencionar tablas y preguntar sobre la base de datos; Shift + Enter para una nueva línea", @@ -819,6 +843,27 @@ "Heading": "Tablas" } }, + "Welcome": { + "Badge": "Modo anónimo", + "Title": "Empieza con un espacio de trabajo anónimo y mejora solo cuando necesites Chatbot.", + "Description": "Explora Dory de inmediato sin crear una cuenta. Crearemos un espacio de trabajo temporal para ti y conservaremos los datos de tu organización cuando más tarde inicies sesión.", + "CardTitle": "Entra en Dory al instante", + "CardDescription": "Crea una cuenta anónima y un espacio de trabajo personal con un solo clic.", + "Start": "Empezar con una cuenta anónima", + "Resume": "Continuar en el espacio de trabajo anónimo", + "Starting": "Preparando espacio de trabajo…", + "Hint": "Puedes seguir navegando de forma anónima. Cuando necesites Chatbot, inicia sesión y vincularemos este espacio de trabajo con tu cuenta real.", + "HaveAccount": "¿Ya tienes una cuenta?", + "SignIn": "Iniciar sesión", + "Highlights": { + "Instant": "Sin barrera de registro antes del primer uso.", + "Private": "Espacio de trabajo temporal limitado a tu sesión.", + "Upgrade": "Inicia sesión más tarde sin perder tu organización." + }, + "Errors": { + "StartFailed": "No se pudo iniciar el espacio de trabajo anónimo. Inténtalo de nuevo." + } + }, "Monitoring": { "Tabs": { "Overview": "Resumen", @@ -1252,6 +1297,11 @@ "SaveQuery": "Guardar consulta", "Stop": "Detener" }, + "AnonymousWorkspaceAlert": { + "Title": "No has iniciado sesión, así que el contenido del espacio de trabajo no se puede guardar", + "Description": "Este es un espacio de trabajo de invitado. Inicia sesión o crea una cuenta para guardar consultas y otro contenido del espacio de trabajo sin perder tus datos actuales de invitado.", + "Action": "Inicia sesión para continuar" + }, "Refresh": "Actualizar", "Sidebar": { "Tables": "Tablas", @@ -1727,7 +1777,8 @@ "ConnectionIdRequired": "Se requiere el ID de conexión", "ListSessionsFailed": "No se pudieron obtener las sesiones", "CopilotCreationNotAllowed": "Las sesiones de Copilot no se pueden crear desde este endpoint", - "CreateSessionFailed": "No se pudo crear la sesión" + "CreateSessionFailed": "No se pudo crear la sesión", + "FullAccountRequired": "Inicia sesión para usar Chatbot." }, "Tools": { "Rag": { @@ -2343,11 +2394,23 @@ "StarNotificationDescription": "Dale una estrella en GitHub para ayudar a que más gente descubra el proyecto.", "StarNotificationAction": "Dar estrella en GitHub", "DismissStarNotification": "Cerrar aviso de estrella de GitHub", + "LogOut": "Cerrar sesión", "Update": "Actualizar", "Updating": "Actualizando...", "UpdateVersion": "Versión {version}", "UpdateTooltip": "Haz clic para reiniciar la app y actualizar a {version}", - "UpdateTooltipUnknown": "Haz clic para reiniciar la app y actualizar a la última versión" + "UpdateTooltipUnknown": "Haz clic para reiniciar la app y actualizar a la última versión", + "GuestSession": { + "Name": "Invitado", + "Subtitle": "Espacio de trabajo temporal", + "Title": "¿Abandonar la sesión de invitado?", + "Description": "Si abandonas ahora esta sesión de invitado, eliminaremos esta cuenta temporal y su espacio de trabajo. La próxima vez que entres obtendrás una nueva cuenta de invitado.", + "SignIn": "Iniciar sesión", + "AbandonAction": "Abandonar sesión de invitado", + "Confirm": "Abandonar sesión", + "Cancel": "Mantener sesión", + "DeleteFailed": "No se pudo eliminar la sesión de invitado. Inténtalo de nuevo." + } }, "OrganizationSettings": { "Title": "Configuración de la organización", diff --git a/apps/web/public/locales/ja.json b/apps/web/public/locales/ja.json index d589340f..0c0fec40 100644 --- a/apps/web/public/locales/ja.json +++ b/apps/web/public/locales/ja.json @@ -98,13 +98,22 @@ "ForgotPassword": "パスワードをお忘れですか?", "Submitting": "ログイン中…", "Submit": "ログイン", - "DemoEnter": "デモとして入る", + "DemoEnter": "ゲストとして続行", "OrContinueWith": "または次で続行", "LoginWithGithub": "GitHub でログイン", "LoginWithGoogle": "Google でログイン", "LoginWithMeta": "Meta でログイン", "NoAccount": "アカウントをお持ちでないですか?", "SignUp": "新規登録", + "Guest": { + "Action": "ゲストとして続行", + "Tooltip": "初めて利用する方に最適です。後でサインインしても、現在のゲストワークスペースはあなたのアカウントに引き継がれます。", + "ConfirmTitle": "一時的なワークスペースを作成しますか?", + "ConfirmDescription": "すぐにゲストワークスペースを作成します。後でサインインしても、このワークスペースはあなたのアカウントに引き継がれます。", + "Confirm": "ゲストワークスペースを作成", + "Cancel": "戻る", + "StartFailed": "ゲストワークスペースの開始に失敗しました" + }, "ContinueAgreement": "続行をクリックすると、次に同意したものとみなされます:", "Terms": "利用規約", "And": "および", @@ -126,6 +135,10 @@ }, "TeamName": "{name} の組織", "TeamDefaultName": "デフォルト", + "AnonymousWorkspace": { + "Name": "ゲストワークスペース", + "LinkedName": "インポートされたゲストワークスペース" + }, "Emails": { "ResetPassword": { "Subject": "パスワードをリセット", @@ -749,6 +762,17 @@ "Chatbot": { "Close": "閉じる", "EmptyState": "セッションを選択するか、新しく作成してください。", + "AuthRequired": { + "Title": "Chatbot を使うにはサインインしてください", + "Description": "ゲストワークスペースでもアプリは閲覧できますが、Chatbot を使うには通常アカウントが必要です。", + "Hint": "サインイン後も、現在のワークスペースと組織はそのまま引き継がれます。", + "WorkspaceNotice": "サインインすると、現在のゲストワークスペースはあなたのアカウントに引き継がれます。", + "SignIn": "続行するにはサインイン", + "SheetTitle": "アカウントで続行", + "SheetDescription": "このゲストワークスペースを通常の Dory アカウントに紐付けます。", + "SignInTab": "サインイン", + "SignUpTab": "アカウント作成" + }, "Typing": "生成中", "Input": { "GlobalPlaceholder": "@ でテーブルに言及してデータベースについて質問できます。改行は Shift + Enter", @@ -819,6 +843,27 @@ "Heading": "テーブル" } }, + "Welcome": { + "Badge": "匿名モード", + "Title": "匿名ワークスペースですぐ始めて、Chatbot が必要になったらアップグレード。", + "Description": "アカウントを作成せずにすぐ Dory を試せます。一時的なワークスペースを作成し、後でサインインしたときにも組織データを引き継ぎます。", + "CardTitle": "すぐに Dory を始める", + "CardDescription": "ワンクリックで匿名アカウントと個人用ワークスペースを作成します。", + "Start": "匿名アカウントで始める", + "Resume": "匿名ワークスペースを続ける", + "Starting": "ワークスペースを準備中…", + "Hint": "匿名のまま閲覧を続けられます。Chatbot が必要になったらサインインすれば、このワークスペースを実アカウントに紐付けます。", + "HaveAccount": "すでにアカウントをお持ちですか?", + "SignIn": "サインイン", + "Highlights": { + "Instant": "初回利用前に登録は不要です。", + "Private": "現在のセッションに限定された一時ワークスペースです。", + "Upgrade": "後でサインインしても組織を失いません。" + }, + "Errors": { + "StartFailed": "匿名ワークスペースの開始に失敗しました。もう一度お試しください。" + } + }, "Monitoring": { "Tabs": { "Overview": "概要", @@ -1252,6 +1297,11 @@ "SaveQuery": "クエリを保存", "Stop": "停止" }, + "AnonymousWorkspaceAlert": { + "Title": "サインインしていないため、ワークスペース内容を保存できません", + "Description": "現在はゲストワークスペースです。サインインまたはアカウント登録すると、現在のゲストデータを保持したままクエリや他のワークスペース内容を保存できます。", + "Action": "サインインして続行" + }, "Refresh": "更新", "Sidebar": { "Tables": "テーブル", @@ -1727,7 +1777,8 @@ "ConnectionIdRequired": "接続IDが必要です", "ListSessionsFailed": "セッションの取得に失敗しました", "CopilotCreationNotAllowed": "このエンドポイントでは Copilot セッションを作成できません", - "CreateSessionFailed": "セッションの作成に失敗しました" + "CreateSessionFailed": "セッションの作成に失敗しました", + "FullAccountRequired": "Chatbot を使うにはサインインしてください。" }, "Tools": { "Rag": { @@ -2343,11 +2394,23 @@ "StarNotificationDescription": "GitHub でスターを付けて、このプロジェクトを広めてください。", "StarNotificationAction": "GitHub でスター", "DismissStarNotification": "GitHub スター案内を閉じる", + "LogOut": "ログアウト", "Update": "更新", "Updating": "更新中...", "UpdateVersion": "バージョン {version}", "UpdateTooltip": "クリックして再起動し、{version} に更新します", - "UpdateTooltipUnknown": "クリックして再起動し、最新バージョンに更新します" + "UpdateTooltipUnknown": "クリックして再起動し、最新バージョンに更新します", + "GuestSession": { + "Name": "ゲスト", + "Subtitle": "一時ワークスペース", + "Title": "ゲストセッションを破棄しますか?", + "Description": "今このゲストセッションを破棄すると、この一時アカウントとワークスペースは削除されます。次回開始時には新しいゲストアカウントが作成されます。", + "SignIn": "サインイン", + "AbandonAction": "ゲストセッションを破棄", + "Confirm": "セッションを破棄", + "Cancel": "セッションを保持", + "DeleteFailed": "ゲストセッションの削除に失敗しました。もう一度お試しください。" + } }, "OrganizationSettings": { "Title": "組織設定", diff --git a/apps/web/public/locales/zh.json b/apps/web/public/locales/zh.json index 3c5c40d7..09432346 100644 --- a/apps/web/public/locales/zh.json +++ b/apps/web/public/locales/zh.json @@ -102,13 +102,22 @@ "ForgotPassword": "忘记密码?", "Submitting": "正在登录…", "Submit": "登录", - "DemoEnter": "以 Demo 身份进入", + "DemoEnter": "以访客身份继续", "OrContinueWith": "或使用以下方式继续", "LoginWithGithub": "使用 GitHub 登录", "LoginWithGoogle": "使用 Google 登录", "LoginWithMeta": "使用 Meta 登录", "NoAccount": "还没有账号?", "SignUp": "注册", + "Guest": { + "Action": "以访客身份继续", + "Tooltip": "更适合首次体验的用户。如果你之后登录,我们会将当前访客工作区保留到你的账号下。", + "ConfirmTitle": "要创建临时工作区吗?", + "ConfirmDescription": "我们会立即为你创建一个访客工作区。如果你之后登录,我们会将这个工作区保留到你的账号下。", + "Confirm": "创建访客工作区", + "Cancel": "返回", + "StartFailed": "启动访客工作区失败" + }, "ContinueAgreement": "继续即表示你同意我们的", "Terms": "服务条款", "And": "和", @@ -130,6 +139,10 @@ }, "TeamName": "{name}的团队", "TeamDefaultName": "默认", + "AnonymousWorkspace": { + "Name": "访客工作区", + "LinkedName": "导入的访客工作区" + }, "Emails": { "ResetPassword": { "Subject": "重置你的密码", @@ -761,11 +774,23 @@ "TableSummary": "所有表的行数汇总" } }, + "AuthRequired": { + "Title": "登录后才能使用 Chatbot", + "Description": "访客工作区可以继续浏览应用,但 Chatbot 需要正式账号。", + "Hint": "登录后会保留当前工作区和组织,不会丢数据。", + "WorkspaceNotice": "登录后,当前访客工作区会保留到你的账号下。", + "SignIn": "登录后继续", + "SheetTitle": "继续并绑定账号", + "SheetDescription": "把当前访客工作区绑定到你的正式 Dory 账号。", + "SignInTab": "登录", + "SignUpTab": "注册" + }, "Typing": "正在生成", "Input": { "GlobalPlaceholder": "@ 选中表进行数据库问答,Shift + Enter 换行", "CopilotPlaceholder": "问这段 SQL / 让 AI 修复或改写,Shift + Enter 换行", - "SentWithAttachments": "已发送附件" + "SentWithAttachments": "已发送附件", + "WelcomePlaceholder": "询问你的数据……例如:“上周收入最高的 10 位用户”" }, "Sessions": { "Title": "会话列表", @@ -831,6 +856,27 @@ "Heading": "表名" } }, + "Welcome": { + "Badge": "匿名模式", + "Title": "先用匿名工作区体验,等需要 Chatbot 时再登录。", + "Description": "无需注册即可直接进入 Dory。我们会先为你创建一个临时工作区,之后登录时保留当前组织和数据。", + "CardTitle": "立即进入 Dory", + "CardDescription": "点击一次即可创建匿名账号和默认工作区。", + "Start": "匿名开始使用", + "Resume": "继续匿名工作区", + "Starting": "正在准备工作区…", + "Hint": "你可以先匿名浏览。等需要 Chatbot 时再登录,我们会把当前工作区绑定到正式账号。", + "HaveAccount": "已经有账号了?", + "SignIn": "去登录", + "Highlights": { + "Instant": "第一次使用前不强制注册。", + "Private": "临时工作区仅绑定当前会话。", + "Upgrade": "后续登录也不会丢失当前组织。" + }, + "Errors": { + "StartFailed": "匿名工作区启动失败,请稍后重试。" + } + }, "Monitoring": { "Tabs": { "Overview": "概览", @@ -1266,6 +1312,11 @@ "SaveQuery": "保存查询", "Stop": "停止" }, + "AnonymousWorkspaceAlert": { + "Title": "未登录,无法保存工作区内容", + "Description": "当前是访客工作区。登录或注册后,才能保存查询和其它工作区内容,并保留当前访客数据。", + "Action": "登录后继续" + }, "Refresh": "刷新", "Sidebar": { "Tables": "表", @@ -1741,7 +1792,8 @@ "ConnectionIdRequired": "缺少 Connection ID 参数", "ListSessionsFailed": "获取会话列表失败", "CopilotCreationNotAllowed": "Copilot 会话不能通过该接口创建", - "CreateSessionFailed": "创建会话失败" + "CreateSessionFailed": "创建会话失败", + "FullAccountRequired": "请先登录后再使用 Chatbot。" }, "Tools": { "Rag": { @@ -2352,16 +2404,28 @@ "Chatbot": "聊天助手", "Monitoring": "监控", "Privileges": "权限", - "GetHelp": "帮助", "StarNotificationTitle": "喜欢 Dory 吗?", "StarNotificationDescription": "去 GitHub 点个 Star,帮助更多人发现这个项目。", "StarNotificationAction": "GitHub Star", "DismissStarNotification": "关闭 GitHub Star 提示", + "GetHelp": "获取帮助", + "LogOut": "退出登录", "Update": "更新", "Updating": "更新中...", "UpdateVersion": "版本 {version}", "UpdateTooltip": "点击后将重启应用并升级到 {version}", - "UpdateTooltipUnknown": "点击后将重启应用并升级到最新版本" + "UpdateTooltipUnknown": "点击后将重启应用并升级到最新版本", + "GuestSession": { + "Name": "Guest", + "Subtitle": "临时工作区", + "Title": "要放弃当前访客会话吗?", + "Description": "如果现在放弃这个访客会话,我们会删除这个临时账号和工作区。下次开始使用时会创建一个新的访客账号。", + "SignIn": "登录关联账号", + "AbandonAction": "放弃访客会话", + "Confirm": "确认放弃", + "Cancel": "继续保留", + "DeleteFailed": "删除访客会话失败,请重试。" + } }, "OrganizationSettings": { "Title": "组织设置", diff --git a/apps/web/scripts/tests/anonymous-delete-cleanup.test.ts b/apps/web/scripts/tests/anonymous-delete-cleanup.test.ts new file mode 100644 index 00000000..d3d19a09 --- /dev/null +++ b/apps/web/scripts/tests/anonymous-delete-cleanup.test.ts @@ -0,0 +1,61 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { anonymousDeleteCleanupTableCoverage, anonymousMergeCleanupTableCoverage } from '../../lib/auth/anonymous'; +import { anonymousOwnershipNoMigratePolicies } from '../../lib/database/postgres/impl/organization/anonymous-resource-merge'; + +const cleanupTables: Set = new Set([ + ...anonymousDeleteCleanupTableCoverage.connectionIdentityScoped, + ...anonymousDeleteCleanupTableCoverage.connectionScoped, + ...anonymousDeleteCleanupTableCoverage.organizationScoped, +]); + +test('anonymous delete cleanup covers all anonymous workspace business tables', () => { + assert.deepEqual( + [...cleanupTables].sort(), + [ + 'aiSchemaCache', + 'aiUsageEvents', + 'aiUsageTraces', + 'chatMessages', + 'chatSessionState', + 'chatSessions', + 'connectionIdentities', + 'connectionIdentitySecrets', + 'connectionSsh', + 'connections', + 'invitation', + 'organizationMembers', + 'organizations', + 'queryAudit', + 'savedQueries', + 'savedQueryFolders', + 'syncOperations', + 'tabs', + ], + ); +}); + +test('anonymous delete cleanup includes no-migrate ownership tables that must be removed before deleting the user', () => { + const deleteOnlyTables = new Set( + anonymousOwnershipNoMigratePolicies + .map(policy => policy.table) + .filter(table => !['account', 'session'].includes(table)), + ); + + for (const table of deleteOnlyTables) { + assert.equal(cleanupTables.has(table), true, `expected cleanup to include ${table}`); + } +}); + +test('anonymous delete cleanup deletes organizations after dependent resources', () => { + const organizationScopedTables = anonymousDeleteCleanupTableCoverage.organizationScoped; + + assert.equal(organizationScopedTables[organizationScopedTables.length - 1], 'organizations'); + assert.equal(organizationScopedTables.indexOf('connections') < organizationScopedTables.indexOf('organizations'), true); + assert.equal(organizationScopedTables.indexOf('organizationMembers') < organizationScopedTables.indexOf('organizations'), true); + assert.equal(organizationScopedTables.indexOf('invitation') < organizationScopedTables.indexOf('organizations'), true); +}); + +test('anonymous merge cleanup removes organization-scoped no-migrate tables before deleting the source organization', () => { + assert.deepEqual([...anonymousMergeCleanupTableCoverage.organizationScoped].sort(), ['aiUsageEvents', 'aiUsageTraces', 'invitation', 'queryAudit']); +}); diff --git a/apps/web/scripts/tests/anonymous-delete-route.test.ts b/apps/web/scripts/tests/anonymous-delete-route.test.ts new file mode 100644 index 00000000..40471983 --- /dev/null +++ b/apps/web/scripts/tests/anonymous-delete-route.test.ts @@ -0,0 +1,19 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { buildAnonymousDeleteResponse, isLocalAnonymousDeleteRequest } from '../../lib/auth/anonymous-delete'; + +test('anonymous delete route matcher only matches the delete endpoint', () => { + assert.equal(isLocalAnonymousDeleteRequest('/api/auth/delete-anonymous-user'), true); + assert.equal(isLocalAnonymousDeleteRequest('/api/auth/sign-in/email'), false); +}); + +test('anonymous delete response clears both Better Auth session cookies', () => { + const response = buildAnonymousDeleteResponse(new Request('http://localhost:3000/api/auth/delete-anonymous-user', { method: 'POST' })); + const setCookies = [...response.headers.entries()] + .filter(([header]) => header === 'set-cookie') + .map(([, value]) => value); + + assert.equal(response.status, 200); + assert.equal(setCookies.some(cookie => cookie.includes('better-auth.session_token=; Path=/; Max-Age=0; HttpOnly; SameSite=lax')), true); + assert.equal(setCookies.some(cookie => cookie.includes('__Secure-better-auth.session_token=; Path=/; Max-Age=0; HttpOnly; SameSite=lax')), true); +}); diff --git a/apps/web/scripts/tests/anonymous-link-strategy.test.ts b/apps/web/scripts/tests/anonymous-link-strategy.test.ts new file mode 100644 index 00000000..599a43a9 --- /dev/null +++ b/apps/web/scripts/tests/anonymous-link-strategy.test.ts @@ -0,0 +1,94 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { resolveAnonymousOrganizationLinkDecision } from '../../lib/auth/anonymous-link-strategy'; + +test('merges guest organizations into the only system default organization', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'anonymous' }], + userOrganizations: [{ id: 'org_default', provisioningKind: 'system_default' }], + newActiveOrganizationId: null, + }); + + assert.deepEqual(decision, { + action: 'merge', + primarySourceOrganizationId: 'org_guest', + sourceOrganizationIds: ['org_guest'], + targetOrganizationId: 'org_default', + }); +}); + +test('prefers an explicit active manual organization over the system default organization', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'anonymous' }], + userOrganizations: [ + { id: 'org_default', provisioningKind: 'system_default' }, + { id: 'org_manual', provisioningKind: 'manual' }, + ], + newActiveOrganizationId: 'org_manual', + }); + + assert.deepEqual(decision, { + action: 'merge', + primarySourceOrganizationId: 'org_guest', + sourceOrganizationIds: ['org_guest'], + targetOrganizationId: 'org_manual', + }); +}); + +test('promotes the guest organization when both default and manual organizations exist without an explicit target', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'anonymous' }], + userOrganizations: [ + { id: 'org_default', provisioningKind: 'system_default' }, + { id: 'org_manual', provisioningKind: 'manual' }, + ], + newActiveOrganizationId: null, + }); + + assert.deepEqual(decision, { + action: 'promote', + primarySourceOrganizationId: 'org_guest', + sourceOrganizationIds: ['org_guest'], + targetOrganizationId: null, + }); +}); + +test('promotes the guest organization when no merge target exists', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'anonymous' }], + userOrganizations: [], + newActiveOrganizationId: null, + }); + + assert.deepEqual(decision, { + action: 'promote', + primarySourceOrganizationId: 'org_guest', + sourceOrganizationIds: ['org_guest'], + targetOrganizationId: null, + }); +}); + +test('allows an explicit active organization with unknown provisioning kind', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'anonymous' }], + userOrganizations: [{ id: 'org_legacy', provisioningKind: null }], + newActiveOrganizationId: 'org_legacy', + }); + + assert.deepEqual(decision, { + action: 'merge', + primarySourceOrganizationId: 'org_guest', + sourceOrganizationIds: ['org_guest'], + targetOrganizationId: 'org_legacy', + }); +}); + +test('does not merge when the source organization is not explicitly marked anonymous', () => { + const decision = resolveAnonymousOrganizationLinkDecision({ + sourceOrganizations: [{ id: 'org_guest', provisioningKind: 'manual' }], + userOrganizations: [{ id: 'org_default', provisioningKind: 'system_default' }], + newActiveOrganizationId: null, + }); + + assert.equal(decision, null); +}); diff --git a/apps/web/scripts/tests/anonymous-ownership-migration.test.ts b/apps/web/scripts/tests/anonymous-ownership-migration.test.ts new file mode 100644 index 00000000..c7215c37 --- /dev/null +++ b/apps/web/scripts/tests/anonymous-ownership-migration.test.ts @@ -0,0 +1,57 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { getTableColumns } from 'drizzle-orm'; +import { schema } from '../../lib/database/postgres/schemas'; +import { + anonymousOwnershipMigrations, + anonymousOwnershipNoMigratePolicies, + getAnonymousOwnershipTablePolicies, +} from '../../lib/database/postgres/impl/organization/anonymous-resource-merge'; + +const ownershipColumnNames = new Set(['organizationId', 'userId', 'createdByUserId']); + +function getOwnershipScopedSchemaTables() { + return Object.entries(schema) + .filter(([, table]) => { + try { + const columns = Object.keys(getTableColumns(table as any)); + return columns.some(column => ownershipColumnNames.has(column)); + } catch { + return false; + } + }) + .map(([tableName]) => tableName) + .sort(); +} + +test('anonymous ownership policies cover every ownership-scoped schema table exactly once', () => { + const ownershipScopedTables = getOwnershipScopedSchemaTables(); + const policies = getAnonymousOwnershipTablePolicies(); + const policyTables = policies.map(policy => policy.table).sort(); + const duplicateTables = policyTables.filter((table, index) => table === policyTables[index - 1]); + + assert.deepEqual(duplicateTables, []); + assert.deepEqual(policyTables, ownershipScopedTables); +}); + +test('anonymous ownership registry keeps audit and ai usage tables explicit no-migrate', () => { + const policyByTable = new Map(getAnonymousOwnershipTablePolicies().map(policy => [policy.table, policy])); + + assert.equal(policyByTable.get('queryAudit')?.strategy, 'no-migrate'); + assert.equal(policyByTable.get('aiUsageEvents')?.strategy, 'no-migrate'); + assert.equal(policyByTable.get('aiUsageTraces')?.strategy, 'no-migrate'); +}); + +test('anonymous ownership migrations only cover business resources', () => { + const migrationTableSet = new Set(anonymousOwnershipMigrations.flatMap(migration => migration.tables)); + const noMigrateTableSet = new Set(anonymousOwnershipNoMigratePolicies.map(policy => policy.table)); + + assert.deepEqual( + [...migrationTableSet].sort(), + ['aiSchemaCache', 'chatMessages', 'chatSessionState', 'chatSessions', 'connectionIdentities', 'connections', 'savedQueries', 'savedQueryFolders', 'syncOperations', 'tabs'], + ); + assert.deepEqual( + [...noMigrateTableSet].sort(), + ['account', 'aiUsageEvents', 'aiUsageTraces', 'invitation', 'organizationMembers', 'queryAudit', 'session'], + ); +});