From 4132eaacd5af4432884a6d5462364bb36cb27956 Mon Sep 17 00:00:00 2001 From: Jalil Date: Tue, 7 Jul 2026 22:09:33 -0700 Subject: [PATCH 1/5] Add fast external MCP capability search --- .../capability-sources/external-mcp-client.ts | 25 +- .../external-mcp-connections.ts | 3 + .../external-mcp-manifests.ts | 387 + .../capability-sources/oauth-credentials.ts | 28 +- ee/apps/den-api/src/env.ts | 18 + .../den-api/src/mcp-manifest-maintenance.ts | 186 + ee/apps/den-api/src/mcp/agent.ts | 36 +- .../den-api/src/mcp/external-capabilities.ts | 380 +- .../den-api/src/routes/org/mcp-connections.ts | 101 + ee/apps/den-api/src/server.ts | 2 + ee/apps/den-api/src/utils/concurrency.ts | 21 + ee/apps/den-api/test/concurrency-util.test.ts | 19 + .../test/mcp-agent-config-policy.test.ts | 1 + .../den-db/drizzle/0032_stale_lady_vermin.sql | 25 + .../den-db/drizzle/meta/0032_snapshot.json | 8763 +++++++++++++++++ ee/packages/den-db/drizzle/meta/_journal.json | 9 +- ee/packages/den-db/src/schema/index.ts | 1 + .../sharables/external-mcp-manifests.ts | 57 + ee/packages/utils/src/typeid.ts | 1 + 19 files changed, 9935 insertions(+), 128 deletions(-) create mode 100644 ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts create mode 100644 ee/apps/den-api/src/mcp-manifest-maintenance.ts create mode 100644 ee/apps/den-api/src/utils/concurrency.ts create mode 100644 ee/apps/den-api/test/concurrency-util.test.ts create mode 100644 ee/packages/den-db/drizzle/0032_stale_lady_vermin.sql create mode 100644 ee/packages/den-db/drizzle/meta/0032_snapshot.json create mode 100644 ee/packages/den-db/src/schema/sharables/external-mcp-manifests.ts diff --git a/ee/apps/den-api/src/capability-sources/external-mcp-client.ts b/ee/apps/den-api/src/capability-sources/external-mcp-client.ts index ebdc30e15a..21b771013a 100644 --- a/ee/apps/den-api/src/capability-sources/external-mcp-client.ts +++ b/ee/apps/den-api/src/capability-sources/external-mcp-client.ts @@ -276,12 +276,31 @@ export async function completeExternalMcpAuth(connection: ExternalMcpConnectionR await transport.finishAuth(code) } -export async function listExternalMcpTools(connection: ExternalMcpConnectionRow, redirectUri: string, member?: ExternalMcpMemberContext) { +export async function listExternalMcpTools( + connection: ExternalMcpConnectionRow, + redirectUri: string, + member?: ExternalMcpMemberContext, + options?: { timeoutMs?: number }, +) { + return listExternalMcpToolsWithOptions(connection, redirectUri, member, options) +} + +export async function listExternalMcpToolsWithOptions( + connection: ExternalMcpConnectionRow, + redirectUri: string, + member?: ExternalMcpMemberContext, + options?: { timeoutMs?: number }, +) { const client = buildClient() const { transport } = buildTransport(connection, redirectUri, undefined, member) - await client.connect(transport) + const startedAt = Date.now() + const timeoutMs = options?.timeoutMs + await client.connect(transport, timeoutMs === undefined ? undefined : { timeout: timeoutMs }) try { - const { tools } = await client.listTools() + const remainingMs = timeoutMs === undefined + ? undefined + : Math.max(1, timeoutMs - (Date.now() - startedAt)) + const { tools } = await client.listTools(undefined, remainingMs === undefined ? undefined : { timeout: remainingMs }) return tools } finally { await client.close() diff --git a/ee/apps/den-api/src/capability-sources/external-mcp-connections.ts b/ee/apps/den-api/src/capability-sources/external-mcp-connections.ts index ae71bfd09c..566a3c8519 100644 --- a/ee/apps/den-api/src/capability-sources/external-mcp-connections.ts +++ b/ee/apps/den-api/src/capability-sources/external-mcp-connections.ts @@ -7,6 +7,7 @@ import { } from "@openwork-ee/den-db/schema" import { createDenTypeId, type DenTypeId } from "@openwork-ee/utils/typeid" import { db } from "../db.js" +import { deleteManifests } from "./external-mcp-manifests.js" /** * CRUD for ExternalMcpConnectionTable and its access grants — the "add any @@ -208,6 +209,7 @@ export async function deleteExternalMcpConnection(input: { eq(OrgOAuthClientTable.organizationId, input.organizationId), eq(OrgOAuthClientTable.providerId, existing.id), )) + await deleteManifests({ connectionId: existing.id }) await db.delete(ExternalMcpConnectionTable).where(eq(ExternalMcpConnectionTable.id, existing.id)) return true } @@ -262,5 +264,6 @@ export async function disconnectExternalMcpConnection(input: { connectedAt: null, }) .where(eq(ExternalMcpConnectionTable.id, existing.id)) + await deleteManifests({ connectionId: existing.id, principal: "shared" }) return true } diff --git a/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts new file mode 100644 index 0000000000..400f01bf3b --- /dev/null +++ b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts @@ -0,0 +1,387 @@ +import { createHash } from "node:crypto" +import { and, eq, inArray, isNull, lte, or, sql } from "@openwork-ee/den-db/drizzle" +import { + ExternalMcpToolManifestTable, + type CachedExternalMcpTool, +} from "@openwork-ee/den-db/schema" +import { createDenTypeId, type DenTypeId } from "@openwork-ee/utils/typeid" +import { db } from "../db.js" +import { env } from "../env.js" +import type { ExternalMcpConnectionRow } from "./external-mcp-connections.js" +import { listExternalMcpToolsWithOptions } from "./external-mcp-client.js" +import type { ExternalMcpMemberContext } from "./external-mcp-client.js" + +export type ManifestPrincipal = "shared" | DenTypeId<"member"> +export type ExternalMcpToolManifestRow = typeof ExternalMcpToolManifestTable.$inferSelect + +export type ManifestPair = { + connection: ExternalMcpConnectionRow + principal: ManifestPrincipal +} + +export type ManifestClassification = + | { state: "fresh"; row: ExternalMcpToolManifestRow } + | { state: "stale"; row: ExternalMcpToolManifestRow } + | { state: "miss"; row: ExternalMcpToolManifestRow | null } + +type SaveListingInput = { + connection: ExternalMcpConnectionRow + principal: ManifestPrincipal + tools: readonly CachedExternalMcpTool[] + durationMs: number +} + +type SaveFailureInput = { + connection: ExternalMcpConnectionRow + principal: ManifestPrincipal + error: unknown + durationMs: number +} + +type RevalidationInput = { + connection: ExternalMcpConnectionRow + principal: ManifestPrincipal + redirectUri: string + member?: ExternalMcpMemberContext +} + +const inFlightRevalidations = new Map>() + +export function manifestPrincipalFor( + connection: ExternalMcpConnectionRow, + member?: ExternalMcpMemberContext, +): ManifestPrincipal { + if (connection.credentialMode === "per_member") { + if (!member) { + throw new Error(`Connection "${connection.id}" uses per-member manifests but no member context was provided.`) + } + return member.orgMembershipId + } + return "shared" +} + +export function computeManifestConfigHash(connection: ExternalMcpConnectionRow): string { + return createHash("sha256") + .update(`${connection.url}\n${connection.authType}\n${connection.credentialMode}`) + .digest("hex") +} + +function rowKey(connectionId: string, principal: string) { + return `${connectionId}\0${principal}` +} + +function shortErrorMessage(error: unknown): string { + const message = error instanceof Error ? error.message : String(error) + return message.length > 1024 ? `${message.slice(0, 1021)}...` : message +} + +function normalizeTools(tools: readonly CachedExternalMcpTool[]): { + tools: CachedExternalMcpTool[] + toolCount: number + toolsHash: string + toolsTruncated: boolean +} { + const normalized = tools.map((tool) => ({ + name: tool.name, + ...(tool.title ? { title: tool.title } : {}), + ...(tool.description ? { description: tool.description } : {}), + })) + let candidate = normalized + let toolsTruncated = false + + if (Buffer.byteLength(JSON.stringify(candidate), "utf8") > env.mcpManifestMaxBytes) { + candidate = candidate.map((tool) => ({ + ...tool, + ...(tool.description ? { description: tool.description.slice(0, 500) } : {}), + })) + toolsTruncated = true + } + + while (candidate.length > 0 && Buffer.byteLength(JSON.stringify(candidate), "utf8") > env.mcpManifestMaxBytes) { + candidate = candidate.slice(0, -1) + toolsTruncated = true + } + + return { + tools: candidate, + toolCount: candidate.length, + toolsHash: createHash("sha256").update(JSON.stringify(candidate)).digest("hex"), + toolsTruncated, + } +} + +export function classifyManifest( + row: ExternalMcpToolManifestRow | null, + connection: ExternalMcpConnectionRow, + now = new Date(), +): ManifestClassification { + if (!row) return { state: "miss", row: null } + if (row.configHash !== computeManifestConfigHash(connection)) return { state: "miss", row } + if (row.tools.length === 0 || !row.listedAt) return { state: "miss", row } + + const ageMs = now.getTime() - row.listedAt.getTime() + if (ageMs >= env.mcpManifestMaxAgeMs) return { state: "miss", row } + if (row.staleAt && row.staleAt <= now) return { state: "stale", row } + if (row.status === "ok" && ageMs < env.mcpManifestFreshTtlMs) return { state: "fresh", row } + return { state: "stale", row } +} + +export async function getManifests(input: { + pairs: readonly ManifestPair[] +}): Promise> { + if (input.pairs.length === 0) return new Map() + const connectionIds = [...new Set(input.pairs.map((pair) => pair.connection.id))] + const principals = [...new Set(input.pairs.map((pair) => pair.principal))] + const rows = await db + .select() + .from(ExternalMcpToolManifestTable) + .where(and( + inArray(ExternalMcpToolManifestTable.externalMcpConnectionId, connectionIds), + inArray(ExternalMcpToolManifestTable.principal, principals), + )) + return new Map(rows.map((row) => [rowKey(row.externalMcpConnectionId, row.principal), row])) +} + +export function manifestMapKey(connectionId: string, principal: ManifestPrincipal): string { + return rowKey(connectionId, principal) +} + +export async function saveManifestListing(input: SaveListingInput): Promise { + const prepared = normalizeTools(input.tools) + const values = { + id: createDenTypeId("externalMcpToolManifest"), + organizationId: input.connection.organizationId, + externalMcpConnectionId: input.connection.id, + principal: input.principal, + configHash: computeManifestConfigHash(input.connection), + status: "ok" as const, + tools: prepared.tools, + toolCount: prepared.toolCount, + toolsHash: prepared.toolsHash, + toolsTruncated: prepared.toolsTruncated, + lastError: null, + durationMs: input.durationMs, + listedAt: new Date(), + staleAt: null, + refreshStartedAt: null, + } + await db + .insert(ExternalMcpToolManifestTable) + .values(values) + .onDuplicateKeyUpdate({ + set: { + configHash: values.configHash, + status: values.status, + tools: values.tools, + toolCount: values.toolCount, + toolsHash: values.toolsHash, + toolsTruncated: values.toolsTruncated, + lastError: values.lastError, + durationMs: values.durationMs, + listedAt: values.listedAt, + staleAt: values.staleAt, + refreshStartedAt: values.refreshStartedAt, + }, + }) + + const rows = await db + .select() + .from(ExternalMcpToolManifestTable) + .where(and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connection.id), + eq(ExternalMcpToolManifestTable.principal, input.principal), + )) + .limit(1) + const row = rows[0] + if (!row) throw new Error("Failed to save external MCP tool manifest.") + return row +} + +export async function saveManifestFailure(input: SaveFailureInput): Promise { + const existingRows = await db + .select() + .from(ExternalMcpToolManifestTable) + .where(and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connection.id), + eq(ExternalMcpToolManifestTable.principal, input.principal), + )) + .limit(1) + const existing = existingRows[0] + const values = { + id: existing?.id ?? createDenTypeId("externalMcpToolManifest"), + organizationId: input.connection.organizationId, + externalMcpConnectionId: input.connection.id, + principal: input.principal, + configHash: computeManifestConfigHash(input.connection), + status: "error" as const, + tools: existing?.tools ?? [], + toolCount: existing?.toolCount ?? 0, + toolsHash: existing?.toolsHash ?? null, + toolsTruncated: existing?.toolsTruncated ?? false, + lastError: shortErrorMessage(input.error), + durationMs: input.durationMs, + listedAt: existing?.listedAt ?? null, + staleAt: existing?.staleAt ?? null, + refreshStartedAt: null, + } + + await db + .insert(ExternalMcpToolManifestTable) + .values(values) + .onDuplicateKeyUpdate({ + set: { + configHash: values.configHash, + status: values.status, + tools: values.tools, + toolCount: values.toolCount, + toolsHash: values.toolsHash, + toolsTruncated: values.toolsTruncated, + lastError: values.lastError, + durationMs: values.durationMs, + refreshStartedAt: values.refreshStartedAt, + }, + }) +} + +export async function markManifestsStale(input: { + connectionId: DenTypeId<"externalMcpConnection"> + principal?: ManifestPrincipal +}): Promise { + const where = input.principal + ? and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connectionId), + eq(ExternalMcpToolManifestTable.principal, input.principal), + ) + : eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connectionId) + await db + .update(ExternalMcpToolManifestTable) + .set({ staleAt: new Date() }) + .where(where) +} + +export async function deleteManifests(input: { + connectionId: DenTypeId<"externalMcpConnection"> + principal?: ManifestPrincipal +}): Promise { + const where = input.principal + ? and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connectionId), + eq(ExternalMcpToolManifestTable.principal, input.principal), + ) + : eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connectionId) + await db.delete(ExternalMcpToolManifestTable).where(where) +} + +export async function claimManifestRefresh(input: { + rowId: DenTypeId<"externalMcpToolManifest"> + leaseMs?: number +}): Promise { + const leaseMs = input.leaseMs ?? env.mcpManifestRefreshLeaseMs + const leaseMicros = leaseMs * 1000 + const result = await db + .update(ExternalMcpToolManifestTable) + .set({ refreshStartedAt: sql`NOW(3)` }) + .where(and( + eq(ExternalMcpToolManifestTable.id, input.rowId), + or( + isNull(ExternalMcpToolManifestTable.refreshStartedAt), + lte(ExternalMcpToolManifestTable.refreshStartedAt, sql`DATE_SUB(NOW(3), INTERVAL ${leaseMicros} MICROSECOND)`), + ), + )) + return rowsAffected(result) === 1 +} + +export async function createRefreshLeaseForPair(input: { + connection: ExternalMcpConnectionRow + principal: ManifestPrincipal +}): Promise { + const values = { + id: createDenTypeId("externalMcpToolManifest"), + organizationId: input.connection.organizationId, + externalMcpConnectionId: input.connection.id, + principal: input.principal, + configHash: computeManifestConfigHash(input.connection), + status: "error" as const, + tools: [], + toolCount: 0, + toolsHash: null, + toolsTruncated: false, + lastError: null, + durationMs: null, + listedAt: null, + staleAt: new Date(), + refreshStartedAt: null, + } + await db + .insert(ExternalMcpToolManifestTable) + .values(values) + .onDuplicateKeyUpdate({ + set: { + configHash: computeManifestConfigHash(input.connection), + }, + }) + const rows = await db + .select() + .from(ExternalMcpToolManifestTable) + .where(and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, input.connection.id), + eq(ExternalMcpToolManifestTable.principal, input.principal), + )) + .limit(1) + const row = rows[0] + if (!row) throw new Error("Failed to create external MCP manifest refresh lease.") + return row +} + +export function scheduleManifestRevalidation(input: RevalidationInput): void { + const key = rowKey(input.connection.id, input.principal) + if (inFlightRevalidations.has(key)) return + const task = revalidateManifest(input) + .catch((error) => { + console.warn(`[mcp-manifest][revalidate_failed] connectionId=${input.connection.id} principal=${input.principal} reason=${shortErrorMessage(error)}`) + }) + .finally(() => { + inFlightRevalidations.delete(key) + }) + inFlightRevalidations.set(key, task) +} + +export async function revalidateManifest(input: RevalidationInput): Promise { + const row = await createRefreshLeaseForPair({ connection: input.connection, principal: input.principal }) + const claimed = await claimManifestRefresh({ rowId: row.id }) + if (!claimed) return + const startedAt = Date.now() + try { + const tools = await listExternalMcpToolsWithOptions(input.connection, input.redirectUri, input.member, { + timeoutMs: env.mcpListToolsTimeoutMs, + }) + await saveManifestListing({ + connection: input.connection, + principal: input.principal, + tools, + durationMs: Date.now() - startedAt, + }) + } catch (error) { + await saveManifestFailure({ + connection: input.connection, + principal: input.principal, + error, + durationMs: Date.now() - startedAt, + }) + } +} + +function rowsAffected(result: unknown): number { + if (Array.isArray(result)) { + const first = result[0] + if (typeof first === "object" && first !== null && "affectedRows" in first) { + const affectedRows = first.affectedRows + return typeof affectedRows === "number" ? affectedRows : 0 + } + } + if (typeof result === "object" && result !== null && "rowsAffected" in result) { + const rowsAffectedValue = result.rowsAffected + return typeof rowsAffectedValue === "number" ? rowsAffectedValue : 0 + } + return 0 +} diff --git a/ee/apps/den-api/src/capability-sources/oauth-credentials.ts b/ee/apps/den-api/src/capability-sources/oauth-credentials.ts index 0dc666b801..07530139fc 100644 --- a/ee/apps/den-api/src/capability-sources/oauth-credentials.ts +++ b/ee/apps/den-api/src/capability-sources/oauth-credentials.ts @@ -1,10 +1,12 @@ -import { and, eq } from "@openwork-ee/den-db/drizzle" +import { and, eq, inArray } from "@openwork-ee/den-db/drizzle" import { ConnectedAccountTable, OrgOAuthClientTable, } from "@openwork-ee/den-db/schema" import { createDenTypeId, type DenTypeId } from "@openwork-ee/utils/typeid" import { db } from "../db.js" +import { isDenTypeId } from "@openwork-ee/utils/typeid" +import { deleteManifests } from "./external-mcp-manifests.js" /** * Generic, provider-agnostic reads/writes for the two credential tables. @@ -79,6 +81,24 @@ export async function getConnectedAccount(input: { return rows[0] ?? null } +export async function getConnectedAccounts(input: { + organizationId: OrganizationId + orgMembershipId: OrgMembershipId + providerIds: string[] +}): Promise> { + const providerIds = [...new Set(input.providerIds)] + if (providerIds.length === 0) return new Map() + const rows = await db + .select() + .from(ConnectedAccountTable) + .where(and( + eq(ConnectedAccountTable.organizationId, input.organizationId), + eq(ConnectedAccountTable.orgMembershipId, input.orgMembershipId), + inArray(ConnectedAccountTable.providerId, providerIds), + )) + return new Map(rows.map((row) => [row.providerId, row])) +} + /** Upsert used both to stash a pending PKCE verifier before redirect, and to save real tokens after exchange. */ export async function upsertConnectedAccount(input: { organizationId: OrganizationId @@ -134,5 +154,11 @@ export async function disconnectAccount(input: { const existing = await getConnectedAccount(input) if (!existing) return false await db.delete(ConnectedAccountTable).where(eq(ConnectedAccountTable.id, existing.id)) + if (isDenTypeId("externalMcpConnection", input.providerId)) { + await deleteManifests({ + connectionId: input.providerId, + principal: input.orgMembershipId, + }) + } return true } diff --git a/ee/apps/den-api/src/env.ts b/ee/apps/den-api/src/env.ts index 334fd0bd05..d5936d8817 100644 --- a/ee/apps/den-api/src/env.ts +++ b/ee/apps/den-api/src/env.ts @@ -86,6 +86,15 @@ const EnvSchema = z.object({ VERCEL_DNS_DOMAIN: z.string().optional(), DEN_PLAN_GATING_ENABLED: z.string().optional(), DEN_MCP_CONNECTIONS_GATING_ENABLED: z.string().optional(), + DEN_MCP_LIST_TOOLS_TIMEOUT_MS: z.string().optional(), + DEN_MCP_LIST_TOOLS_CONCURRENCY: z.string().optional(), + DEN_MCP_MANIFEST_CACHE_ENABLED: z.string().optional(), + DEN_MCP_MANIFEST_FRESH_TTL_MS: z.string().optional(), + DEN_MCP_MANIFEST_MAX_AGE_MS: z.string().optional(), + DEN_MCP_MANIFEST_MAX_BYTES: z.string().optional(), + DEN_MCP_MANIFEST_REFRESH_INTERVAL_MS: z.string().optional(), + DEN_MCP_MANIFEST_REFRESH_BATCH_SIZE: z.string().optional(), + DEN_MCP_MANIFEST_REFRESH_LEASE_MS: z.string().optional(), SCIM_MAINTENANCE_INTERVAL_MS: z.string().optional(), POLAR_FEATURE_GATE_ENABLED: z.string().optional(), POLAR_API_BASE: z.string().optional(), @@ -285,6 +294,15 @@ export const env = { allowPrivateMcpUrls, planGatingEnabled, mcpConnectionsGatingEnabled, + mcpListToolsTimeoutMs: Number(parsed.DEN_MCP_LIST_TOOLS_TIMEOUT_MS ?? "3500"), + mcpListToolsConcurrency: Number(parsed.DEN_MCP_LIST_TOOLS_CONCURRENCY ?? "5"), + mcpManifestCacheEnabled: (parsed.DEN_MCP_MANIFEST_CACHE_ENABLED ?? "true").toLowerCase() !== "false", + mcpManifestFreshTtlMs: Number(parsed.DEN_MCP_MANIFEST_FRESH_TTL_MS ?? "900000"), + mcpManifestMaxAgeMs: Number(parsed.DEN_MCP_MANIFEST_MAX_AGE_MS ?? "86400000"), + mcpManifestMaxBytes: Number(parsed.DEN_MCP_MANIFEST_MAX_BYTES ?? "262144"), + mcpManifestRefreshIntervalMs: Number(parsed.DEN_MCP_MANIFEST_REFRESH_INTERVAL_MS ?? "300000"), + mcpManifestRefreshBatchSize: Number(parsed.DEN_MCP_MANIFEST_REFRESH_BATCH_SIZE ?? "20"), + mcpManifestRefreshLeaseMs: Number(parsed.DEN_MCP_MANIFEST_REFRESH_LEASE_MS ?? "60000"), scimMaintenanceIntervalMs: Number(parsed.SCIM_MAINTENANCE_INTERVAL_MS ?? "300000"), requireEmailVerification, passwordBreachScreeningEnabled, diff --git a/ee/apps/den-api/src/mcp-manifest-maintenance.ts b/ee/apps/den-api/src/mcp-manifest-maintenance.ts new file mode 100644 index 0000000000..c3b449cbd6 --- /dev/null +++ b/ee/apps/den-api/src/mcp-manifest-maintenance.ts @@ -0,0 +1,186 @@ +import { and, eq, isNull, lt, lte, or, sql } from "@openwork-ee/den-db/drizzle" +import { + ConnectedAccountTable, + ExternalMcpConnectionTable, + ExternalMcpToolManifestTable, +} from "@openwork-ee/den-db/schema" +import { normalizeDenTypeId, isDenTypeId } from "@openwork-ee/utils/typeid" +import { db } from "./db.js" +import { env } from "./env.js" +import { listTeamsForMember } from "./orgs.js" +import { + deleteManifests, + getManifests, + manifestMapKey, + revalidateManifest, + type ManifestPrincipal, +} from "./capability-sources/external-mcp-manifests.js" +import { + memberCanUseExternalMcpConnection, + type ExternalMcpConnectionRow, +} from "./capability-sources/external-mcp-connections.js" + +let manifestMaintenanceRunning = false +let warnedMissingPublicUrl = false + +function redirectUriForRefresh(connectionId: string) { + if (!env.apiPublicUrl) return null + return `${env.apiPublicUrl.replace(/\/+$/, "")}/v1/mcp-connections/${encodeURIComponent(connectionId)}/connect/callback` +} + +function isSharedRefreshable(connection: ExternalMcpConnectionRow) { + if (connection.credentialMode !== "shared") return false + if (connection.authType === "oauth") return Boolean(connection.accessToken) + if (connection.authType === "apikey") return Boolean(connection.apiKey) + return true +} + +async function refreshManifestRow(row: typeof ExternalMcpToolManifestTable.$inferSelect) { + const connectionRows = await db + .select() + .from(ExternalMcpConnectionTable) + .where(eq(ExternalMcpConnectionTable.id, row.externalMcpConnectionId)) + .limit(1) + const connection = connectionRows[0] + if (!connection) { + await deleteManifests({ connectionId: row.externalMcpConnectionId, principal: row.principal as ManifestPrincipal }) + return "deleted" as const + } + + const redirectUri = redirectUriForRefresh(connection.id) + if (!redirectUri) return "skipped" as const + + if (row.principal === "shared") { + if (!isSharedRefreshable(connection)) { + await deleteManifests({ connectionId: connection.id, principal: "shared" }) + return "deleted" as const + } + await revalidateManifest({ connection, principal: "shared", redirectUri }) + return "refreshed" as const + } + + if (!isDenTypeId("member", row.principal)) { + await deleteManifests({ connectionId: connection.id, principal: row.principal as ManifestPrincipal }) + return "deleted" as const + } + const orgMembershipId = normalizeDenTypeId("member", row.principal) + const accountRows = await db + .select({ id: ConnectedAccountTable.id, accessToken: ConnectedAccountTable.accessToken }) + .from(ConnectedAccountTable) + .where(and( + eq(ConnectedAccountTable.organizationId, connection.organizationId), + eq(ConnectedAccountTable.orgMembershipId, orgMembershipId), + eq(ConnectedAccountTable.providerId, connection.id), + )) + .limit(1) + const account = accountRows[0] + if (!account?.accessToken) { + await deleteManifests({ connectionId: connection.id, principal: orgMembershipId }) + return "deleted" as const + } + const teams = await listTeamsForMember({ organizationId: connection.organizationId, memberId: orgMembershipId }) + const canUse = await memberCanUseExternalMcpConnection({ + connectionId: connection.id, + orgMembershipId, + teamIds: teams.map((team) => team.id), + }) + if (!canUse) { + await deleteManifests({ connectionId: connection.id, principal: orgMembershipId }) + return "deleted" as const + } + await revalidateManifest({ + connection, + principal: orgMembershipId, + redirectUri, + member: { orgMembershipId }, + }) + return "refreshed" as const +} + +async function seedSharedConnectionRows(limit: number) { + const connections = await db + .select() + .from(ExternalMcpConnectionTable) + .where(eq(ExternalMcpConnectionTable.credentialMode, "shared")) + .limit(limit) + let seeded = 0 + for (const connection of connections) { + if (!isSharedRefreshable(connection)) continue + const manifests = await getManifests({ pairs: [{ connection, principal: "shared" }] }) + if (manifests.has(manifestMapKey(connection.id, "shared"))) continue + const redirectUri = redirectUriForRefresh(connection.id) + if (!redirectUri) continue + await revalidateManifest({ connection, principal: "shared", redirectUri }) + seeded += 1 + } + return seeded +} + +export async function runMcpManifestMaintenanceOnce() { + if (!env.apiPublicUrl) { + if (!warnedMissingPublicUrl) { + console.warn("[mcp-manifest][refresh_disabled] reason=missing_api_public_url") + warnedMissingPublicUrl = true + } + return { scanned: 0, refreshed: 0, failures: 0, deleted: 0, seeded: 0 } + } + + const staleCutoff = new Date(Date.now() - Math.floor(env.mcpManifestFreshTtlMs * 0.8)) + const errorCutoff = new Date(Date.now() - env.mcpManifestFreshTtlMs) + const rows = await db + .select() + .from(ExternalMcpToolManifestTable) + .where(or( + and(lte(ExternalMcpToolManifestTable.staleAt, new Date())), + lt(ExternalMcpToolManifestTable.listedAt, staleCutoff), + and( + eq(ExternalMcpToolManifestTable.status, "error"), + lt(ExternalMcpToolManifestTable.updatedAt, errorCutoff), + ), + isNull(ExternalMcpToolManifestTable.listedAt), + )) + .orderBy(sql`${ExternalMcpToolManifestTable.listedAt} ASC`) + .limit(env.mcpManifestRefreshBatchSize) + + let refreshed = 0 + let failures = 0 + let deleted = 0 + for (const row of rows) { + try { + const result = await refreshManifestRow(row) + if (result === "refreshed") refreshed += 1 + if (result === "deleted") deleted += 1 + } catch (error) { + failures += 1 + const message = error instanceof Error ? error.message : String(error) + console.warn(`[mcp-manifest][refresh] connectionId=${row.externalMcpConnectionId} principal=${row.principal} status=error reason=${message}`) + } + } + const seeded = await seedSharedConnectionRows(Math.max(0, env.mcpManifestRefreshBatchSize - rows.length)) + console.info(`[mcp-manifest][refresh_summary] scanned=${rows.length} refreshed=${refreshed} failures=${failures} deleted=${deleted} seeded=${seeded}`) + return { scanned: rows.length, refreshed, failures, deleted, seeded } +} + +export function startMcpManifestMaintenanceLoop(intervalMs = env.mcpManifestRefreshIntervalMs) { + if (!Number.isFinite(intervalMs) || intervalMs <= 0) { + return () => undefined + } + + const run = () => { + if (manifestMaintenanceRunning) return + manifestMaintenanceRunning = true + void runMcpManifestMaintenanceOnce() + .catch((error) => { + const message = error instanceof Error ? error.message : String(error) + console.error(`[mcp-manifest][maintenance_failed] reason=${message}`) + }) + .finally(() => { + manifestMaintenanceRunning = false + }) + } + + const timer = setInterval(run, intervalMs) + timer.unref() + run() + return () => clearInterval(timer) +} diff --git a/ee/apps/den-api/src/mcp/agent.ts b/ee/apps/den-api/src/mcp/agent.ts index fc9543e707..15555c8035 100644 --- a/ee/apps/den-api/src/mcp/agent.ts +++ b/ee/apps/den-api/src/mcp/agent.ts @@ -103,24 +103,24 @@ export function registerAgentMcpRoutes b.score - a.score) .slice(0, boundedLimit) diff --git a/ee/apps/den-api/src/mcp/external-capabilities.ts b/ee/apps/den-api/src/mcp/external-capabilities.ts index e84fa8b70b..273db96e0d 100644 --- a/ee/apps/den-api/src/mcp/external-capabilities.ts +++ b/ee/apps/den-api/src/mcp/external-capabilities.ts @@ -8,9 +8,23 @@ import { type ExternalMcpConnectionRow, } from "../capability-sources/external-mcp-connections.js" import { callExternalMcpTool, listExternalMcpTools } from "../capability-sources/external-mcp-client.js" -import { getConnectedAccount } from "../capability-sources/oauth-credentials.js" +import { getConnectedAccount, getConnectedAccounts, type ConnectedAccountRow } from "../capability-sources/oauth-credentials.js" +import { + classifyManifest, + getManifests, + manifestMapKey, + manifestPrincipalFor, + markManifestsStale, + saveManifestFailure, + saveManifestListing, + scheduleManifestRevalidation, + type ExternalMcpToolManifestRow, + type ManifestPrincipal, +} from "../capability-sources/external-mcp-manifests.js" import { db } from "../db.js" +import { env } from "../env.js" import { listTeamsForMember } from "../orgs.js" +import { mapWithConcurrency } from "../utils/concurrency.js" import { tokenize } from "./search.js" import type { CapabilityMatch } from "./search.js" @@ -86,7 +100,7 @@ function hasSharedCredential(connection: ExternalMcpConnectionRow): boolean { return true } -function redirectUriFor(redirectUriBase: string, connectionId: string): string { +export function redirectUriFor(redirectUriBase: string, connectionId: string): string { return `${redirectUriBase}/v1/mcp-connections/${encodeURIComponent(connectionId)}/connect/callback` } @@ -116,6 +130,198 @@ function shortErrorMessage(error: unknown): string { return message.length > 120 ? `${message.slice(0, 117)}...` : message } +type ToolForSearch = { + name: string + title?: string + description?: string +} + +type ExternalSearchCounters = { + cacheHits: number + staleServed: number + misses: number + errors: number + timeouts: number +} + +function isTimeoutError(error: unknown): boolean { + if (typeof error !== "object" || error === null) return false + if ("code" in error && error.code === -32001) return true + const message = error instanceof Error ? error.message : String(error) + return /timeout|timed out/i.test(message) +} + +function isUnknownToolError(error: unknown): boolean { + if (typeof error === "object" && error !== null && "code" in error) { + const code = error.code + if (code === -32601) return true + if (code === -32602) { + const message = error instanceof Error ? error.message : String(error) + return /unknown tool|not found/i.test(message) + } + } + return false +} + +function scoreTools( + connection: ExternalMcpConnectionRow, + tools: readonly ToolForSearch[], + queryTokens: string[], +): ExternalCapabilityMatch[] { + const matches: ExternalCapabilityMatch[] = [] + for (const tool of tools) { + const summary = tool.description ?? tool.title ?? tool.name + const nameTokens = tokenize(`${connection.name} ${tool.name}`) + const summaryTokens = tokenize(summary) + const score = scoreText(nameTokens, summaryTokens, queryTokens) + if (score <= 0) continue + matches.push({ + name: buildExternalCapabilityName(connection.id, tool.name), + method: "MCP", + path: connection.url, + score, + summary: `[${connection.name}] ${summary}`, + pathParams: [], + queryParams: [], + hasBody: true, + }) + } + return matches +} + +function statusMatch(input: { + connection: ExternalMcpConnectionRow + queryTokens: string[] + status: "needs_connection" | "error" + summary: string + hint: string +}): ExternalCapabilityMatch[] { + const nameTokens = tokenize(input.connection.name) + const score = scoreText(nameTokens, nameTokens, input.queryTokens) + if (score <= 0) return [] + return [{ + name: buildExternalCapabilityName(input.connection.id, "*"), + method: "MCP", + path: input.connection.url, + score, + summary: input.summary, + pathParams: [], + queryParams: [], + hasBody: false, + status: input.status, + hint: input.hint, + }] +} + +async function listAndMaybeCache(input: { + connection: ExternalMcpConnectionRow + redirectUri: string + member?: { orgMembershipId: DenTypeId<"member"> } + principal: ManifestPrincipal + cacheEnabled: boolean + counters: ExternalSearchCounters +}) { + const startedAt = Date.now() + try { + const tools = await listExternalMcpTools(input.connection, input.redirectUri, input.member, { + timeoutMs: env.mcpListToolsTimeoutMs, + }) + if (input.cacheEnabled) { + await saveManifestListing({ + connection: input.connection, + principal: input.principal, + tools, + durationMs: Date.now() - startedAt, + }) + } + return tools + } catch (error) { + input.counters.errors += 1 + if (isTimeoutError(error)) input.counters.timeouts += 1 + if (input.cacheEnabled) { + await saveManifestFailure({ + connection: input.connection, + principal: input.principal, + error, + durationMs: Date.now() - startedAt, + }) + } + throw error + } +} + +async function collectConnectionMatches(input: { + connection: ExternalMcpConnectionRow + account?: ConnectedAccountRow + manifest?: ExternalMcpToolManifestRow + queryTokens: string[] + redirectUriBase: string + orgMembershipId: DenTypeId<"member"> + counters: ExternalSearchCounters +}): Promise { + const { connection, queryTokens } = input + if (connection.credentialMode === "per_member") { + if (!input.account?.accessToken) { + return statusMatch({ + connection, + queryTokens, + status: "needs_connection", + summary: `[${connection.name}] Available to you, but you haven't connected your ${connection.name} account yet.`, + hint: `Ask the user to open OpenWork Cloud -> Your Connections and click Connect on "${connection.name}", then search again.`, + }) + } + } else if (!hasSharedCredential(connection)) { + return statusMatch({ + connection, + queryTokens, + status: "needs_connection", + summary: `[${connection.name}] Available to your organization, but an admin hasn't connected it yet.`, + hint: `Ask an org admin to open the OpenWork Cloud dashboard -> Connections and connect "${connection.name}", then search again.`, + }) + } + + const member = connection.credentialMode === "per_member" + ? { orgMembershipId: input.orgMembershipId } + : undefined + const principal = manifestPrincipalFor(connection, member) + const redirectUri = redirectUriFor(input.redirectUriBase, connection.id) + + if (env.mcpManifestCacheEnabled) { + const classification = classifyManifest(input.manifest ?? null, connection) + if (classification.state === "fresh") { + input.counters.cacheHits += 1 + return scoreTools(connection, classification.row.tools, queryTokens) + } + if (classification.state === "stale") { + input.counters.staleServed += 1 + scheduleManifestRevalidation({ connection, principal, redirectUri, member }) + return scoreTools(connection, classification.row.tools, queryTokens) + } + input.counters.misses += 1 + } + + try { + const tools = await listAndMaybeCache({ + connection, + redirectUri, + member, + principal, + cacheEnabled: env.mcpManifestCacheEnabled, + counters: input.counters, + }) + return scoreTools(connection, tools, queryTokens) + } catch (error) { + const message = shortErrorMessage(error) + return statusMatch({ + connection, + queryTokens, + status: "error", + summary: `[${connection.name}] This connection is set up but not responding right now (${message}).`, + hint: `The stored credential may be expired or the server may be unreachable. Reconnect "${connection.name}" from the OpenWork Cloud dashboard -> Connections, then search again.`, + }) + } +} + /** * Live-lists tools for every external MCP connection the calling member has * been granted, and returns the ones matching `query`, in the same @@ -130,110 +336,65 @@ export async function searchExternalCapabilities(input: { limit?: number }): Promise { if (!input.member) return [] + const memberIdentity = input.member const queryTokens = tokenize(input.query) if (queryTokens.length === 0) return [] const connections = await listUsableExternalMcpConnections({ organizationId: normalizeDenTypeId("organization", input.organizationId), - orgMembershipId: input.member.orgMembershipId, - teamIds: input.member.teamIds, + orgMembershipId: memberIdentity.orgMembershipId, + teamIds: memberIdentity.teamIds, }) - const matches: ExternalCapabilityMatch[] = [] - - for (const connection of connections) { - if (connection.credentialMode === "per_member") { - const account = await getConnectedAccount({ - organizationId: connection.organizationId, - orgMembershipId: input.member.orgMembershipId, - providerId: connection.id, + const startedAt = Date.now() + const counters: ExternalSearchCounters = { + cacheHits: 0, + staleServed: 0, + misses: 0, + errors: 0, + timeouts: 0, + } + const perMemberConnections = connections.filter((connection) => connection.credentialMode === "per_member") + const accounts = await getConnectedAccounts({ + organizationId: normalizeDenTypeId("organization", input.organizationId), + orgMembershipId: memberIdentity.orgMembershipId, + providerIds: perMemberConnections.map((connection) => connection.id), + }) + const manifestPairs = env.mcpManifestCacheEnabled + ? connections + .filter((connection) => connection.credentialMode === "shared" ? hasSharedCredential(connection) : Boolean(accounts.get(connection.id)?.accessToken)) + .map((connection) => ({ + connection, + principal: manifestPrincipalFor( + connection, + connection.credentialMode === "per_member" + ? { orgMembershipId: memberIdentity.orgMembershipId } + : undefined, + ), + })) + : [] + const manifests = await getManifests({ pairs: manifestPairs }) + const matchesByConnection = await mapWithConcurrency( + connections, + env.mcpListToolsConcurrency, + (connection) => { + const account = accounts.get(connection.id) + const principal = connection.credentialMode === "per_member" + ? memberIdentity.orgMembershipId + : "shared" + return collectConnectionMatches({ + connection, + account, + manifest: manifests.get(manifestMapKey(connection.id, principal)), + queryTokens, + redirectUriBase: input.redirectUriBase, + orgMembershipId: memberIdentity.orgMembershipId, + counters, }) - if (!account?.accessToken) { - // Granted but not yet connected: surface the connection itself (not - // its tools — we can't list them without the member's credential) so - // the agent can tell the human exactly what to do. - const nameTokens = tokenize(connection.name) - const score = scoreText(nameTokens, nameTokens, queryTokens) - if (score > 0) { - matches.push({ - name: buildExternalCapabilityName(connection.id, "*"), - method: "MCP", - path: connection.url, - score, - summary: `[${connection.name}] Available to you, but you haven't connected your ${connection.name} account yet.`, - pathParams: [], - queryParams: [], - hasBody: false, - status: "needs_connection", - hint: `Ask the user to open OpenWork Cloud -> Your Connections and click Connect on "${connection.name}", then search again.`, - }) - } - continue - } - } else if (!hasSharedCredential(connection)) { - const nameTokens = tokenize(connection.name) - const score = scoreText(nameTokens, nameTokens, queryTokens) - if (score > 0) { - matches.push({ - name: buildExternalCapabilityName(connection.id, "*"), - method: "MCP", - path: connection.url, - score, - summary: `[${connection.name}] Available to your organization, but an admin hasn't connected it yet.`, - pathParams: [], - queryParams: [], - hasBody: false, - status: "needs_connection", - hint: `Ask an org admin to open the OpenWork Cloud dashboard -> Connections and connect "${connection.name}", then search again.`, - }) - } - continue - } + }, + ) + const matches = matchesByConnection.flat() - const member = connection.credentialMode === "per_member" - ? { orgMembershipId: input.member.orgMembershipId } - : undefined - let tools: Awaited> - try { - tools = await listExternalMcpTools(connection, redirectUriFor(input.redirectUriBase, connection.id), member) - } catch (error) { - const message = shortErrorMessage(error) - const nameTokens = tokenize(connection.name) - const score = scoreText(nameTokens, nameTokens, queryTokens) - if (score > 0) { - matches.push({ - name: buildExternalCapabilityName(connection.id, "*"), - method: "MCP", - path: connection.url, - score, - summary: `[${connection.name}] This connection is set up but not responding right now (${message}).`, - pathParams: [], - queryParams: [], - hasBody: false, - status: "error", - hint: `The stored credential may be expired or the server may be unreachable. Reconnect "${connection.name}" from the OpenWork Cloud dashboard -> Connections, then search again.`, - }) - } - continue - } - - for (const tool of tools) { - const summary = tool.description ?? tool.title ?? tool.name - const nameTokens = tokenize(`${connection.name} ${tool.name}`) - const summaryTokens = tokenize(summary) - const score = scoreText(nameTokens, summaryTokens, queryTokens) - if (score <= 0) continue - matches.push({ - name: buildExternalCapabilityName(connection.id, tool.name), - method: "MCP", - path: connection.url, - score, - summary: `[${connection.name}] ${summary}`, - pathParams: [], - queryParams: [], - hasBody: true, - }) - } - } + console.info(`[mcp-agent][external_mcp_search] connections=${connections.length} cache_hits=${counters.cacheHits} stale_served=${counters.staleServed} misses=${counters.misses} errors=${counters.errors} timeouts=${counters.timeouts} durationMs=${Date.now() - startedAt}`) matches.sort((a, b) => (b.score - a.score) || a.name.localeCompare(b.name)) return matches.slice(0, input.limit ?? 5) @@ -316,12 +477,21 @@ export async function executeExternalCapability(input: { return { ok: false, error: "connection_not_connected", message: `"${connection.name}" is not connected yet.` } } - const result = await callExternalMcpTool({ - connection, - redirectUri: redirectUriFor(input.redirectUriBase, connection.id), - toolName: input.toolName, - args: input.args, - member, - }) + let result: Awaited> + try { + result = await callExternalMcpTool({ + connection, + redirectUri: redirectUriFor(input.redirectUriBase, connection.id), + toolName: input.toolName, + args: input.args, + member, + }) + } catch (error) { + if (isUnknownToolError(error)) { + const principal = manifestPrincipalFor(connection, member) + void markManifestsStale({ connectionId: connection.id, principal }) + } + throw error + } return { ok: true, result } } diff --git a/ee/apps/den-api/src/routes/org/mcp-connections.ts b/ee/apps/den-api/src/routes/org/mcp-connections.ts index b3313b559f..aea07eb285 100644 --- a/ee/apps/den-api/src/routes/org/mcp-connections.ts +++ b/ee/apps/den-api/src/routes/org/mcp-connections.ts @@ -18,6 +18,14 @@ import { connectExternalMcp, completeExternalMcpAuth, } from "../../capability-sources/external-mcp-client.js" +import { + getManifests, + manifestMapKey, + manifestPrincipalFor, + revalidateManifest, + deleteManifests, + type ManifestPrincipal, +} from "../../capability-sources/external-mcp-manifests.js" import { createExternalMcpConnection, deleteExternalMcpConnection, @@ -90,6 +98,13 @@ const connectionResponseSchema = z.object({ connectedForMe: z.boolean(), /** Present only for scope=manageable (admin) listings. */ access: accessSummarySchema.nullable(), + tools: z.object({ + count: z.number(), + listedAt: z.string().nullable(), + status: z.enum(["ok", "error"]), + truncated: z.boolean(), + lastError: z.string().nullable(), + }).nullable(), }).meta({ ref: "ExternalMcpConnectionResponse" }) const connectionListResponseSchema = z.object({ @@ -158,6 +173,13 @@ const connectionValidationFailedSchema = z.object({ message: z.string(), }).meta({ ref: "ExternalMcpConnectionValidationFailedError" }) +const refreshToolsResponseSchema = z.object({ + status: z.enum(["ok", "error"]), + toolCount: z.number(), + listedAt: z.string().nullable(), + message: z.string().optional(), +}).meta({ ref: "ExternalMcpRefreshToolsResponse" }) + function errorMessage(error: unknown) { return error instanceof Error ? error.message : String(error) } @@ -195,6 +217,12 @@ async function toConnectionResponse( connectedForMe = Boolean(account?.accessToken) } + const principal: ManifestPrincipal = row.credentialMode === "per_member" + ? options.callerOrgMembershipId + : "shared" + const manifests = await getManifests({ pairs: [{ connection: row, principal }] }) + const manifest = manifests.get(manifestMapKey(row.id, principal)) + let access: { orgWide: boolean; memberIds: string[]; teamIds: string[] } | null = null if (options.includeAccess) { const grants = await listExternalMcpConnectionAccess(row.id) @@ -215,6 +243,15 @@ async function toConnectionResponse( connectedAt: row.connectedAt ? row.connectedAt.toISOString() : null, connectedForMe, access, + tools: manifest + ? { + count: manifest.toolCount, + listedAt: manifest.listedAt ? manifest.listedAt.toISOString() : null, + status: manifest.status, + truncated: manifest.toolsTruncated, + lastError: manifest.lastError, + } + : null, } } @@ -517,6 +554,66 @@ export function registerMcpConnectionRoutes { + const payload = c.get("organizationContext") + const { connectionId } = c.req.valid("param") + const externalMcpConnectionId = normalizeDenTypeId("externalMcpConnection", connectionId) + const connection = await getExternalMcpConnection({ organizationId: payload.organization.id, connectionId: externalMcpConnectionId }) + if (!connection) { + return c.json({ error: "connection_not_found", message: "Unknown connection." }, 404) + } + + const memberTeams: MemberTeamSummary[] = c.get("memberTeams") ?? [] + const isAdmin = verifyOrgRole({ roles: ["admin"], userContext: payload.currentMember }) + const canUse = await memberCanUseExternalMcpConnection({ + connectionId: externalMcpConnectionId, + orgMembershipId: payload.currentMember.id, + teamIds: memberTeams.map((team) => team.id), + }) + if (!isAdmin && !canUse) { + return c.json({ error: "forbidden", message: "You have not been granted access to this connection." }, 403) + } + + if (connection.credentialMode === "shared" && !isAdmin) { + return c.json({ error: "forbidden", message: "Only workspace owners and admins can refresh a shared org-account connection." }, 403) + } + const member = connection.credentialMode === "per_member" + ? { orgMembershipId: payload.currentMember.id } + : undefined + const principal = manifestPrincipalFor(connection, member) + await revalidateManifest({ + connection, + principal, + redirectUri: callbackRedirectUri(c.req.raw, connection.id), + member, + }) + const manifests = await getManifests({ pairs: [{ connection, principal }] }) + const manifest = manifests.get(manifestMapKey(connection.id, principal)) + return c.json({ + status: manifest?.status ?? "error", + toolCount: manifest?.toolCount ?? 0, + listedAt: manifest?.listedAt ? manifest.listedAt.toISOString() : null, + ...(manifest?.lastError ? { message: manifest.lastError } : {}), + }) + }, + ) + app.get( "/v1/mcp-connections/:connectionId/connect/start", describeRoute({ @@ -636,6 +733,10 @@ export function registerMcpConnectionRoutes( + items: readonly T[], + limit: number, + fn: (item: T, index: number) => Promise, +): Promise { + if (items.length === 0) return [] + const workerCount = Math.max(1, Math.min(Math.floor(limit), items.length)) + const results: R[] = new Array(items.length) + let nextIndex = 0 + + async function worker() { + while (nextIndex < items.length) { + const index = nextIndex + nextIndex += 1 + results[index] = await fn(items[index], index) + } + } + + await Promise.all(Array.from({ length: workerCount }, () => worker())) + return results +} diff --git a/ee/apps/den-api/test/concurrency-util.test.ts b/ee/apps/den-api/test/concurrency-util.test.ts new file mode 100644 index 0000000000..73daf46f2d --- /dev/null +++ b/ee/apps/den-api/test/concurrency-util.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, test } from "bun:test" +import { mapWithConcurrency } from "../src/utils/concurrency.js" + +describe("mapWithConcurrency", () => { + test("preserves input order while bounding in-flight work", async () => { + let inFlight = 0 + let maxInFlight = 0 + const results = await mapWithConcurrency([3, 2, 1, 0], 2, async (value) => { + inFlight += 1 + maxInFlight = Math.max(maxInFlight, inFlight) + await new Promise((resolve) => setTimeout(resolve, value * 5)) + inFlight -= 1 + return value * 10 + }) + + expect(results).toEqual([30, 20, 10, 0]) + expect(maxInFlight).toBeLessThanOrEqual(2) + }) +}) diff --git a/ee/apps/den-api/test/mcp-agent-config-policy.test.ts b/ee/apps/den-api/test/mcp-agent-config-policy.test.ts index 63f4e83fad..2b972040c4 100644 --- a/ee/apps/den-api/test/mcp-agent-config-policy.test.ts +++ b/ee/apps/den-api/test/mcp-agent-config-policy.test.ts @@ -66,6 +66,7 @@ describe("agent-configurable org connections policy", () => { test("discovery surfaces the agent needs are readable", () => { expect(allowed("getV1McpConnections")).toBe(true) expect(allowed("getV1McpConnectionsPresets")).toBe(true) + expect(allowed("postV1McpConnectionsByConnectionIdRefreshTools")).toBe(true) }) test("agent catalog search discovers member list and admin create mcp-connection operations", () => { diff --git a/ee/packages/den-db/drizzle/0032_stale_lady_vermin.sql b/ee/packages/den-db/drizzle/0032_stale_lady_vermin.sql new file mode 100644 index 0000000000..72aaa252a5 --- /dev/null +++ b/ee/packages/den-db/drizzle/0032_stale_lady_vermin.sql @@ -0,0 +1,25 @@ +CREATE TABLE `external_mcp_tool_manifest` ( + `id` varchar(64) NOT NULL, + `organization_id` varchar(64) NOT NULL, + `external_mcp_connection_id` varchar(64) NOT NULL, + `principal` varchar(64) NOT NULL, + `config_hash` varchar(64) NOT NULL, + `status` enum('ok','error') NOT NULL, + `tools` json NOT NULL, + `tool_count` int NOT NULL DEFAULT 0, + `tools_hash` varchar(64), + `tools_truncated` boolean NOT NULL DEFAULT false, + `last_error` text, + `duration_ms` int, + `listed_at` timestamp(3), + `stale_at` timestamp(3), + `refresh_started_at` timestamp(3), + `created_at` timestamp(3) NOT NULL DEFAULT (now()), + `updated_at` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), + CONSTRAINT `external_mcp_tool_manifest_id` PRIMARY KEY(`id`), + CONSTRAINT `emtm_connection_principal` UNIQUE(`external_mcp_connection_id`,`principal`) +); +--> statement-breakpoint +CREATE INDEX `emtm_organization_id` ON `external_mcp_tool_manifest` (`organization_id`);--> statement-breakpoint +CREATE INDEX `emtm_listed_at` ON `external_mcp_tool_manifest` (`listed_at`);--> statement-breakpoint +CREATE INDEX `emtm_refresh_started_at` ON `external_mcp_tool_manifest` (`refresh_started_at`); \ No newline at end of file diff --git a/ee/packages/den-db/drizzle/meta/0032_snapshot.json b/ee/packages/den-db/drizzle/meta/0032_snapshot.json new file mode 100644 index 0000000000..559289ea28 --- /dev/null +++ b/ee/packages/den-db/drizzle/meta/0032_snapshot.json @@ -0,0 +1,8763 @@ +{ + "version": "5", + "dialect": "mysql", + "id": "a565b456-3a04-4c0e-a42c-45ed20967e93", + "prevId": "5a458e2c-34f3-4b47-acab-835bd3dcf180", + "tables": { + "account": { + "name": "account", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "account_user_id": { + "name": "account_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "account_id": { + "name": "account_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "apikey": { + "name": "apikey", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_id": { + "name": "config_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'default'" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "start": { + "name": "start", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "prefix": { + "name": "prefix", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reference_id": { + "name": "reference_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "refill_interval": { + "name": "refill_interval", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "request_count": { + "name": "request_count", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "apikey_config_id": { + "name": "apikey_config_id", + "columns": [ + "config_id" + ], + "isUnique": false + }, + "apikey_reference_id": { + "name": "apikey_reference_id", + "columns": [ + "reference_id" + ], + "isUnique": false + }, + "apikey_key": { + "name": "apikey_key", + "columns": [ + "key" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "apikey_id": { + "name": "apikey_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "jwks": { + "name": "jwks", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "alg": { + "name": "alg", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "crv": { + "name": "crv", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "jwks_id": { + "name": "jwks_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "session": { + "name": "session", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "active_team_id": { + "name": "active_team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "session_token": { + "name": "session_token", + "columns": [ + "token" + ], + "isUnique": true + }, + "session_user_id": { + "name": "session_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "session_id": { + "name": "session_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "user_email": { + "name": "user_email", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "user_id": { + "name": "user_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "verification": { + "name": "verification", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "identifier": { + "name": "identifier", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "verification_identifier": { + "name": "verification_identifier", + "columns": [ + "identifier" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verification_id": { + "name": "verification_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "external_identity": { + "name": "external_identity", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scim_provider_id": { + "name": "scim_provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(191)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_id": { + "name": "external_id", + "type": "varchar(191)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_name": { + "name": "user_name", + "type": "varchar(191)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(191)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "varchar(191)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name_json": { + "name": "name_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "emails_json": { + "name": "emails_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "attributes_json": { + "name": "attributes_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "last_scim_sync_at": { + "name": "last_scim_sync_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_sso_login_at": { + "name": "last_sso_login_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "external_identity_org_user": { + "name": "external_identity_org_user", + "columns": [ + "organization_id", + "user_id" + ], + "isUnique": true + }, + "external_identity_org_sso_remote": { + "name": "external_identity_org_sso_remote", + "columns": [ + "organization_id", + "sso_provider_id", + "remote_id" + ], + "isUnique": true + }, + "external_identity_org_scim_external": { + "name": "external_identity_org_scim_external", + "columns": [ + "organization_id", + "scim_provider_id", + "external_id" + ], + "isUnique": true + }, + "external_identity_org_email": { + "name": "external_identity_org_email", + "columns": [ + "organization_id", + "email" + ], + "isUnique": false + }, + "external_identity_sso_provider": { + "name": "external_identity_sso_provider", + "columns": [ + "sso_provider_id" + ], + "isUnique": false + }, + "external_identity_scim_provider": { + "name": "external_identity_scim_provider", + "columns": [ + "scim_provider_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "external_identity_id": { + "name": "external_identity_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "oauthAccessToken": { + "name": "oauthAccessToken", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reference_id": { + "name": "reference_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_id": { + "name": "refresh_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "oauth_access_token_client_id": { + "name": "oauth_access_token_client_id", + "columns": [ + "client_id" + ], + "isUnique": false + }, + "oauth_access_token_session_id": { + "name": "oauth_access_token_session_id", + "columns": [ + "session_id" + ], + "isUnique": false + }, + "oauth_access_token_user_id": { + "name": "oauth_access_token_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "oauth_access_token_reference_id": { + "name": "oauth_access_token_reference_id", + "columns": [ + "reference_id" + ], + "isUnique": false + }, + "oauth_access_token_refresh_id": { + "name": "oauth_access_token_refresh_id", + "columns": [ + "refresh_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "oauthAccessToken_id": { + "name": "oauthAccessToken_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "oauthClient": { + "name": "oauthClient", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "skip_consent": { + "name": "skip_consent", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enable_end_session": { + "name": "enable_end_session", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "subject_type": { + "name": "subject_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "contacts": { + "name": "contacts", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tos": { + "name": "tos", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "policy": { + "name": "policy", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "software_id": { + "name": "software_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "software_version": { + "name": "software_version", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "software_statement": { + "name": "software_statement", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "redirect_uris": { + "name": "redirect_uris", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "post_logout_redirect_uris": { + "name": "post_logout_redirect_uris", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_endpoint_auth_method": { + "name": "token_endpoint_auth_method", + "type": "varchar(128)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "grant_types": { + "name": "grant_types", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "response_types": { + "name": "response_types", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public": { + "name": "public", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "require_pkce": { + "name": "require_pkce", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reference_id": { + "name": "reference_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "oauth_client_client_id": { + "name": "oauth_client_client_id", + "columns": [ + "client_id" + ], + "isUnique": true + }, + "oauth_client_user_id": { + "name": "oauth_client_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "oauth_client_reference_id": { + "name": "oauth_client_reference_id", + "columns": [ + "reference_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "oauthClient_id": { + "name": "oauthClient_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "oauthConsent": { + "name": "oauthConsent", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reference_id": { + "name": "reference_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "oauth_consent_client_id": { + "name": "oauth_consent_client_id", + "columns": [ + "client_id" + ], + "isUnique": false + }, + "oauth_consent_user_id": { + "name": "oauth_consent_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "oauth_consent_reference_id": { + "name": "oauth_consent_reference_id", + "columns": [ + "reference_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "oauthConsent_id": { + "name": "oauthConsent_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "oauthRefreshToken": { + "name": "oauthRefreshToken", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reference_id": { + "name": "reference_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "revoked": { + "name": "revoked", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_time": { + "name": "auth_time", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "oauth_refresh_token_client_id": { + "name": "oauth_refresh_token_client_id", + "columns": [ + "client_id" + ], + "isUnique": false + }, + "oauth_refresh_token_session_id": { + "name": "oauth_refresh_token_session_id", + "columns": [ + "session_id" + ], + "isUnique": false + }, + "oauth_refresh_token_user_id": { + "name": "oauth_refresh_token_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "oauth_refresh_token_reference_id": { + "name": "oauth_refresh_token_reference_id", + "columns": [ + "reference_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "oauthRefreshToken_id": { + "name": "oauthRefreshToken_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "scim_provider": { + "name": "scim_provider", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scim_token": { + "name": "scim_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "scim_provider_provider_id": { + "name": "scim_provider_provider_id", + "columns": [ + "provider_id" + ], + "isUnique": true + }, + "scim_provider_organization_id": { + "name": "scim_provider_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "scim_provider_id": { + "name": "scim_provider_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "scim_sync_event": { + "name": "scim_sync_event", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "payload_json": { + "name": "payload_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "next_retry_at": { + "name": "next_retry_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "scim_sync_event_org_status": { + "name": "scim_sync_event_org_status", + "columns": [ + "organization_id", + "status" + ], + "isUnique": false + }, + "scim_sync_event_provider_status": { + "name": "scim_sync_event_provider_status", + "columns": [ + "provider_id", + "status" + ], + "isUnique": false + }, + "scim_sync_event_next_retry": { + "name": "scim_sync_event_next_retry", + "columns": [ + "next_retry_at" + ], + "isUnique": false + }, + "scim_sync_event_user": { + "name": "scim_sync_event_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "scim_sync_event_id": { + "name": "scim_sync_event_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "sso_connection": { + "name": "sso_connection", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "kind": { + "name": "kind", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "issuer": { + "name": "issuer", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "domain": { + "name": "domain", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'enabled'" + }, + "sign_in_path": { + "name": "sign_in_path", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_tested_at": { + "name": "last_tested_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "sso_connection_organization_id": { + "name": "sso_connection_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": true + }, + "sso_connection_provider_id": { + "name": "sso_connection_provider_id", + "columns": [ + "provider_id" + ], + "isUnique": true + }, + "sso_connection_domain": { + "name": "sso_connection_domain", + "columns": [ + "domain" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "sso_connection_id": { + "name": "sso_connection_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "sso_provider": { + "name": "sso_provider", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "issuer": { + "name": "issuer", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "domain": { + "name": "domain", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "domain_verified": { + "name": "domain_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "sso_provider_provider_id": { + "name": "sso_provider_provider_id", + "columns": [ + "provider_id" + ], + "isUnique": true + }, + "sso_provider_domain": { + "name": "sso_provider_domain", + "columns": [ + "domain" + ], + "isUnique": false + }, + "sso_provider_organization_id": { + "name": "sso_provider_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "sso_provider_user_id": { + "name": "sso_provider_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "sso_provider_id": { + "name": "sso_provider_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "desktop_policy_member": { + "name": "desktop_policy_member", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "desktop_policy_id": { + "name": "desktop_policy_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_member_id": { + "name": "org_member_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "desktop_policy_member_organization_id": { + "name": "desktop_policy_member_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "desktop_policy_member_policy_id": { + "name": "desktop_policy_member_policy_id", + "columns": [ + "desktop_policy_id" + ], + "isUnique": false + }, + "desktop_policy_member_org_member_id": { + "name": "desktop_policy_member_org_member_id", + "columns": [ + "org_member_id" + ], + "isUnique": false + }, + "desktop_policy_member_team_id": { + "name": "desktop_policy_member_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "desktop_policy_member_policy_org_member": { + "name": "desktop_policy_member_policy_org_member", + "columns": [ + "desktop_policy_id", + "org_member_id" + ], + "isUnique": true + }, + "desktop_policy_member_policy_team": { + "name": "desktop_policy_member_policy_team", + "columns": [ + "desktop_policy_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "desktop_policy_member_id": { + "name": "desktop_policy_member_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "desktop_policy": { + "name": "desktop_policy", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "policy_name": { + "name": "policy_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "policy": { + "name": "policy", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(json_object())" + }, + "created_by_org_member_id": { + "name": "created_by_org_member_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "desktop_policy_organization_id": { + "name": "desktop_policy_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "desktop_policy_created_by_member_id": { + "name": "desktop_policy_created_by_member_id", + "columns": [ + "created_by_org_member_id" + ], + "isUnique": false + }, + "desktop_policy_is_enabled": { + "name": "desktop_policy_is_enabled", + "columns": [ + "is_enabled" + ], + "isUnique": false + }, + "desktop_policy_deleted_at": { + "name": "desktop_policy_deleted_at", + "columns": [ + "deleted_at" + ], + "isUnique": false + }, + "desktop_policy_org_default": { + "name": "desktop_policy_org_default", + "columns": [ + "organization_id", + "is_default" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "desktop_policy_id": { + "name": "desktop_policy_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_keys": { + "name": "inference_keys", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_hash": { + "name": "key_hash", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key_prefix": { + "name": "key_prefix", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','revoked')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "inference_keys_key_hash": { + "name": "inference_keys_key_hash", + "columns": [ + "key_hash" + ], + "isUnique": true + }, + "inference_keys_organization_id": { + "name": "inference_keys_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "inference_keys_org_membership_id": { + "name": "inference_keys_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "inference_keys_status": { + "name": "inference_keys_status", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_keys_id": { + "name": "inference_keys_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_org_limit_policies": { + "name": "inference_org_limit_policies", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "window_type": { + "name": "window_type", + "type": "enum('five_hour','weekly','monthly')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reset_strategy": { + "name": "reset_strategy", + "type": "enum('anchored','activity_based')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "anchor_at": { + "name": "anchor_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "current_bucket_id": { + "name": "current_bucket_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "inference_org_limit_policies_organization_id": { + "name": "inference_org_limit_policies_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "inference_org_limit_policies_org_window_type": { + "name": "inference_org_limit_policies_org_window_type", + "columns": [ + "organization_id", + "window_type" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_org_limit_policies_id": { + "name": "inference_org_limit_policies_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_org_upstream_provider_keys": { + "name": "inference_org_upstream_provider_keys", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'openrouter'" + }, + "external_key_hash": { + "name": "external_key_hash", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_workspace_id": { + "name": "external_workspace_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_api_key": { + "name": "encrypted_api_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key_prefix": { + "name": "key_prefix", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','revoked')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "inference_org_upstream_provider_keys_organization_id": { + "name": "inference_org_upstream_provider_keys_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "inference_org_upstream_provider_keys_external_key_hash": { + "name": "inference_org_upstream_provider_keys_external_key_hash", + "columns": [ + "external_key_hash" + ], + "isUnique": false + }, + "inference_org_upstream_provider_keys_org_provider": { + "name": "inference_org_upstream_provider_keys_org_provider", + "columns": [ + "organization_id", + "provider" + ], + "isUnique": true + }, + "inference_org_upstream_provider_keys_status": { + "name": "inference_org_upstream_provider_keys_status", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_org_upstream_provider_keys_id": { + "name": "inference_org_upstream_provider_keys_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_org_usage_buckets": { + "name": "inference_org_usage_buckets", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "policy_id": { + "name": "policy_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "window_start_at": { + "name": "window_start_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "window_end_at": { + "name": "window_end_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "limit_amount": { + "name": "limit_amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "used_amount": { + "name": "used_amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "inference_org_usage_buckets_org_window": { + "name": "inference_org_usage_buckets_org_window", + "columns": [ + "organization_id", + "window_start_at", + "window_end_at" + ], + "isUnique": false + }, + "inference_org_usage_buckets_policy_id": { + "name": "inference_org_usage_buckets_policy_id", + "columns": [ + "policy_id" + ], + "isUnique": false + }, + "inference_org_usage_buckets_policy_window": { + "name": "inference_org_usage_buckets_policy_window", + "columns": [ + "policy_id", + "window_start_at", + "window_end_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_org_usage_buckets_id": { + "name": "inference_org_usage_buckets_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_usage_ledger_bucket_charges": { + "name": "inference_usage_ledger_bucket_charges", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ledger_entry_id": { + "name": "ledger_entry_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "bucket_id": { + "name": "bucket_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "amount": { + "name": "amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "inference_usage_ledger_bucket_charges_bucket_id": { + "name": "inference_usage_ledger_bucket_charges_bucket_id", + "columns": [ + "bucket_id" + ], + "isUnique": false + }, + "inference_usage_ledger_bucket_charges_entry_bucket": { + "name": "inference_usage_ledger_bucket_charges_entry_bucket", + "columns": [ + "ledger_entry_id", + "bucket_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_usage_ledger_bucket_charges_id": { + "name": "inference_usage_ledger_bucket_charges_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "inference_usage_ledger_entries": { + "name": "inference_usage_ledger_entries", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "inference_key_id": { + "name": "inference_key_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_job_id": { + "name": "external_job_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_event_id": { + "name": "external_event_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cost_amount": { + "name": "cost_amount", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_type": { + "name": "event_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "occurred_at": { + "name": "occurred_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "inference_usage_ledger_entries_organization_id": { + "name": "inference_usage_ledger_entries_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "inference_usage_ledger_entries_org_membership_id": { + "name": "inference_usage_ledger_entries_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "inference_usage_ledger_entries_inference_key_id": { + "name": "inference_usage_ledger_entries_inference_key_id", + "columns": [ + "inference_key_id" + ], + "isUnique": false + }, + "inference_usage_ledger_entries_external_event_id": { + "name": "inference_usage_ledger_entries_external_event_id", + "columns": [ + "external_event_id" + ], + "isUnique": true + }, + "inference_usage_ledger_entries_job_event_type": { + "name": "inference_usage_ledger_entries_job_event_type", + "columns": [ + "external_job_id", + "event_type" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "inference_usage_ledger_entries_id": { + "name": "inference_usage_ledger_entries_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "memory_context": { + "name": "memory_context", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "memory_id": { + "name": "memory_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "citation": { + "name": "citation", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "snippet": { + "name": "snippet", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "origin": { + "name": "origin", + "type": "enum('active_conversation','searched_conversation')", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "memory_context_memory_id": { + "name": "memory_context_memory_id", + "columns": [ + "memory_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "memory_context_id": { + "name": "memory_context_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "memory": { + "name": "memory", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_id": { + "name": "org_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "enum('user','org')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'user'" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "memory_user_id": { + "name": "memory_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "memory_id": { + "name": "memory_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "desktop_handoff_grant": { + "name": "desktop_handoff_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "desktop_handoff_grant_user_id": { + "name": "desktop_handoff_grant_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "desktop_handoff_grant_expires_at": { + "name": "desktop_handoff_grant_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "desktop_handoff_grant_id": { + "name": "desktop_handoff_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "install_link": { + "name": "install_link", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_hash": { + "name": "token_hash", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "install_link_token_hash": { + "name": "install_link_token_hash", + "columns": [ + "token_hash" + ], + "isUnique": true + }, + "install_link_organization_id": { + "name": "install_link_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "install_link_created_by_user_id": { + "name": "install_link_created_by_user_id", + "columns": [ + "created_by_user_id" + ], + "isUnique": false + }, + "install_link_revoked_at": { + "name": "install_link_revoked_at", + "columns": [ + "revoked_at" + ], + "isUnique": false + }, + "install_link_expires_at": { + "name": "install_link_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "install_link_id": { + "name": "install_link_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "invitation": { + "name": "invitation", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_member_id": { + "name": "org_member_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "invite_token": { + "name": "invite_token", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "invitation_organization_id": { + "name": "invitation_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "invitation_email": { + "name": "invitation_email", + "columns": [ + "email" + ], + "isUnique": false + }, + "invitation_status": { + "name": "invitation_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "invitation_team_id": { + "name": "invitation_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "invitation_org_member_id": { + "name": "invitation_org_member_id", + "columns": [ + "org_member_id" + ], + "isUnique": false + }, + "invitation_invite_token": { + "name": "invitation_invite_token", + "columns": [ + "invite_token" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "invitation_id": { + "name": "invitation_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "member": { + "name": "member", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "invite_id": { + "name": "invite_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "invited_by_org_member": { + "name": "invited_by_org_member", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'member'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "removed_by_org_member": { + "name": "removed_by_org_member", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "member_organization_id": { + "name": "member_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "member_user_id": { + "name": "member_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "member_invite_id": { + "name": "member_invite_id", + "columns": [ + "invite_id" + ], + "isUnique": false + }, + "member_invited_by_org_member": { + "name": "member_invited_by_org_member", + "columns": [ + "invited_by_org_member" + ], + "isUnique": false + }, + "member_removed_at": { + "name": "member_removed_at", + "columns": [ + "removed_at" + ], + "isUnique": false + }, + "member_removed_by_org_member": { + "name": "member_removed_by_org_member", + "columns": [ + "removed_by_org_member" + ], + "isUnique": false + }, + "member_organization_user": { + "name": "member_organization_user", + "columns": [ + "organization_id", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "member_id": { + "name": "member_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "organization_role": { + "name": "organization_role", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "organization_role_organization_id": { + "name": "organization_role_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "organization_role_name": { + "name": "organization_role_name", + "columns": [ + "organization_id", + "role" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "organization_role_id": { + "name": "organization_role_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "organization": { + "name": "organization", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "logo": { + "name": "logo", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allowed_email_domains": { + "name": "allowed_email_domains", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "desktop_app_restrictions": { + "name": "desktop_app_restrictions", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(json_object())" + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "organization_slug": { + "name": "organization_slug", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "organization_id": { + "name": "organization_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "workspace_bootstrap": { + "name": "workspace_bootstrap", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "setup_member_id": { + "name": "setup_member_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_public_key": { + "name": "device_public_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "device_key_fingerprint": { + "name": "device_key_fingerprint", + "type": "varchar(128)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'provisional'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "workspace_bootstrap_organization_id": { + "name": "workspace_bootstrap_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "workspace_bootstrap_status": { + "name": "workspace_bootstrap_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "workspace_bootstrap_expires_at": { + "name": "workspace_bootstrap_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "workspace_bootstrap_id": { + "name": "workspace_bootstrap_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "workspace_claim": { + "name": "workspace_claim", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "bootstrap_id": { + "name": "bootstrap_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_hash": { + "name": "token_hash", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "claimed_by_user_id": { + "name": "claimed_by_user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "workspace_claim_token_hash": { + "name": "workspace_claim_token_hash", + "columns": [ + "token_hash" + ], + "isUnique": true + }, + "workspace_claim_bootstrap_id": { + "name": "workspace_claim_bootstrap_id", + "columns": [ + "bootstrap_id" + ], + "isUnique": false + }, + "workspace_claim_organization_id": { + "name": "workspace_claim_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "workspace_claim_status": { + "name": "workspace_claim_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "workspace_claim_expires_at": { + "name": "workspace_claim_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "workspace_claim_id": { + "name": "workspace_claim_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connected_account": { + "name": "connected_account", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_account_id": { + "name": "external_account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pending_code_verifier": { + "name": "pending_code_verifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connected_at": { + "name": "connected_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "connected_account_organization_id": { + "name": "connected_account_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connected_account_org_membership_id": { + "name": "connected_account_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "connected_account_member_provider": { + "name": "connected_account_member_provider", + "columns": [ + "org_membership_id", + "provider_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connected_account_id": { + "name": "connected_account_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "external_mcp_connection_access_grant": { + "name": "external_mcp_connection_access_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_mcp_connection_id": { + "name": "external_mcp_connection_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "org_wide": { + "name": "org_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "emc_access_grant_organization_id": { + "name": "emc_access_grant_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "emc_access_grant_connection_id": { + "name": "emc_access_grant_connection_id", + "columns": [ + "external_mcp_connection_id" + ], + "isUnique": false + }, + "emc_access_grant_org_membership_id": { + "name": "emc_access_grant_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "emc_access_grant_team_id": { + "name": "emc_access_grant_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "emc_access_grant_connection_member": { + "name": "emc_access_grant_connection_member", + "columns": [ + "external_mcp_connection_id", + "org_membership_id" + ], + "isUnique": true + }, + "emc_access_grant_connection_team": { + "name": "emc_access_grant_connection_team", + "columns": [ + "external_mcp_connection_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "external_mcp_connection_access_grant_id": { + "name": "external_mcp_connection_access_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "external_mcp_connection": { + "name": "external_mcp_connection", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "enum('oauth','apikey','none')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credential_mode": { + "name": "credential_mode", + "type": "enum('shared','per_member')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'shared'" + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "varchar(1024)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pending_code_verifier": { + "name": "pending_code_verifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connected_at": { + "name": "connected_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "external_mcp_connection_organization_id": { + "name": "external_mcp_connection_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "external_mcp_connection_id": { + "name": "external_mcp_connection_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "org_oauth_client": { + "name": "org_oauth_client", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "extra": { + "name": "extra", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "org_oauth_client_organization_id": { + "name": "org_oauth_client_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "org_oauth_client_org_provider": { + "name": "org_oauth_client_org_provider", + "columns": [ + "organization_id", + "provider_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "org_oauth_client_id": { + "name": "org_oauth_client_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "external_mcp_tool_manifest": { + "name": "external_mcp_tool_manifest", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_mcp_connection_id": { + "name": "external_mcp_connection_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "principal": { + "name": "principal", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_hash": { + "name": "config_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('ok','error')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tools": { + "name": "tools", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tool_count": { + "name": "tool_count", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "tools_hash": { + "name": "tools_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tools_truncated": { + "name": "tools_truncated", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "listed_at": { + "name": "listed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "stale_at": { + "name": "stale_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_started_at": { + "name": "refresh_started_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "emtm_connection_principal": { + "name": "emtm_connection_principal", + "columns": [ + "external_mcp_connection_id", + "principal" + ], + "isUnique": true + }, + "emtm_organization_id": { + "name": "emtm_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "emtm_listed_at": { + "name": "emtm_listed_at", + "columns": [ + "listed_at" + ], + "isUnique": false + }, + "emtm_refresh_started_at": { + "name": "emtm_refresh_started_at", + "columns": [ + "refresh_started_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "external_mcp_tool_manifest_id": { + "name": "external_mcp_tool_manifest_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "llm_provider_access": { + "name": "llm_provider_access", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "llm_provider_id": { + "name": "llm_provider_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "llm_provider_access_llm_provider_id": { + "name": "llm_provider_access_llm_provider_id", + "columns": [ + "llm_provider_id" + ], + "isUnique": false + }, + "llm_provider_access_org_membership_id": { + "name": "llm_provider_access_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "llm_provider_access_team_id": { + "name": "llm_provider_access_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "llm_provider_access_provider_org_membership": { + "name": "llm_provider_access_provider_org_membership", + "columns": [ + "llm_provider_id", + "org_membership_id" + ], + "isUnique": true + }, + "llm_provider_access_provider_team": { + "name": "llm_provider_access_provider_team", + "columns": [ + "llm_provider_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "llm_provider_access_id": { + "name": "llm_provider_access_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "llm_provider_model": { + "name": "llm_provider_model", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "llm_provider_id": { + "name": "llm_provider_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_id": { + "name": "model_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "model_config": { + "name": "model_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "llm_provider_model_llm_provider_id": { + "name": "llm_provider_model_llm_provider_id", + "columns": [ + "llm_provider_id" + ], + "isUnique": false + }, + "llm_provider_model_model_id": { + "name": "llm_provider_model_model_id", + "columns": [ + "model_id" + ], + "isUnique": false + }, + "llm_provider_model_provider_model": { + "name": "llm_provider_model_provider_model", + "columns": [ + "llm_provider_id", + "model_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "llm_provider_model_id": { + "name": "llm_provider_model_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "llm_provider": { + "name": "llm_provider", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "enum('models_dev','custom','openwork')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "api_key": { + "name": "api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "llm_provider_organization_id": { + "name": "llm_provider_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "llm_provider_created_by_org_membership_id": { + "name": "llm_provider_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "llm_provider_source": { + "name": "llm_provider_source", + "columns": [ + "source" + ], + "isUnique": false + }, + "llm_provider_provider_id": { + "name": "llm_provider_provider_id", + "columns": [ + "provider_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "llm_provider_id": { + "name": "llm_provider_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "config_object_access_grant": { + "name": "config_object_access_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_object_id": { + "name": "config_object_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "org_wide": { + "name": "org_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role": { + "name": "role", + "type": "enum('viewer','editor','manager')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "config_object_access_grant_organization_id": { + "name": "config_object_access_grant_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "config_object_access_grant_config_object_id": { + "name": "config_object_access_grant_config_object_id", + "columns": [ + "config_object_id" + ], + "isUnique": false + }, + "config_object_access_grant_org_membership_id": { + "name": "config_object_access_grant_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "config_object_access_grant_team_id": { + "name": "config_object_access_grant_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "config_object_access_grant_org_wide": { + "name": "config_object_access_grant_org_wide", + "columns": [ + "org_wide" + ], + "isUnique": false + }, + "config_object_access_grant_object_org_membership": { + "name": "config_object_access_grant_object_org_membership", + "columns": [ + "config_object_id", + "org_membership_id" + ], + "isUnique": true + }, + "config_object_access_grant_object_team": { + "name": "config_object_access_grant_object_team", + "columns": [ + "config_object_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "config_object_access_grant_id": { + "name": "config_object_access_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "config_object": { + "name": "config_object", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "object_type": { + "name": "object_type", + "type": "enum('skill','agent','command','tool','mcp','hook','context','custom')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_mode": { + "name": "source_mode", + "type": "enum('cloud','import','connector')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "search_text": { + "name": "search_text", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "current_file_name": { + "name": "current_file_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "current_file_extension": { + "name": "current_file_extension", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "current_relative_path": { + "name": "current_relative_path", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','inactive','deleted','archived','ingestion_error')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "config_object_organization_id": { + "name": "config_object_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "config_object_type": { + "name": "config_object_type", + "columns": [ + "object_type" + ], + "isUnique": false + }, + "config_object_source_mode": { + "name": "config_object_source_mode", + "columns": [ + "source_mode" + ], + "isUnique": false + }, + "config_object_status": { + "name": "config_object_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "config_object_created_by_org_membership_id": { + "name": "config_object_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "config_object_connector_instance_id": { + "name": "config_object_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "config_object_current_relative_path": { + "name": "config_object_current_relative_path", + "columns": [ + "current_relative_path" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "config_object_id": { + "name": "config_object_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "config_object_version": { + "name": "config_object_version", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_object_id": { + "name": "config_object_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "normalized_payload_json": { + "name": "normalized_payload_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "raw_source_text": { + "name": "raw_source_text", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "schema_version": { + "name": "schema_version", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_via": { + "name": "created_via", + "type": "enum('cloud','import','connector','system')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connector_sync_event_id": { + "name": "connector_sync_event_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_revision_ref": { + "name": "source_revision_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_deleted_version": { + "name": "is_deleted_version", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "config_object_version_organization_id": { + "name": "config_object_version_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "config_object_version_config_object_id": { + "name": "config_object_version_config_object_id", + "columns": [ + "config_object_id" + ], + "isUnique": false + }, + "config_object_version_created_by_org_membership_id": { + "name": "config_object_version_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "config_object_version_connector_sync_event_id": { + "name": "config_object_version_connector_sync_event_id", + "columns": [ + "connector_sync_event_id" + ], + "isUnique": false + }, + "config_object_version_source_revision_ref": { + "name": "config_object_version_source_revision_ref", + "columns": [ + "source_revision_ref" + ], + "isUnique": false + }, + "config_object_version_lookup_latest": { + "name": "config_object_version_lookup_latest", + "columns": [ + "config_object_id", + "created_at", + "id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "config_object_version_id": { + "name": "config_object_version_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_account": { + "name": "connector_account", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_account_ref": { + "name": "external_account_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','inactive','disconnected','error')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata_json": { + "name": "metadata_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "connector_account_organization_id": { + "name": "connector_account_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_account_created_by_org_membership_id": { + "name": "connector_account_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "connector_account_connector_type": { + "name": "connector_account_connector_type", + "columns": [ + "connector_type" + ], + "isUnique": false + }, + "connector_account_status": { + "name": "connector_account_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "connector_account_org_type_remote_id": { + "name": "connector_account_org_type_remote_id", + "columns": [ + "organization_id", + "connector_type", + "remote_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_account_id": { + "name": "connector_account_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_instance_access_grant": { + "name": "connector_instance_access_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "org_wide": { + "name": "org_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role": { + "name": "role", + "type": "enum('viewer','editor','manager')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "connector_instance_access_grant_organization_id": { + "name": "connector_instance_access_grant_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_instance_access_grant_instance_id": { + "name": "connector_instance_access_grant_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_instance_access_grant_org_membership_id": { + "name": "connector_instance_access_grant_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "connector_instance_access_grant_team_id": { + "name": "connector_instance_access_grant_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "connector_instance_access_grant_org_wide": { + "name": "connector_instance_access_grant_org_wide", + "columns": [ + "org_wide" + ], + "isUnique": false + }, + "connector_instance_access_grant_instance_org_membership": { + "name": "connector_instance_access_grant_instance_org_membership", + "columns": [ + "connector_instance_id", + "org_membership_id" + ], + "isUnique": true + }, + "connector_instance_access_grant_instance_team": { + "name": "connector_instance_access_grant_instance_team", + "columns": [ + "connector_instance_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_instance_access_grant_id": { + "name": "connector_instance_access_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_instance": { + "name": "connector_instance", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_account_id": { + "name": "connector_account_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','disabled','archived','error')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "instance_config_json": { + "name": "instance_config_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_sync_status": { + "name": "last_sync_status", + "type": "enum('pending','queued','running','completed','failed','partial','ignored')", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_sync_cursor": { + "name": "last_sync_cursor", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "connector_instance_organization_id": { + "name": "connector_instance_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_instance_connector_account_id": { + "name": "connector_instance_connector_account_id", + "columns": [ + "connector_account_id" + ], + "isUnique": false + }, + "connector_instance_created_by_org_membership_id": { + "name": "connector_instance_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "connector_instance_connector_type": { + "name": "connector_instance_connector_type", + "columns": [ + "connector_type" + ], + "isUnique": false + }, + "connector_instance_status": { + "name": "connector_instance_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "connector_instance_org_name": { + "name": "connector_instance_org_name", + "columns": [ + "organization_id", + "name" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_instance_id": { + "name": "connector_instance_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_mapping": { + "name": "connector_mapping", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_target_id": { + "name": "connector_target_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "mapping_kind": { + "name": "mapping_kind", + "type": "enum('path','api','custom')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "selector": { + "name": "selector", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "object_type": { + "name": "object_type", + "type": "enum('skill','agent','command','tool','mcp','hook','context','custom')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auto_add_to_plugin": { + "name": "auto_add_to_plugin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "mapping_config_json": { + "name": "mapping_config_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "connector_mapping_organization_id": { + "name": "connector_mapping_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_mapping_connector_instance_id": { + "name": "connector_mapping_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_mapping_connector_target_id": { + "name": "connector_mapping_connector_target_id", + "columns": [ + "connector_target_id" + ], + "isUnique": false + }, + "connector_mapping_object_type": { + "name": "connector_mapping_object_type", + "columns": [ + "object_type" + ], + "isUnique": false + }, + "connector_mapping_plugin_id": { + "name": "connector_mapping_plugin_id", + "columns": [ + "plugin_id" + ], + "isUnique": false + }, + "connector_mapping_target_selector_object_type": { + "name": "connector_mapping_target_selector_object_type", + "columns": [ + "connector_target_id", + "selector", + "object_type" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_mapping_id": { + "name": "connector_mapping_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_source_binding": { + "name": "connector_source_binding", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_object_id": { + "name": "config_object_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_target_id": { + "name": "connector_target_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_mapping_id": { + "name": "connector_mapping_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_locator": { + "name": "external_locator", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_stable_ref": { + "name": "external_stable_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_seen_source_revision_ref": { + "name": "last_seen_source_revision_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','inactive','deleted','archived','ingestion_error')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "connector_source_binding_organization_id": { + "name": "connector_source_binding_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_source_binding_config_object_id": { + "name": "connector_source_binding_config_object_id", + "columns": [ + "config_object_id" + ], + "isUnique": false + }, + "connector_source_binding_connector_instance_id": { + "name": "connector_source_binding_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_source_binding_connector_target_id": { + "name": "connector_source_binding_connector_target_id", + "columns": [ + "connector_target_id" + ], + "isUnique": false + }, + "connector_source_binding_connector_mapping_id": { + "name": "connector_source_binding_connector_mapping_id", + "columns": [ + "connector_mapping_id" + ], + "isUnique": false + }, + "connector_source_binding_external_locator": { + "name": "connector_source_binding_external_locator", + "columns": [ + "external_locator" + ], + "isUnique": false + }, + "connector_source_binding_config_object": { + "name": "connector_source_binding_config_object", + "columns": [ + "config_object_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_source_binding_id": { + "name": "connector_source_binding_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_source_tombstone": { + "name": "connector_source_tombstone", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_target_id": { + "name": "connector_target_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_mapping_id": { + "name": "connector_mapping_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_locator": { + "name": "external_locator", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "former_config_object_id": { + "name": "former_config_object_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "deleted_in_sync_event_id": { + "name": "deleted_in_sync_event_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "deleted_source_revision_ref": { + "name": "deleted_source_revision_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "connector_source_tombstone_organization_id": { + "name": "connector_source_tombstone_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_source_tombstone_connector_instance_id": { + "name": "connector_source_tombstone_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_source_tombstone_connector_target_id": { + "name": "connector_source_tombstone_connector_target_id", + "columns": [ + "connector_target_id" + ], + "isUnique": false + }, + "connector_source_tombstone_connector_mapping_id": { + "name": "connector_source_tombstone_connector_mapping_id", + "columns": [ + "connector_mapping_id" + ], + "isUnique": false + }, + "connector_source_tombstone_external_locator": { + "name": "connector_source_tombstone_external_locator", + "columns": [ + "external_locator" + ], + "isUnique": false + }, + "connector_source_tombstone_former_config_object_id": { + "name": "connector_source_tombstone_former_config_object_id", + "columns": [ + "former_config_object_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_source_tombstone_id": { + "name": "connector_source_tombstone_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_sync_event": { + "name": "connector_sync_event", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_target_id": { + "name": "connector_target_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "event_type": { + "name": "event_type", + "type": "enum('push','installation','installation_repositories','repository','manual_resync')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_event_ref": { + "name": "external_event_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_revision_ref": { + "name": "source_revision_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('pending','queued','running','completed','failed','partial','ignored')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "summary_json": { + "name": "summary_json", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "connector_sync_event_organization_id": { + "name": "connector_sync_event_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_sync_event_connector_instance_id": { + "name": "connector_sync_event_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_sync_event_connector_target_id": { + "name": "connector_sync_event_connector_target_id", + "columns": [ + "connector_target_id" + ], + "isUnique": false + }, + "connector_sync_event_event_type": { + "name": "connector_sync_event_event_type", + "columns": [ + "event_type" + ], + "isUnique": false + }, + "connector_sync_event_status": { + "name": "connector_sync_event_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "connector_sync_event_source_revision_ref": { + "name": "connector_sync_event_source_revision_ref", + "columns": [ + "source_revision_ref" + ], + "isUnique": false + }, + "connector_sync_event_external_event_ref": { + "name": "connector_sync_event_external_event_ref", + "columns": [ + "external_event_ref" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_sync_event_id": { + "name": "connector_sync_event_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "connector_target": { + "name": "connector_target", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_instance_id": { + "name": "connector_instance_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connector_type": { + "name": "connector_type", + "type": "enum('github')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "remote_id": { + "name": "remote_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_kind": { + "name": "target_kind", + "type": "enum('repository_branch')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "external_target_ref": { + "name": "external_target_ref", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "target_config_json": { + "name": "target_config_json", + "type": "json", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "connector_target_organization_id": { + "name": "connector_target_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "connector_target_connector_instance_id": { + "name": "connector_target_connector_instance_id", + "columns": [ + "connector_instance_id" + ], + "isUnique": false + }, + "connector_target_connector_type": { + "name": "connector_target_connector_type", + "columns": [ + "connector_type" + ], + "isUnique": false + }, + "connector_target_target_kind": { + "name": "connector_target_target_kind", + "columns": [ + "target_kind" + ], + "isUnique": false + }, + "connector_target_instance_remote_id": { + "name": "connector_target_instance_remote_id", + "columns": [ + "connector_instance_id", + "remote_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "connector_target_id": { + "name": "connector_target_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "marketplace_access_grant": { + "name": "marketplace_access_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "marketplace_id": { + "name": "marketplace_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "org_wide": { + "name": "org_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role": { + "name": "role", + "type": "enum('viewer','editor','manager')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "marketplace_access_grant_organization_id": { + "name": "marketplace_access_grant_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "marketplace_access_grant_marketplace_id": { + "name": "marketplace_access_grant_marketplace_id", + "columns": [ + "marketplace_id" + ], + "isUnique": false + }, + "marketplace_access_grant_org_membership_id": { + "name": "marketplace_access_grant_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "marketplace_access_grant_team_id": { + "name": "marketplace_access_grant_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "marketplace_access_grant_org_wide": { + "name": "marketplace_access_grant_org_wide", + "columns": [ + "org_wide" + ], + "isUnique": false + }, + "marketplace_access_grant_marketplace_org_membership": { + "name": "marketplace_access_grant_marketplace_org_membership", + "columns": [ + "marketplace_id", + "org_membership_id" + ], + "isUnique": true + }, + "marketplace_access_grant_marketplace_team": { + "name": "marketplace_access_grant_marketplace_team", + "columns": [ + "marketplace_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "marketplace_access_grant_id": { + "name": "marketplace_access_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "marketplace_plugin": { + "name": "marketplace_plugin", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "marketplace_id": { + "name": "marketplace_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "membership_source": { + "name": "membership_source", + "type": "enum('manual','connector','api','system')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'manual'" + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "marketplace_plugin_organization_id": { + "name": "marketplace_plugin_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "marketplace_plugin_marketplace_id": { + "name": "marketplace_plugin_marketplace_id", + "columns": [ + "marketplace_id" + ], + "isUnique": false + }, + "marketplace_plugin_plugin_id": { + "name": "marketplace_plugin_plugin_id", + "columns": [ + "plugin_id" + ], + "isUnique": false + }, + "marketplace_plugin_marketplace_plugin": { + "name": "marketplace_plugin_marketplace_plugin", + "columns": [ + "marketplace_id", + "plugin_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "marketplace_plugin_id": { + "name": "marketplace_plugin_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "marketplace": { + "name": "marketplace", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "logo_url": { + "name": "logo_url", + "type": "varchar(1024)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','inactive','deleted','archived')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "marketplace_organization_id": { + "name": "marketplace_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "marketplace_created_by_org_membership_id": { + "name": "marketplace_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "marketplace_status": { + "name": "marketplace_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "marketplace_name": { + "name": "marketplace_name", + "columns": [ + "name" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "marketplace_id": { + "name": "marketplace_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_access_grant": { + "name": "plugin_access_grant", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "org_wide": { + "name": "org_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role": { + "name": "role", + "type": "enum('viewer','editor','manager')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "plugin_access_grant_organization_id": { + "name": "plugin_access_grant_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "plugin_access_grant_plugin_id": { + "name": "plugin_access_grant_plugin_id", + "columns": [ + "plugin_id" + ], + "isUnique": false + }, + "plugin_access_grant_org_membership_id": { + "name": "plugin_access_grant_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "plugin_access_grant_team_id": { + "name": "plugin_access_grant_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "plugin_access_grant_org_wide": { + "name": "plugin_access_grant_org_wide", + "columns": [ + "org_wide" + ], + "isUnique": false + }, + "plugin_access_grant_plugin_org_membership": { + "name": "plugin_access_grant_plugin_org_membership", + "columns": [ + "plugin_id", + "org_membership_id" + ], + "isUnique": true + }, + "plugin_access_grant_plugin_team": { + "name": "plugin_access_grant_plugin_team", + "columns": [ + "plugin_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugin_access_grant_id": { + "name": "plugin_access_grant_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_config_object": { + "name": "plugin_config_object", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config_object_id": { + "name": "config_object_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "membership_source": { + "name": "membership_source", + "type": "enum('manual','connector','api','system')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'manual'" + }, + "connector_mapping_id": { + "name": "connector_mapping_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "removed_at": { + "name": "removed_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "plugin_config_object_organization_id": { + "name": "plugin_config_object_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "plugin_config_object_plugin_id": { + "name": "plugin_config_object_plugin_id", + "columns": [ + "plugin_id" + ], + "isUnique": false + }, + "plugin_config_object_config_object_id": { + "name": "plugin_config_object_config_object_id", + "columns": [ + "config_object_id" + ], + "isUnique": false + }, + "plugin_config_object_connector_mapping_id": { + "name": "plugin_config_object_connector_mapping_id", + "columns": [ + "connector_mapping_id" + ], + "isUnique": false + }, + "plugin_config_object_plugin_config_object": { + "name": "plugin_config_object_plugin_config_object", + "columns": [ + "plugin_id", + "config_object_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugin_config_object_id": { + "name": "plugin_config_object_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin": { + "name": "plugin", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('active','inactive','deleted','archived')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "plugin_organization_id": { + "name": "plugin_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "plugin_created_by_org_membership_id": { + "name": "plugin_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "plugin_status": { + "name": "plugin_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "plugin_name": { + "name": "plugin_name", + "columns": [ + "name" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugin_id": { + "name": "plugin_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "skill_hub_member": { + "name": "skill_hub_member", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "skill_hub_id": { + "name": "skill_hub_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "skill_hub_member_skill_hub_id": { + "name": "skill_hub_member_skill_hub_id", + "columns": [ + "skill_hub_id" + ], + "isUnique": false + }, + "skill_hub_member_org_membership_id": { + "name": "skill_hub_member_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "skill_hub_member_team_id": { + "name": "skill_hub_member_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "skill_hub_member_hub_org_membership": { + "name": "skill_hub_member_hub_org_membership", + "columns": [ + "skill_hub_id", + "org_membership_id" + ], + "isUnique": true + }, + "skill_hub_member_hub_team": { + "name": "skill_hub_member_hub_team", + "columns": [ + "skill_hub_id", + "team_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "skill_hub_member_id": { + "name": "skill_hub_member_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "skill_hub_skill": { + "name": "skill_hub_skill", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "skill_hub_id": { + "name": "skill_hub_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "skill_id": { + "name": "skill_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "skill_hub_skill_skill_hub_id": { + "name": "skill_hub_skill_skill_hub_id", + "columns": [ + "skill_hub_id" + ], + "isUnique": false + }, + "skill_hub_skill_skill_id": { + "name": "skill_hub_skill_skill_id", + "columns": [ + "skill_id" + ], + "isUnique": false + }, + "skill_hub_skill_hub_skill": { + "name": "skill_hub_skill_hub_skill", + "columns": [ + "skill_hub_id", + "skill_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "skill_hub_skill_id": { + "name": "skill_hub_skill_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "skill_hub": { + "name": "skill_hub", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "skill_hub_organization_id": { + "name": "skill_hub_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "skill_hub_created_by_org_membership_id": { + "name": "skill_hub_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "skill_hub_id": { + "name": "skill_hub_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "skill": { + "name": "skill", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "skill_text": { + "name": "skill_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "shared": { + "name": "shared", + "type": "enum('org','public')", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "skill_organization_id": { + "name": "skill_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "skill_created_by_org_membership_id": { + "name": "skill_created_by_org_membership_id", + "columns": [ + "created_by_org_membership_id" + ], + "isUnique": false + }, + "skill_shared": { + "name": "skill_shared", + "columns": [ + "shared" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "skill_id": { + "name": "skill_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "org_subscriptions": { + "name": "org_subscriptions", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_org_membership_id": { + "name": "created_by_org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "enum('inference','seat')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('incomplete','incomplete_expired','trialing','active','past_due','canceled','unpaid','paused','expired')", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'incomplete'" + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stripe_price_id": { + "name": "stripe_price_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "stripe_subscription_item_id": { + "name": "stripe_subscription_item_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "quantity": { + "name": "quantity", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "current_period_start": { + "name": "current_period_start", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "current_period_end": { + "name": "current_period_end", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_event_id": { + "name": "last_event_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "org_subscriptions_organization_id": { + "name": "org_subscriptions_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "org_subscriptions_customer_id": { + "name": "org_subscriptions_customer_id", + "columns": [ + "stripe_customer_id" + ], + "isUnique": false + }, + "org_subscriptions_subscription_id": { + "name": "org_subscriptions_subscription_id", + "columns": [ + "stripe_subscription_id" + ], + "isUnique": true + }, + "org_subscriptions_org_type": { + "name": "org_subscriptions_org_type", + "columns": [ + "organization_id", + "type" + ], + "isUnique": true + }, + "org_subscriptions_status": { + "name": "org_subscriptions_status", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "org_subscriptions_id": { + "name": "org_subscriptions_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "team_member": { + "name": "team_member", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "team_id": { + "name": "team_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_membership_id": { + "name": "org_membership_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "team_member_team_id": { + "name": "team_member_team_id", + "columns": [ + "team_id" + ], + "isUnique": false + }, + "team_member_org_membership_id": { + "name": "team_member_org_membership_id", + "columns": [ + "org_membership_id" + ], + "isUnique": false + }, + "team_member_team_org_membership": { + "name": "team_member_team_org_membership", + "columns": [ + "team_id", + "org_membership_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "team_member_id": { + "name": "team_member_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "team": { + "name": "team", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "team_organization_id": { + "name": "team_organization_id", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "team_organization_name": { + "name": "team_organization_name", + "columns": [ + "organization_id", + "name" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "team_id": { + "name": "team_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "audit_event": { + "name": "audit_event", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_id": { + "name": "org_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worker_id": { + "name": "worker_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "actor_user_id": { + "name": "actor_user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "audit_event_org_id": { + "name": "audit_event_org_id", + "columns": [ + "org_id" + ], + "isUnique": false + }, + "audit_event_worker_id": { + "name": "audit_event_worker_id", + "columns": [ + "worker_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "audit_event_id": { + "name": "audit_event_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "daytona_sandbox": { + "name": "daytona_sandbox", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worker_id": { + "name": "worker_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sandbox_id": { + "name": "sandbox_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_volume_id": { + "name": "workspace_volume_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data_volume_id": { + "name": "data_volume_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "signed_preview_url": { + "name": "signed_preview_url", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "signed_preview_url_expires_at": { + "name": "signed_preview_url_expires_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "region": { + "name": "region", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "daytona_sandbox_worker_id": { + "name": "daytona_sandbox_worker_id", + "columns": [ + "worker_id" + ], + "isUnique": true + }, + "daytona_sandbox_sandbox_id": { + "name": "daytona_sandbox_sandbox_id", + "columns": [ + "sandbox_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "daytona_sandbox_id": { + "name": "daytona_sandbox_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "worker_bundle": { + "name": "worker_bundle", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worker_id": { + "name": "worker_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "storage_url": { + "name": "storage_url", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "worker_bundle_worker_id": { + "name": "worker_bundle_worker_id", + "columns": [ + "worker_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "worker_bundle_id": { + "name": "worker_bundle_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "worker_instance": { + "name": "worker_instance", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worker_id": { + "name": "worker_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "region": { + "name": "region", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('provisioning','healthy','failed','stopped')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "worker_instance_worker_id": { + "name": "worker_instance_worker_id", + "columns": [ + "worker_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "worker_instance_id": { + "name": "worker_instance_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "worker": { + "name": "worker", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_id": { + "name": "org_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "varchar(1024)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "destination": { + "name": "destination", + "type": "enum('local','cloud')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "enum('provisioning','healthy','failed','stopped')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "image_version": { + "name": "image_version", + "type": "varchar(128)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "workspace_path": { + "name": "workspace_path", + "type": "varchar(1024)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sandbox_backend": { + "name": "sandbox_backend", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_heartbeat_at": { + "name": "last_heartbeat_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "worker_org_id": { + "name": "worker_org_id", + "columns": [ + "org_id" + ], + "isUnique": false + }, + "worker_created_by_user_id": { + "name": "worker_created_by_user_id", + "columns": [ + "created_by_user_id" + ], + "isUnique": false + }, + "worker_status": { + "name": "worker_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "worker_last_heartbeat_at": { + "name": "worker_last_heartbeat_at", + "columns": [ + "last_heartbeat_at" + ], + "isUnique": false + }, + "worker_last_active_at": { + "name": "worker_last_active_at", + "columns": [ + "last_active_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "worker_id": { + "name": "worker_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "worker_token": { + "name": "worker_token", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worker_id": { + "name": "worker_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "enum('client','host','activity')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "worker_token_worker_id": { + "name": "worker_token_worker_id", + "columns": [ + "worker_id" + ], + "isUnique": false + }, + "worker_token_token": { + "name": "worker_token_token", + "columns": [ + "token" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "worker_token_id": { + "name": "worker_token_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "admin_allowlist": { + "name": "admin_allowlist", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "note": { + "name": "note", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + } + }, + "indexes": { + "admin_allowlist_email": { + "name": "admin_allowlist_email", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "admin_allowlist_id": { + "name": "admin_allowlist_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "rate_limit": { + "name": "rate_limit", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "count": { + "name": "count", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_request": { + "name": "last_request", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "rate_limit_key": { + "name": "rate_limit_key", + "columns": [ + "key" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "rate_limit_id": { + "name": "rate_limit_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "telemetry_event": { + "name": "telemetry_event", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_id": { + "name": "org_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "member_id": { + "name": "member_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_type": { + "name": "event_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_timestamp": { + "name": "event_timestamp", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "telemetry_event_org_id_type_ts": { + "name": "telemetry_event_org_id_type_ts", + "columns": [ + "org_id", + "event_type", + "event_timestamp" + ], + "isUnique": false + }, + "telemetry_event_org_id_member_id": { + "name": "telemetry_event_org_id_member_id", + "columns": [ + "org_id", + "member_id" + ], + "isUnique": false + }, + "telemetry_event_org_session_ts": { + "name": "telemetry_event_org_session_ts", + "columns": [ + "org_id", + "session_id", + "event_timestamp" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "telemetry_event_id": { + "name": "telemetry_event_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "telemetry_session_dimension": { + "name": "telemetry_session_dimension", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "org_id": { + "name": "org_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dimension_type": { + "name": "dimension_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dimension_value": { + "name": "dimension_value", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dimension_label": { + "name": "dimension_label", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(now())" + } + }, + "indexes": { + "telemetry_session_dimension_org_source_session_type": { + "name": "telemetry_session_dimension_org_source_session_type", + "columns": [ + "org_id", + "source", + "session_id", + "dimension_type" + ], + "isUnique": true + }, + "telemetry_session_dimension_filter": { + "name": "telemetry_session_dimension_filter", + "columns": [ + "org_id", + "dimension_type", + "dimension_value", + "session_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "telemetry_session_dimension_id": { + "name": "telemetry_session_dimension_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + } + }, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "tables": {}, + "indexes": {} + } +} \ No newline at end of file diff --git a/ee/packages/den-db/drizzle/meta/_journal.json b/ee/packages/den-db/drizzle/meta/_journal.json index 980f97a6f2..61473b62db 100644 --- a/ee/packages/den-db/drizzle/meta/_journal.json +++ b/ee/packages/den-db/drizzle/meta/_journal.json @@ -218,6 +218,13 @@ "when": 1783392573893, "tag": "0031_telemetry_session_dimension", "breakpoints": true + }, + { + "idx": 32, + "version": "5", + "when": 1783487261976, + "tag": "0032_stale_lady_vermin", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/ee/packages/den-db/src/schema/index.ts b/ee/packages/den-db/src/schema/index.ts index 6c3a968261..5b619bd208 100644 --- a/ee/packages/den-db/src/schema/index.ts +++ b/ee/packages/den-db/src/schema/index.ts @@ -4,6 +4,7 @@ export * from "./inference" export * from "./memory" export * from "./org" export * from "./sharables/capability-credentials" +export * from "./sharables/external-mcp-manifests" export * from "./sharables/llm-providers" export * from "./sharables/plugin-arch" export * from "./sharables/skills" diff --git a/ee/packages/den-db/src/schema/sharables/external-mcp-manifests.ts b/ee/packages/den-db/src/schema/sharables/external-mcp-manifests.ts new file mode 100644 index 0000000000..e0f155c093 --- /dev/null +++ b/ee/packages/den-db/src/schema/sharables/external-mcp-manifests.ts @@ -0,0 +1,57 @@ +import { sql } from "drizzle-orm" +import { + boolean, + index, + int, + json, + mysqlEnum, + mysqlTable, + text, + timestamp, + uniqueIndex, + varchar, +} from "drizzle-orm/mysql-core" +import { denTypeIdColumn } from "../../columns" + +export type CachedExternalMcpTool = { + name: string + title?: string + description?: string +} + +export const externalMcpToolManifestStatusValues = ["ok", "error"] as const +export type ExternalMcpToolManifestStatus = (typeof externalMcpToolManifestStatusValues)[number] + +export const ExternalMcpToolManifestTable = mysqlTable( + "external_mcp_tool_manifest", + { + id: denTypeIdColumn("externalMcpToolManifest", "id").notNull().primaryKey(), + organizationId: denTypeIdColumn("organization", "organization_id").notNull(), + externalMcpConnectionId: denTypeIdColumn( + "externalMcpConnection", + "external_mcp_connection_id", + ).notNull(), + principal: varchar("principal", { length: 64 }).notNull(), + configHash: varchar("config_hash", { length: 64 }).notNull(), + status: mysqlEnum("status", externalMcpToolManifestStatusValues).notNull(), + tools: json("tools").$type().notNull(), + toolCount: int("tool_count").notNull().default(0), + toolsHash: varchar("tools_hash", { length: 64 }), + toolsTruncated: boolean("tools_truncated").notNull().default(false), + lastError: text("last_error"), + durationMs: int("duration_ms"), + listedAt: timestamp("listed_at", { fsp: 3 }), + staleAt: timestamp("stale_at", { fsp: 3 }), + refreshStartedAt: timestamp("refresh_started_at", { fsp: 3 }), + createdAt: timestamp("created_at", { fsp: 3 }).notNull().defaultNow(), + updatedAt: timestamp("updated_at", { fsp: 3 }) + .notNull() + .default(sql`CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)`), + }, + (table) => [ + uniqueIndex("emtm_connection_principal").on(table.externalMcpConnectionId, table.principal), + index("emtm_organization_id").on(table.organizationId), + index("emtm_listed_at").on(table.listedAt), + index("emtm_refresh_started_at").on(table.refreshStartedAt), + ], +) diff --git a/ee/packages/utils/src/typeid.ts b/ee/packages/utils/src/typeid.ts index 7c8ca278b8..d05b9aa7d1 100644 --- a/ee/packages/utils/src/typeid.ts +++ b/ee/packages/utils/src/typeid.ts @@ -84,6 +84,7 @@ export const idTypesMapNameToPrefix = { connectedAccount: "cta", externalMcpConnection: "emc", externalMcpConnectionAccessGrant: "emg", + externalMcpToolManifest: "emtm", memory: "mem", memctx: "mctx", } as const From ac90ada0d5abae3e004181fbc8831fbc784e701d Mon Sep 17 00:00:00 2001 From: Jalil Date: Wed, 8 Jul 2026 07:05:58 -0700 Subject: [PATCH 2/5] Protect MCP manifest config hashes --- .../external-mcp-manifests.ts | 20 ++-- .../test/external-mcp-manifests.test.ts | 101 ++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 ee/apps/den-api/test/external-mcp-manifests.test.ts diff --git a/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts index 400f01bf3b..8f404d249f 100644 --- a/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts +++ b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts @@ -207,21 +207,23 @@ export async function saveManifestFailure(input: SaveFailureInput): Promise { + const manifests = await import("../src/capability-sources/external-mcp-manifests.js") + classifyManifest = manifests.classifyManifest + computeManifestConfigHash = manifests.computeManifestConfigHash +}) + +function connection(url: string): ExternalMcpConnectionRow { + const now = new Date("2026-01-01T00:00:00.000Z") + return { + id: createDenTypeId("externalMcpConnection"), + organizationId: createDenTypeId("organization"), + name: "Test MCP", + url, + authType: "none", + credentialMode: "shared", + apiKey: null, + accessToken: null, + refreshToken: null, + tokenType: null, + scope: null, + expiresAt: null, + pendingCodeVerifier: null, + connectedAt: now, + createdByOrgMembershipId: createDenTypeId("member"), + createdAt: now, + updatedAt: now, + } +} + +function manifestRow(input: { + configHash: string + connection: ExternalMcpConnectionRow + listedAt: Date | null + toolCount: number + tools: ExternalMcpToolManifestRow["tools"] +}): ExternalMcpToolManifestRow { + const now = new Date("2026-01-01T00:00:00.000Z") + return { + id: createDenTypeId("externalMcpToolManifest"), + organizationId: input.connection.organizationId, + externalMcpConnectionId: input.connection.id, + principal: "shared", + configHash: input.configHash, + status: "error", + tools: input.tools, + toolCount: input.toolCount, + toolsHash: input.tools.length > 0 ? "old-tools-hash" : null, + toolsTruncated: false, + lastError: "refresh failed", + durationMs: 7, + listedAt: input.listedAt, + staleAt: now, + refreshStartedAt: null, + createdAt: now, + updatedAt: now, + } +} + +describe("external MCP tool manifests", () => { + test("old-config failure rows classify as misses under the current config", () => { + const oldConnection = connection("https://old.example.com/mcp") + const currentConnection = connection("https://new.example.com/mcp") + const failureRow = manifestRow({ + configHash: computeManifestConfigHash(oldConnection), + connection: currentConnection, + listedAt: null, + toolCount: 0, + tools: [], + }) + + expect(classifyManifest(failureRow, currentConnection).state).toBe("miss") + }) + + test("lease refresh rows do not make old-config tools usable", () => { + const oldConnection = connection("https://old.example.com/mcp") + const currentConnection = connection("https://new.example.com/mcp") + const staleRow = manifestRow({ + configHash: computeManifestConfigHash(oldConnection), + connection: currentConnection, + listedAt: new Date("2026-01-01T00:00:00.000Z"), + toolCount: 1, + tools: [{ name: "old-tool", description: "Tool from the previous server." }], + }) + + expect(classifyManifest(staleRow, currentConnection).state).toBe("miss") + }) +}) From 54d71de7944b2c05695979616df455038ff311a8 Mon Sep 17 00:00:00 2001 From: Jalil Date: Wed, 8 Jul 2026 07:06:48 -0700 Subject: [PATCH 3/5] Seed MCP manifests with anti-join --- .../den-api/src/mcp-manifest-maintenance.ts | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/ee/apps/den-api/src/mcp-manifest-maintenance.ts b/ee/apps/den-api/src/mcp-manifest-maintenance.ts index c3b449cbd6..8551fe779e 100644 --- a/ee/apps/den-api/src/mcp-manifest-maintenance.ts +++ b/ee/apps/den-api/src/mcp-manifest-maintenance.ts @@ -1,4 +1,4 @@ -import { and, eq, isNull, lt, lte, or, sql } from "@openwork-ee/den-db/drizzle" +import { and, eq, isNotNull, isNull, lt, lte, or, sql } from "@openwork-ee/den-db/drizzle" import { ConnectedAccountTable, ExternalMcpConnectionTable, @@ -10,8 +10,6 @@ import { env } from "./env.js" import { listTeamsForMember } from "./orgs.js" import { deleteManifests, - getManifests, - manifestMapKey, revalidateManifest, type ManifestPrincipal, } from "./capability-sources/external-mcp-manifests.js" @@ -98,16 +96,31 @@ async function refreshManifestRow(row: typeof ExternalMcpToolManifestTable.$infe } async function seedSharedConnectionRows(limit: number) { - const connections = await db - .select() + if (limit <= 0) return 0 + const rows = await db + .select({ connection: ExternalMcpConnectionTable }) .from(ExternalMcpConnectionTable) - .where(eq(ExternalMcpConnectionTable.credentialMode, "shared")) + .leftJoin( + ExternalMcpToolManifestTable, + and( + eq(ExternalMcpToolManifestTable.externalMcpConnectionId, ExternalMcpConnectionTable.id), + eq(ExternalMcpToolManifestTable.principal, "shared"), + ), + ) + .where(and( + eq(ExternalMcpConnectionTable.credentialMode, "shared"), + isNull(ExternalMcpToolManifestTable.id), + or( + eq(ExternalMcpConnectionTable.authType, "none"), + and(eq(ExternalMcpConnectionTable.authType, "oauth"), isNotNull(ExternalMcpConnectionTable.accessToken)), + and(eq(ExternalMcpConnectionTable.authType, "apikey"), isNotNull(ExternalMcpConnectionTable.apiKey)), + ), + )) + .orderBy(ExternalMcpConnectionTable.createdAt) .limit(limit) let seeded = 0 - for (const connection of connections) { + for (const { connection } of rows) { if (!isSharedRefreshable(connection)) continue - const manifests = await getManifests({ pairs: [{ connection, principal: "shared" }] }) - if (manifests.has(manifestMapKey(connection.id, "shared"))) continue const redirectUri = redirectUriForRefresh(connection.id) if (!redirectUri) continue await revalidateManifest({ connection, principal: "shared", redirectUri }) From 2cb1a398383b2e3da8116a08d4973420ba265c75 Mon Sep 17 00:00:00 2001 From: Jalil Date: Wed, 8 Jul 2026 07:08:14 -0700 Subject: [PATCH 4/5] Batch MCP connection manifest lookups --- .../den-api/src/routes/org/mcp-connections.ts | 75 +++++++++++++++---- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/ee/apps/den-api/src/routes/org/mcp-connections.ts b/ee/apps/den-api/src/routes/org/mcp-connections.ts index aea07eb285..131e458011 100644 --- a/ee/apps/den-api/src/routes/org/mcp-connections.ts +++ b/ee/apps/den-api/src/routes/org/mcp-connections.ts @@ -24,6 +24,7 @@ import { manifestPrincipalFor, revalidateManifest, deleteManifests, + type ExternalMcpToolManifestRow, type ManifestPrincipal, } from "../../capability-sources/external-mcp-manifests.js" import { @@ -42,7 +43,7 @@ import { import { memberFacingMcpConnectionsEnabled } from "../../capability-sources/external-mcp-rollout.js" import { listNativeProviderUsableEntries } from "../../capability-sources/native-provider-connections.js" import { connectCallbackPage } from "../../capability-sources/oauth-callback-page.js" -import { getConnectedAccount, upsertOrgOAuthClient } from "../../capability-sources/oauth-credentials.js" +import { getConnectedAccount, getConnectedAccounts, upsertOrgOAuthClient, type ConnectedAccountRow } from "../../capability-sources/oauth-credentials.js" import { assertPublicUrl } from "../../capability-sources/url-guard.js" import type { MemberTeamSummary } from "../../orgs.js" import { EXTERNAL_MCP_PRESETS } from "../../capability-sources/external-mcp-presets.js" @@ -200,28 +201,37 @@ function isConnectionConnected(row: ExternalMcpConnectionRow): boolean { return Boolean(row.accessToken || row.apiKey || (row.authType === "none" && row.connectedAt)) } +function responseManifestPrincipal(row: ExternalMcpConnectionRow, callerOrgMembershipId: DenTypeId<"member">): ManifestPrincipal { + return row.credentialMode === "per_member" ? callerOrgMembershipId : "shared" +} + async function toConnectionResponse( row: ExternalMcpConnectionRow, options: { callerOrgMembershipId: DenTypeId<"member"> + connectedAccount?: ConnectedAccountRow | null includeAccess: boolean + manifest?: ExternalMcpToolManifestRow | null }, ) { let connectedForMe = isConnectionConnected(row) && row.credentialMode === "shared" if (row.credentialMode === "per_member") { - const account = await getConnectedAccount({ - organizationId: row.organizationId, - orgMembershipId: options.callerOrgMembershipId, - providerId: row.id, - }) + const account = options.connectedAccount === undefined + ? await getConnectedAccount({ + organizationId: row.organizationId, + orgMembershipId: options.callerOrgMembershipId, + providerId: row.id, + }) + : options.connectedAccount connectedForMe = Boolean(account?.accessToken) } - const principal: ManifestPrincipal = row.credentialMode === "per_member" - ? options.callerOrgMembershipId - : "shared" - const manifests = await getManifests({ pairs: [{ connection: row, principal }] }) - const manifest = manifests.get(manifestMapKey(row.id, principal)) + let manifest = options.manifest + if (manifest === undefined) { + const principal = responseManifestPrincipal(row, options.callerOrgMembershipId) + const manifests = await getManifests({ pairs: [{ connection: row, principal }] }) + manifest = manifests.get(manifestMapKey(row.id, principal)) ?? null + } let access: { orgWide: boolean; memberIds: string[]; teamIds: string[] } | null = null if (options.includeAccess) { @@ -255,6 +265,33 @@ async function toConnectionResponse( } } +async function toConnectionResponses(input: { + callerOrgMembershipId: DenTypeId<"member"> + includeAccess: boolean + organizationId: DenTypeId<"organization"> + rows: ExternalMcpConnectionRow[] +}) { + const manifestPairs = input.rows.map((row) => ({ + connection: row, + principal: responseManifestPrincipal(row, input.callerOrgMembershipId), + })) + const manifests = await getManifests({ pairs: manifestPairs }) + const connectedAccounts = await getConnectedAccounts({ + organizationId: input.organizationId, + orgMembershipId: input.callerOrgMembershipId, + providerIds: input.rows.flatMap((row) => row.credentialMode === "per_member" ? [row.id] : []), + }) + return Promise.all(input.rows.map((row) => { + const principal = responseManifestPrincipal(row, input.callerOrgMembershipId) + return toConnectionResponse(row, { + callerOrgMembershipId: input.callerOrgMembershipId, + connectedAccount: row.credentialMode === "per_member" ? connectedAccounts.get(row.id) ?? null : null, + includeAccess: input.includeAccess, + manifest: manifests.get(manifestMapKey(row.id, principal)) ?? null, + }) + })) +} + function callbackRedirectUri(request: Request, connectionId: string) { const origin = resolvePublicOrigin(request, env.apiPublicUrl) return `${origin}/v1/mcp-connections/${encodeURIComponent(connectionId)}/connect/callback` @@ -317,8 +354,12 @@ export function registerMcpConnectionRoutes - toConnectionResponse(row, { callerOrgMembershipId: payload.currentMember.id, includeAccess: true }))) + const connections = await toConnectionResponses({ + callerOrgMembershipId: payload.currentMember.id, + includeAccess: true, + organizationId: payload.organization.id, + rows, + }) return c.json({ connections }) } @@ -335,8 +376,12 @@ export function registerMcpConnectionRoutes team.id), }) - const connections = await Promise.all(rows.map((row) => - toConnectionResponse(row, { callerOrgMembershipId: payload.currentMember.id, includeAccess: false }))) + const connections = await toConnectionResponses({ + callerOrgMembershipId: payload.currentMember.id, + includeAccess: false, + organizationId: payload.organization.id, + rows, + }) // Native providers (e.g. google-workspace) join the same list once the // org saved an OAuth client for them — same card, same connect flow, // same rollout gate (this sits after the gate check on purpose). From c880864d0f2576c9b9e67301420438db8d193f3a Mon Sep 17 00:00:00 2001 From: Jalil Date: Wed, 8 Jul 2026 07:12:25 -0700 Subject: [PATCH 5/5] Bound MCP manifest revalidation --- .../external-mcp-manifests.ts | 95 ++++++++++++++++--- ee/apps/den-api/src/env.ts | 2 + .../den-api/src/mcp-manifest-maintenance.ts | 11 +-- .../den-api/src/routes/org/mcp-connections.ts | 13 ++- .../test/external-mcp-manifests.test.ts | 55 +++++++++++ 5 files changed, 157 insertions(+), 19 deletions(-) diff --git a/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts index 8f404d249f..7aba5f1f6e 100644 --- a/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts +++ b/ee/apps/den-api/src/capability-sources/external-mcp-manifests.ts @@ -24,6 +24,8 @@ export type ManifestClassification = | { state: "stale"; row: ExternalMcpToolManifestRow } | { state: "miss"; row: ExternalMcpToolManifestRow | null } +export type ManifestRevalidationResult = "failed" | "lease_held" | "refreshed" + type SaveListingInput = { connection: ExternalMcpConnectionRow principal: ManifestPrincipal @@ -46,6 +48,56 @@ type RevalidationInput = { } const inFlightRevalidations = new Map>() +const MAX_REVALIDATION_BACKLOG = 20 + +type QueuedManifestRevalidation = { + reject: (error: unknown) => void + resolve: () => void + run: () => Promise +} + +export function createBoundedManifestRevalidationQueue(input: { + concurrency: number + maxBacklog: number +}) { + const concurrency = Math.max(1, Math.floor(input.concurrency)) + const maxBacklog = Math.max(0, Math.floor(input.maxBacklog)) + const queue: QueuedManifestRevalidation[] = [] + let active = 0 + + const drain = () => { + while (active < concurrency) { + const item = queue.shift() + if (!item) return + active += 1 + void item.run() + .then(item.resolve, item.reject) + .finally(() => { + active -= 1 + drain() + }) + } + } + + return { + enqueue(run: () => Promise): Promise | null { + if (queue.length >= maxBacklog && active >= concurrency) return null + const task = new Promise((resolve, reject) => { + queue.push({ reject, resolve, run }) + }) + drain() + return task + }, + stats() { + return { active, queued: queue.length } + }, + } +} + +const manifestRevalidationQueue = createBoundedManifestRevalidationQueue({ + concurrency: env.mcpManifestRevalidateConcurrency, + maxBacklog: MAX_REVALIDATION_BACKLOG, +}) export function manifestPrincipalFor( connection: ExternalMcpConnectionRow, @@ -340,20 +392,30 @@ export async function createRefreshLeaseForPair(input: { export function scheduleManifestRevalidation(input: RevalidationInput): void { const key = rowKey(input.connection.id, input.principal) if (inFlightRevalidations.has(key)) return - const task = revalidateManifest(input) - .catch((error) => { - console.warn(`[mcp-manifest][revalidate_failed] connectionId=${input.connection.id} principal=${input.principal} reason=${shortErrorMessage(error)}`) - }) - .finally(() => { - inFlightRevalidations.delete(key) - }) + const task = manifestRevalidationQueue.enqueue(async () => { + const result = await revalidateManifest(input) + if (result === "failed") { + console.warn(`[mcp-manifest][revalidate_failed] connectionId=${input.connection.id} principal=${input.principal}`) + } + }) + if (!task) { + console.warn(`[mcp-manifest][revalidate_dropped] connectionId=${input.connection.id} principal=${input.principal} reason=queue_full`) + return + } + task.catch((error) => { + console.warn(`[mcp-manifest][revalidate_failed] connectionId=${input.connection.id} principal=${input.principal} reason=${shortErrorMessage(error)}`) + }).finally(() => { + inFlightRevalidations.delete(key) + }) inFlightRevalidations.set(key, task) } -export async function revalidateManifest(input: RevalidationInput): Promise { - const row = await createRefreshLeaseForPair({ connection: input.connection, principal: input.principal }) - const claimed = await claimManifestRefresh({ rowId: row.id }) - if (!claimed) return +export async function revalidateManifestWithClaim(input: RevalidationInput & { + claimRefresh: (rowId: DenTypeId<"externalMcpToolManifest">) => Promise + row: ExternalMcpToolManifestRow +}): Promise { + const claimed = await input.claimRefresh(input.row.id) + if (!claimed) return "lease_held" const startedAt = Date.now() try { const tools = await listExternalMcpToolsWithOptions(input.connection, input.redirectUri, input.member, { @@ -365,6 +427,7 @@ export async function revalidateManifest(input: RevalidationInput): Promise { + const row = await createRefreshLeaseForPair({ connection: input.connection, principal: input.principal }) + return revalidateManifestWithClaim({ + ...input, + row, + claimRefresh: (rowId) => claimManifestRefresh({ rowId }), + }) +} + function rowsAffected(result: unknown): number { if (Array.isArray(result)) { const first = result[0] diff --git a/ee/apps/den-api/src/env.ts b/ee/apps/den-api/src/env.ts index d5936d8817..d378a6825a 100644 --- a/ee/apps/den-api/src/env.ts +++ b/ee/apps/den-api/src/env.ts @@ -95,6 +95,7 @@ const EnvSchema = z.object({ DEN_MCP_MANIFEST_REFRESH_INTERVAL_MS: z.string().optional(), DEN_MCP_MANIFEST_REFRESH_BATCH_SIZE: z.string().optional(), DEN_MCP_MANIFEST_REFRESH_LEASE_MS: z.string().optional(), + DEN_MCP_MANIFEST_REVALIDATE_CONCURRENCY: z.string().optional(), SCIM_MAINTENANCE_INTERVAL_MS: z.string().optional(), POLAR_FEATURE_GATE_ENABLED: z.string().optional(), POLAR_API_BASE: z.string().optional(), @@ -303,6 +304,7 @@ export const env = { mcpManifestRefreshIntervalMs: Number(parsed.DEN_MCP_MANIFEST_REFRESH_INTERVAL_MS ?? "300000"), mcpManifestRefreshBatchSize: Number(parsed.DEN_MCP_MANIFEST_REFRESH_BATCH_SIZE ?? "20"), mcpManifestRefreshLeaseMs: Number(parsed.DEN_MCP_MANIFEST_REFRESH_LEASE_MS ?? "60000"), + mcpManifestRevalidateConcurrency: Number(parsed.DEN_MCP_MANIFEST_REVALIDATE_CONCURRENCY ?? "3"), scimMaintenanceIntervalMs: Number(parsed.SCIM_MAINTENANCE_INTERVAL_MS ?? "300000"), requireEmailVerification, passwordBreachScreeningEnabled, diff --git a/ee/apps/den-api/src/mcp-manifest-maintenance.ts b/ee/apps/den-api/src/mcp-manifest-maintenance.ts index 8551fe779e..803db1da1b 100644 --- a/ee/apps/den-api/src/mcp-manifest-maintenance.ts +++ b/ee/apps/den-api/src/mcp-manifest-maintenance.ts @@ -53,8 +53,7 @@ async function refreshManifestRow(row: typeof ExternalMcpToolManifestTable.$infe await deleteManifests({ connectionId: connection.id, principal: "shared" }) return "deleted" as const } - await revalidateManifest({ connection, principal: "shared", redirectUri }) - return "refreshed" as const + return revalidateManifest({ connection, principal: "shared", redirectUri }) } if (!isDenTypeId("member", row.principal)) { @@ -86,13 +85,12 @@ async function refreshManifestRow(row: typeof ExternalMcpToolManifestTable.$infe await deleteManifests({ connectionId: connection.id, principal: orgMembershipId }) return "deleted" as const } - await revalidateManifest({ + return revalidateManifest({ connection, principal: orgMembershipId, redirectUri, member: { orgMembershipId }, }) - return "refreshed" as const } async function seedSharedConnectionRows(limit: number) { @@ -123,8 +121,8 @@ async function seedSharedConnectionRows(limit: number) { if (!isSharedRefreshable(connection)) continue const redirectUri = redirectUriForRefresh(connection.id) if (!redirectUri) continue - await revalidateManifest({ connection, principal: "shared", redirectUri }) - seeded += 1 + const result = await revalidateManifest({ connection, principal: "shared", redirectUri }) + if (result === "refreshed") seeded += 1 } return seeded } @@ -162,6 +160,7 @@ export async function runMcpManifestMaintenanceOnce() { try { const result = await refreshManifestRow(row) if (result === "refreshed") refreshed += 1 + if (result === "failed") failures += 1 if (result === "deleted") deleted += 1 } catch (error) { failures += 1 diff --git a/ee/apps/den-api/src/routes/org/mcp-connections.ts b/ee/apps/den-api/src/routes/org/mcp-connections.ts index 131e458011..fce30b7b33 100644 --- a/ee/apps/den-api/src/routes/org/mcp-connections.ts +++ b/ee/apps/den-api/src/routes/org/mcp-connections.ts @@ -175,7 +175,7 @@ const connectionValidationFailedSchema = z.object({ }).meta({ ref: "ExternalMcpConnectionValidationFailedError" }) const refreshToolsResponseSchema = z.object({ - status: z.enum(["ok", "error"]), + status: z.enum(["ok", "error", "in_progress"]), toolCount: z.number(), listedAt: z.string().nullable(), message: z.string().optional(), @@ -607,6 +607,7 @@ export function registerMcpConnectionRoutes { const manifests = await import("../src/capability-sources/external-mcp-manifests.js") classifyManifest = manifests.classifyManifest computeManifestConfigHash = manifests.computeManifestConfigHash + createBoundedManifestRevalidationQueue = manifests.createBoundedManifestRevalidationQueue + revalidateManifestWithClaim = manifests.revalidateManifestWithClaim }) function connection(url: string): ExternalMcpConnectionRow { @@ -98,4 +102,55 @@ describe("external MCP tool manifests", () => { expect(classifyManifest(staleRow, currentConnection).state).toBe("miss") }) + + test("bounded revalidation queue caps in-flight work and drops overflow", async () => { + const queue = createBoundedManifestRevalidationQueue({ concurrency: 2, maxBacklog: 2 }) + let inFlight = 0 + let maxInFlight = 0 + let releaseBlocker = () => undefined + const blocker = new Promise((resolve) => { + releaseBlocker = resolve + }) + + const tasks = [0, 1, 2, 3, 4].map((value) => + queue.enqueue(async () => { + inFlight += 1 + maxInFlight = Math.max(maxInFlight, inFlight) + await blocker + inFlight -= 1 + expect(value).toBeGreaterThanOrEqual(0) + })) + const acceptedTasks = tasks.flatMap((task) => task ? [task] : []) + + expect(acceptedTasks.length).toBe(4) + expect(tasks.filter((task) => task === null).length).toBe(1) + await new Promise((resolve) => setTimeout(resolve, 10)) + expect(maxInFlight).toBeLessThanOrEqual(2) + expect(queue.stats()).toEqual({ active: 2, queued: 2 }) + + releaseBlocker() + await Promise.all(acceptedTasks) + expect(queue.stats()).toEqual({ active: 0, queued: 0 }) + }) + + test("revalidation reports lease_held when another worker owns the lease", async () => { + const currentConnection = connection("https://current.example.com/mcp") + const row = manifestRow({ + configHash: computeManifestConfigHash(currentConnection), + connection: currentConnection, + listedAt: null, + toolCount: 0, + tools: [], + }) + + const result = await revalidateManifestWithClaim({ + connection: currentConnection, + principal: "shared", + redirectUri: "https://den.example.com/v1/mcp-connections/callback", + row, + claimRefresh: async () => false, + }) + + expect(result).toBe("lease_held") + }) })