From 941a5e160c019ef8d3bc6e4a393bfa7b2f93ed90 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 12:49:53 -0800 Subject: [PATCH 1/8] feat(api-keys): read-only API keys and expiry chosen at creation Personal and workspace API keys gain an access level (full access or read only) and an expiry picked when the key is created (30 days, 90 days, 1 year, or never; bounded server-side to one day through one year). A read-only key is granted the api:read scope: the operation funnel refuses it any operation api:read does not cover, including operations that declare no scope, with a 403 READ_ONLY_API_KEY refusal rather than an OAuth insufficient_scope challenge. Surfaces that authorize outside the funnel refuse it too: v1 refuses every non-GET except knowledge search, the legacy execute route refuses it, and a workflow MCP server refuses tools/call. An expired key now answers 401 "API key has expired" on v2, v1, and hybrid auth. /api/v2/meta reports the credential's scopes. Migration 0455 adds api_key.access (enum api_key_access, NOT NULL DEFAULT 'write'), so existing keys and the deployed app keep full access. Write keys serialize without the field and older serialized principals parse as write, so queued runs survive a mixed-version deploy. --- .../docs/api-reference/authentication.mdx | 15 +- apps/docs/content/docs/cli/authentication.mdx | 2 +- apps/docs/content/docs/mcp/authentication.mdx | 4 +- apps/docs/openapi-v2-billing.json | 1 + apps/docs/openapi-v2-files-audit.json | 1 + apps/docs/openapi-v2-knowledge.json | 1 + apps/docs/openapi-v2-logs.json | 1 + apps/docs/openapi-v2-resources.json | 21 +- apps/docs/openapi-v2-tables.json | 1 + apps/docs/openapi-v2-workflows.json | 1 + .../api/mcp/serve/[serverId]/route.test.ts | 1 + .../sim/app/api/mcp/serve/[serverId]/route.ts | 21 +- .../[executionId]/[contextId]/route.test.ts | 2 + apps/sim/app/api/users/me/api-keys/route.ts | 14 +- apps/sim/app/api/v1/auth.test.ts | 5 +- apps/sim/app/api/v1/auth.ts | 5 +- apps/sim/app/api/v1/middleware.ts | 40 +- apps/sim/app/api/v2/access-requests.test.ts | 7 +- apps/sim/app/api/v2/audit-logs/route.test.ts | 7 +- .../sim/app/api/v2/billing/logs/route.test.ts | 7 +- .../app/api/v2/billing/status/route.test.ts | 7 +- apps/sim/app/api/v2/blocks/route.test.ts | 7 +- .../app/api/v2/connector-types/route.test.ts | 7 +- .../credentials/[credentialId]/route.test.ts | 7 +- apps/sim/app/api/v2/credentials/route.test.ts | 7 +- .../v2/files/[fileId]/content/route.test.ts | 1 + .../v2/files/[fileId]/metadata/route.test.ts | 7 +- .../app/api/v2/files/[fileId]/route.test.ts | 1 + .../api/v2/files/[fileId]/text/route.test.ts | 7 +- .../api/v2/files/[fileId]/unzip/route.test.ts | 7 +- .../versions/[version]/revert/route.test.ts | 1 + apps/sim/app/api/v2/files/route.test.ts | 1 + .../v2/files/uploads/[uploadId]/route.test.ts | 1 + .../app/api/v2/files/uploads/route.test.ts | 1 + .../[documentId]/chunks/route.test.ts | 7 +- .../from-workspace-files/route.test.ts | 2 +- .../[knowledgeBaseId]/export/route.test.ts | 7 +- .../[knowledgeBaseId]/restore/route.test.ts | 2 +- .../tags/[tagId]/route.test.ts | 2 +- .../[knowledgeBaseId]/tags/route.test.ts | 2 +- .../app/api/v2/knowledge/search/route.test.ts | 7 +- .../sim/app/api/v2/logs/[runId]/route.test.ts | 1 + apps/sim/app/api/v2/logs/route.test.ts | 1 + apps/sim/app/api/v2/logs/stats/route.test.ts | 7 +- apps/sim/app/api/v2/meta/route.ts | 4 +- .../[tableId]/cancel-runs/route.test.ts | 1 + .../v2/tables/[tableId]/columns/route.test.ts | 1 + .../dispatches/[dispatchId]/route.test.ts | 1 + .../tables/[tableId]/dispatches/route.test.ts | 1 + .../v2/tables/[tableId]/groups/route.test.ts | 1 + .../[tableId]/query/count/route.test.ts | 1 + .../v2/tables/[tableId]/query/route.test.ts | 1 + .../v2/tables/[tableId]/restore/route.test.ts | 1 + .../enrichment/[groupId]/route.test.ts | 1 + .../[tableId]/rows/[rowId]/route.test.ts | 1 + .../[tableId]/rows/bulk-update/route.test.ts | 1 + .../v2/tables/[tableId]/rows/route.test.ts | 1 + .../[tableId]/rows/search/route.test.ts | 1 + .../[tableId]/rows/upsert/route.test.ts | 1 + .../[tableId]/views/[viewId]/route.test.ts | 1 + .../v2/tables/folders/restore/route.test.ts | 1 + apps/sim/app/api/v2/tables/move/route.test.ts | 1 + apps/sim/app/api/v2/tables/route.test.ts | 1 + .../v2/tools/[toolId]/execute/route.test.ts | 7 +- apps/sim/app/api/v2/tools/route.test.ts | 7 +- .../[workflowId]/duplicate/route.test.ts | 7 +- .../[workflowId]/operations/route.test.ts | 7 +- .../[workflowId]/restore/route.test.ts | 7 +- .../v2/workflows/[workflowId]/route.test.ts | 1 + .../runs/[runId]/cancel/route.test.ts | 1 + .../runs/[runId]/files/[fileId]/route.test.ts | 1 + .../[workflowId]/runs/[runId]/route.test.ts | 1 + .../workflows/[workflowId]/runs/route.test.ts | 1 + .../[workflowId]/state/route.test.ts | 7 +- .../[workflowId]/versions/route.test.ts | 1 + .../app/api/v2/workflows/move/route.test.ts | 7 +- apps/sim/app/api/v2/workflows/route.test.ts | 1 + .../[workspaceId]/invitations/route.test.ts | 7 +- .../permission-config/route.test.ts | 7 +- .../v2/workspaces/[workspaceId]/route.test.ts | 1 + apps/sim/app/api/v2/workspaces/route.test.ts | 1 + .../api/workflows/[id]/execute/route.test.ts | 3 + .../app/api/workflows/[id]/execute/route.ts | 16 +- .../workspaces/[id]/api-keys/route.test.ts | 2 + .../app/api/workspaces/[id]/api-keys/route.ts | 17 +- .../settings/components/api-keys/api-keys.tsx | 41 +- .../create-api-key-modal.tsx | 59 +- .../workflow-mcp-servers.tsx | 1 + .../components/deploy-modal/deploy-modal.tsx | 1 + .../lib/application/flow.integration.ts | 7 +- .../agent/memory-harness.integration.ts | 1 + apps/sim/hooks/queries/api-keys.ts | 13 +- .../read-only-access.integration.ts | 390 + .../api-key/application/personal-api-keys.ts | 8 +- .../api-key/application/workspace-api-keys.ts | 2 + apps/sim/lib/api-key/auth.ts | 15 +- apps/sim/lib/api-key/orchestration/index.ts | 66 +- apps/sim/lib/api-key/policy-messages.ts | 11 +- apps/sim/lib/api-key/service.ts | 14 +- .../application/read-v2-api-capabilities.ts | 9 +- apps/sim/lib/api/contracts/api-keys.ts | 19 +- apps/sim/lib/api/contracts/v2/meta.ts | 5 + .../lib/api/contracts/v2/openapi/resources.ts | 15 +- .../lib/api/mcp/generated/v2-operations.ts | 2 +- apps/sim/lib/api/mcp/route-handler.test.ts | 14 +- .../api/server/routes/v2-api-key-auth.test.ts | 9 +- .../lib/api/server/routes/v2-api-key-auth.ts | 19 +- .../api/server/routes/v2-binary-route.test.ts | 1 + .../routes/v2-body-lifecycle-route.test.ts | 2 +- .../api/server/routes/v2-json-route.test.ts | 1 + .../lib/api/server/routes/v2-json-route.ts | 7 +- apps/sim/lib/auth/hybrid.test.ts | 4 +- apps/sim/lib/auth/hybrid.ts | 13 +- apps/sim/lib/auth/internal.test.ts | 3 + apps/sim/lib/auth/principal.test.ts | 52 +- .../sso/application/admit-sso-user.test.ts | 1 + .../provider-settings.integration.ts | 14 +- .../application/authorize.test.ts | 2 +- .../lib/core/application/audit-source.test.ts | 7 +- .../application/environment-reference.test.ts | 2 +- apps/sim/lib/core/application/forbidden.ts | 2 + apps/sim/lib/core/application/index.ts | 2 + .../application/oauth-authorization.test.ts | 41 +- .../core/application/oauth-authorization.ts | 57 +- .../lib/core/application/operation.test.ts | 7 +- .../organization-authorization.test.ts | 4 +- .../workspace-authorization.test.ts | 1 + .../application/list-credentials.test.ts | 1 + .../application/manage-groups.test.ts | 28 +- .../application/connection-target.test.ts | 1 + .../application/sharing.integration.ts | 9 +- .../application/use-cases.test.ts | 8 +- .../data-drains/application/use-cases.test.ts | 4 +- .../lib/desktop/source-request.integration.ts | 7 +- apps/sim/lib/execution/files.test.ts | 4 +- .../lib/internal/file/execute-tool.test.ts | 15 +- .../lib/internal/principals/executor.test.ts | 1 + .../application/send-invitation-batch.test.ts | 7 +- .../application-acl.integration.ts | 8 +- .../__integration__/coda-live.integration.ts | 1 + .../confluence-live.integration.ts | 1 + .../filtered-search.integration.ts | 8 +- .../gitlab-federated.integration.ts | 1 + .../gitlab-live.integration.ts | 2 + .../google-drive-live.integration.ts | 2 + .../google-drive-member-live.integration.ts | 1 + .../kb-block-search.integration.ts | 1 + .../keyword-ranking.integration.ts | 1 + .../providers-live.integration.ts | 8 +- .../search-index-policy.integration.ts | 10 +- .../search-latency.integration.ts | 1 + .../__integration__/slack-live.integration.ts | 1 + ...orkspace-kb-document-access.integration.ts | 1 + .../csv-workflow-execution.live.test.ts | 7 +- .../agent-cli/file-upload-transport.test.ts | 7 +- .../agent-cli/saved-run-read.live.test.ts | 21 +- apps/sim/lib/posthog/events.ts | 2 + .../selectors/server/providers/mcp.test.ts | 2 +- .../lib/table/application/analytics.test.ts | 9 +- .../table/application/authorization.test.ts | 1 + .../application/read-current-user.test.ts | 1 + .../lib/workflows/api/route-policies.test.ts | 2 + apps/sim/lib/workflows/api/route-policies.ts | 21 +- .../application/mcp-output-schemas.test.ts | 7 +- .../executor/start-run-identity.test.ts | 2 + .../references/import-configuration.test.ts | 7 +- .../references/selector-values.test.ts | 7 +- .../file-path-references.integration.ts | 2 +- .../application/authorization.test.ts | 1 + .../__integration__/fork-sync.integration.ts | 7 +- .../mapped-import.integration.ts | 7 +- .../__integration__/pagination.integration.ts | 7 +- .../record-workspace-visit.test.ts | 2 +- packages/auth/src/principal.ts | 52 +- .../db/migrations/0455_api_key_access.sql | 2 + .../db/migrations/meta/0455_snapshot.json | 34550 ++++++++++++++++ packages/db/migrations/meta/_journal.json | 9 +- packages/db/schema.ts | 4 + packages/sim-cli/src/generated/v2-api.ts | 1 + .../src/factories/principal.factory.ts | 20 +- .../src/mocks/schema-tables.generated.ts | 2 + packages/testing/src/mocks/v1-route.mock.ts | 4 +- scripts/check-unused-exports.baseline.json | 1 - 183 files changed, 36047 insertions(+), 185 deletions(-) create mode 100644 apps/sim/lib/api-key/__integration__/read-only-access.integration.ts create mode 100644 packages/db/migrations/0455_api_key_access.sql create mode 100644 packages/db/migrations/meta/0455_snapshot.json diff --git a/apps/docs/content/docs/api-reference/authentication.mdx b/apps/docs/content/docs/api-reference/authentication.mdx index 6b3da616caf..6e8dc91c782 100644 --- a/apps/docs/content/docs/api-reference/authentication.mdx +++ b/apps/docs/content/docs/api-reference/authentication.mdx @@ -24,7 +24,7 @@ Workspace Admins can turn off **Allow personal API keys**. The workspace policy ## Create and store a key [#generating-api-keys] 1. Open **Account settings → Sim API keys** to create a personal key, or **Workspace settings → Sim API keys** to create a workspace key. -2. Select **Create API key**, enter a name, and create it. Workspace-key creation requires workspace **Admin** access and the applicable key-management permission. +2. Select **Create API key** and enter a name. Choose its **Access** and when it **Expires**, then create it. Workspace-key creation requires workspace **Admin** access and the applicable key-management permission. 3. Copy the key and store it in a server-side environment variable such as `SIM_API_KEY`. @@ -33,6 +33,19 @@ Sim shows the complete key once, immediately after creation. Copy it before clos Delete a key from the same settings page to revoke it. Update applications that used it with a replacement key. +### Access [#key-access] + +| Access | Allows | +| --- | --- | +| **Full access** | Everything the key's identity can do: reads, changes, deploys, and workflow runs | +| **Read only** | The operations the [`api:read` scope](#oauth-access-tokens) allows, including searches sent as POST requests | + +A read-only key cannot run, resume, or cancel workflows, or create, change, or delete anything. Those requests fail with `403` and `error.details.code` `READ_ONLY_API_KEY`. Access narrows a key; it never grants more than the key's identity already has. Access is fixed at creation, so create a new key to change it. Keys created before access levels existed have full access. Keys created from the deploy modal or for a workflow MCP server always have full access, because they exist to run workflows. + +### Expiration [#key-expiration] + +A key expires 30 days, 90 days, or 1 year after creation, or never. The settings page defaults to 90 days. After it expires, every request with the key fails with `401` and the message `API key has expired`; create a replacement before then. The key list shows each key's expiration date. `GET /api/v2/meta` reports the calling key's `expiresAt` and `scopes`. + ## Send an API key [#using-api-keys] Send the key in `X-API-Key`. The v2 API accepts `Authorization: Bearer` only for [OAuth access tokens](#oauth-access-tokens), not API keys. For example, with `SIM_API_KEY` and `WORKFLOW_ID` set: diff --git a/apps/docs/content/docs/cli/authentication.mdx b/apps/docs/content/docs/cli/authentication.mdx index 491553f61f0..1475ac1b6c1 100644 --- a/apps/docs/content/docs/cli/authentication.mdx +++ b/apps/docs/content/docs/cli/authentication.mdx @@ -154,7 +154,7 @@ export SIM_WORKSPACE="2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67" sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --input '{"source":"nightly"}' --output json ``` -The environment key overrides stored authentication. Use a workspace key only for supported workspace-scoped operations; organization audit logs and fork administration require a personal credential. Never commit credentials. `SIM_CONFIG_DIR` relocates local state when a runner has no writable home directory. +The environment key overrides stored authentication. Use a workspace key only for supported workspace-scoped operations; organization audit logs and fork administration require a personal credential. A job that runs workflows needs a **Full access** key; a **Read only** key suits jobs that only read, such as exporting logs. Choose an expiration your secret rotation covers: an expired key fails with `API key has expired`. See [key access and expiration](/api-reference/authentication#key-access). Never commit credentials. `SIM_CONFIG_DIR` relocates local state when a runner has no writable home directory. ### GitHub Actions diff --git a/apps/docs/content/docs/mcp/authentication.mdx b/apps/docs/content/docs/mcp/authentication.mdx index 5208ed723f0..28d7e22c01b 100644 --- a/apps/docs/content/docs/mcp/authentication.mdx +++ b/apps/docs/content/docs/mcp/authentication.mdx @@ -55,8 +55,10 @@ A personal key uses your current access in the workspaces you can reach. A works The Cursor process must receive `SIM_API_KEY` for its environment interpolation to work. For a self-hosted deployment, replace the Cloud URL in both examples with your server URL. +For an agent that only reads, create a **Read only** key: it reaches the operations `api:read` allows, and a write tool call fails with `READ_ONLY_API_KEY`. See [key access](/api-reference/authentication#key-access). + - Keys created in Sim settings have no default expiration. Revoke a key when it is no longer needed. Prefer OAuth for an app that + Keys created in Sim settings expire after 90 days unless you choose otherwise. Revoke a key when it is no longer needed. Prefer OAuth for an app that supports browser sign-in, and store keys in your app's secret or environment settings rather than in a shared config file. diff --git a/apps/docs/openapi-v2-billing.json b/apps/docs/openapi-v2-billing.json index cd41bac2c0c..fabcf04f983 100644 --- a/apps/docs/openapi-v2-billing.json +++ b/apps/docs/openapi-v2-billing.json @@ -566,6 +566,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/docs/openapi-v2-files-audit.json b/apps/docs/openapi-v2-files-audit.json index 2fcff52693b..d28f2df00a7 100644 --- a/apps/docs/openapi-v2-files-audit.json +++ b/apps/docs/openapi-v2-files-audit.json @@ -4713,6 +4713,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/docs/openapi-v2-knowledge.json b/apps/docs/openapi-v2-knowledge.json index cadd389f3d1..75f473cb683 100644 --- a/apps/docs/openapi-v2-knowledge.json +++ b/apps/docs/openapi-v2-knowledge.json @@ -6018,6 +6018,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/docs/openapi-v2-logs.json b/apps/docs/openapi-v2-logs.json index 52c8878d3e4..58c1c1e947f 100644 --- a/apps/docs/openapi-v2-logs.json +++ b/apps/docs/openapi-v2-logs.json @@ -1065,6 +1065,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/docs/openapi-v2-resources.json b/apps/docs/openapi-v2-resources.json index 89d0ab247db..c53f6f0639f 100644 --- a/apps/docs/openapi-v2-resources.json +++ b/apps/docs/openapi-v2-resources.json @@ -4714,7 +4714,7 @@ "get": { "operationId": "getApiMeta", "summary": "Get API status", - "description": "Get the calling credential’s type and expiry. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.\n\nOAuth scope: `api:read`.", + "description": "Get the calling credential’s type, expiry, and API scopes. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.\n\nOAuth scope: `api:read`.", "x-sim-operation": "meta.capabilities.read", "x-oauth-scope": "api:read", "tags": ["Meta"], @@ -4752,7 +4752,8 @@ "data": { "v2Enabled": true, "keyType": "personal", - "expiresAt": null + "expiresAt": null, + "scopes": ["api:read", "api:write"] } } } @@ -14574,6 +14575,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", @@ -18320,9 +18322,17 @@ } ], "description": "ISO 8601 timestamp when the calling credential expires, or null when it does not." + }, + "scopes": { + "type": "array", + "items": { + "type": "string", + "enum": ["api:read", "api:write", "search:read"] + }, + "description": "API scopes the calling credential holds. A read-only API key holds only api:read and is refused every operation that changes state; a full-access key holds api:read and api:write; an OAuth access token holds what it was granted." } }, - "required": ["v2Enabled", "keyType", "expiresAt"], + "required": ["v2Enabled", "keyType", "expiresAt", "scopes"], "additionalProperties": false, "title": "API status", "description": "API availability and lifecycle facts about the calling credential." @@ -18338,13 +18348,14 @@ "required": ["data"], "additionalProperties": false, "title": "API status response", - "description": "API availability, credential type, and expiry for the caller.", + "description": "API availability, credential type, expiry, and scopes for the caller.", "examples": [ { "data": { "v2Enabled": true, "keyType": "personal", - "expiresAt": null + "expiresAt": null, + "scopes": ["api:read", "api:write"] } } ] diff --git a/apps/docs/openapi-v2-tables.json b/apps/docs/openapi-v2-tables.json index 1efe55b277d..509b1ef430d 100644 --- a/apps/docs/openapi-v2-tables.json +++ b/apps/docs/openapi-v2-tables.json @@ -5977,6 +5977,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/docs/openapi-v2-workflows.json b/apps/docs/openapi-v2-workflows.json index 404c5d208ce..9bdf8bb294a 100644 --- a/apps/docs/openapi-v2-workflows.json +++ b/apps/docs/openapi-v2-workflows.json @@ -7544,6 +7544,7 @@ "PERMISSION_GROUP_CAPABILITY_BLOCKED", "INTEGRATION_NOT_ALLOWED", "INSUFFICIENT_SCOPE", + "READ_ONLY_API_KEY", "SCIM_MANAGED_MEMBERSHIP" ], "title": "Forbidden detail code", diff --git a/apps/sim/app/api/mcp/serve/[serverId]/route.test.ts b/apps/sim/app/api/mcp/serve/[serverId]/route.test.ts index 7a1d7bd850d..e450390e946 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/route.test.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/route.test.ts @@ -80,6 +80,7 @@ const PERSONAL_API_KEY_PRINCIPAL = { kind: 'personal_api_key', userId: 'user-1', keyId: 'personal-key-1', + access: 'write', } as const const OAUTH_WRITE_PRINCIPAL = { diff --git a/apps/sim/app/api/mcp/serve/[serverId]/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/route.ts index aa1464b421d..19fc099ba35 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/route.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/route.ts @@ -17,7 +17,11 @@ import { SUPPORTED_PROTOCOL_VERSIONS, type Tool, } from '@modelcontextprotocol/sdk/types.js' -import { isUserCredentialPrincipal, type WorkflowExecutionPrincipal } from '@sim/auth/principal' +import { + isReadOnlyApiKeyPrincipal, + isUserCredentialPrincipal, + type WorkflowExecutionPrincipal, +} from '@sim/auth/principal' import { db } from '@sim/db' import { workflow, @@ -37,7 +41,7 @@ import { mcpServeRouteParamsSchema, mcpToolCallParamsSchema, } from '@/lib/api/contracts/mcp' -import { PERSONAL_KEY_DENIED } from '@/lib/api-key/policy-messages' +import { PERSONAL_KEY_DENIED, READ_ONLY_API_KEY_DENIED } from '@/lib/api-key/policy-messages' import { type AuthResult, checkHybridAuth } from '@/lib/auth/hybrid' import { InvalidOAuthAccessTokenError, @@ -604,13 +608,24 @@ async function authorizeMcpServeRequest( } } -/** Calling a tool runs a workflow, so an OAuth token needs `api:write`. */ +/** + * Calling a tool runs a workflow, so an OAuth token needs `api:write` and a + * read-only API key is refused outright: it has no scope to step up to. + */ function insufficientToolCallScopeResponse( id: RequestId, serverId: string, executeAuthContext: ExecuteAuthContext | null ): NextResponse | null { const principal = executeAuthContext?.principal + if (principal && isReadOnlyApiKeyPrincipal(principal)) { + return NextResponse.json( + createError(id, ErrorCode.InvalidRequest, READ_ONLY_API_KEY_DENIED, { + code: 'READ_ONLY_API_KEY', + }), + { status: 403 } + ) + } if (principal?.kind !== 'oauth_access_token') return null if (oauthScopeSatisfies(principal.scopes, OAUTH_API_WRITE_SCOPE)) return null return insufficientScopeResponse( diff --git a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.test.ts b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.test.ts index 56955c216d2..54f3a68e6e1 100644 --- a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.test.ts +++ b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.test.ts @@ -185,6 +185,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => { success: true, keyId: WORKSPACE_KEY_PRINCIPAL.keyId, keyType: 'workspace', + access: 'write', workspaceId: WORKSPACE_ID, }) mockResolvePermission.mockResolvedValue('write') @@ -250,6 +251,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => { success: true, keyId: 'personal-key', keyType: 'personal', + access: 'write', userId: 'read-only-member', }), }, diff --git a/apps/sim/app/api/users/me/api-keys/route.ts b/apps/sim/app/api/users/me/api-keys/route.ts index de3fe9f43b0..f74c5a599ac 100644 --- a/apps/sim/app/api/users/me/api-keys/route.ts +++ b/apps/sim/app/api/users/me/api-keys/route.ts @@ -14,7 +14,7 @@ import { listPersonalApiKeys, personalApiKeyOperations, } from '@/lib/api-key/application/personal-api-keys' -import { performCreatePersonalApiKey } from '@/lib/api-key/orchestration' +import { apiKeyCreationErrorStatus, performCreatePersonalApiKey } from '@/lib/api-key/orchestration' import { getSession } from '@/lib/auth' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import { capabilityRefusal } from '@/lib/permission-groups/capability-assertions' @@ -79,23 +79,29 @@ export const POST = withRouteHandler(async (request: NextRequest) => { const parsed = await parseRequest(createPersonalApiKeyContract, request, {}) if (!parsed.success) return parsed.response - const { name } = parsed.data.body + const { name, access, expiresAt } = parsed.data.body const result = await performCreatePersonalApiKey({ userId, name, + access, + expiresAt, actorName: session.user.name, actorEmail: session.user.email, request, }) if (!result.success || !result.key) { - const status = result.errorCode === 'conflict' ? 409 : 500 - return NextResponse.json({ error: result.error }, { status }) + return NextResponse.json( + { error: result.error }, + { status: apiKeyCreationErrorStatus(result.errorCode) } + ) } captureServerEvent(userId, 'api_key_created', { key_name: name, scope: 'personal', + access, + expires: expiresAt != null, }) return NextResponse.json({ key: result.key }) diff --git a/apps/sim/app/api/v1/auth.test.ts b/apps/sim/app/api/v1/auth.test.ts index 4678f115e6d..7610abfabf3 100644 --- a/apps/sim/app/api/v1/auth.test.ts +++ b/apps/sim/app/api/v1/auth.test.ts @@ -21,6 +21,7 @@ describe('v1 API key authentication', () => { userId: 'user-1', keyId: 'key-1', keyType: 'personal', + access: 'write', }) await expect( @@ -32,7 +33,7 @@ describe('v1 API key authentication', () => { ) ).resolves.toMatchObject({ authenticated: true, - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, }) }) @@ -42,6 +43,7 @@ describe('v1 API key authentication', () => { userId: 'creator-1', keyId: 'key-1', keyType: 'workspace', + access: 'write', workspaceId: 'workspace-1', }) @@ -62,6 +64,7 @@ describe('v1 API key authentication', () => { userId: 'creator-1', keyId: 'key-1', keyType: 'workspace', + access: 'write', }) await expect( diff --git a/apps/sim/app/api/v1/auth.ts b/apps/sim/app/api/v1/auth.ts index 1d9d4d14d1d..d9d072d2109 100644 --- a/apps/sim/app/api/v1/auth.ts +++ b/apps/sim/app/api/v1/auth.ts @@ -29,6 +29,7 @@ export async function authenticateV1Request(request: NextRequest): Promise = new Set(['/api/v1/knowledge/search']) + +/** + * v1 authorizes in its handlers rather than through the operation funnel, so a + * read-only key is held to reads here, by method: every v1 `POST`, `PUT`, + * `PATCH`, and `DELETE` but search creates, changes, deploys, or deletes. + */ +function isV1ReadRequest(request: NextRequest): boolean { + if (request.method === 'GET' || request.method === 'HEAD') return true + return request.method === 'POST' && V1_READ_ONLY_POST_PATHS.has(request.nextUrl.pathname) } interface AuthorizedRequest { @@ -163,6 +185,21 @@ export async function checkRateLimit( } } + if (auth.principal?.access === 'read' && !isV1ReadRequest(request)) { + return { + allowed: false, + remaining: 0, + limit: 0, + resetAt: new Date(), + refusal: { + status: 403, + code: 'FORBIDDEN', + message: READ_ONLY_API_KEY_DENIED, + details: { code: 'READ_ONLY_API_KEY' }, + }, + } + } + const userId = auth.userId! const subscription = await getHighestPrioritySubscription(userId) @@ -240,6 +277,7 @@ export async function authenticateRequest( } export function createRateLimitResponse(result: RateLimitResult): NextResponse { + if (result.refusal) return workspaceAccessErrorResponse(result.refusal) /** * An authentication failure never reaches the token bucket, so there is no * limit to report. Publishing a placeholder told unauthenticated callers they diff --git a/apps/sim/app/api/v2/access-requests.test.ts b/apps/sim/app/api/v2/access-requests.test.ts index 3f339f51054..2a726160727 100644 --- a/apps/sim/app/api/v2/access-requests.test.ts +++ b/apps/sim/app/api/v2/access-requests.test.ts @@ -69,7 +69,12 @@ import { GET as listWorkspace, } from '@/app/api/v2/workspaces/[workspaceId]/access-requests/route' -const principal = { kind: 'personal_api_key', userId: 'caller', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'caller', + keyId: 'key', + access: 'write', +} as const const organizationId = 'organization-123' const workspaceId = 'workspace-123' const requestId = 'request-123' diff --git a/apps/sim/app/api/v2/audit-logs/route.test.ts b/apps/sim/app/api/v2/audit-logs/route.test.ts index 2383d574037..89801ae7efd 100644 --- a/apps/sim/app/api/v2/audit-logs/route.test.ts +++ b/apps/sim/app/api/v2/audit-logs/route.test.ts @@ -23,7 +23,12 @@ import { REFILTERED_CURSOR_MESSAGE } from '@/lib/api/cursor-binding' import { GET as listLogs } from '@/app/api/v2/audit-logs/route' const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'admin-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'admin-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', 'user:admin-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/billing/logs/route.test.ts b/apps/sim/app/api/v2/billing/logs/route.test.ts index 58c7b694916..0c069f6a078 100644 --- a/apps/sim/app/api/v2/billing/logs/route.test.ts +++ b/apps/sim/app/api/v2/billing/logs/route.test.ts @@ -33,7 +33,12 @@ function ledgerCursor( } const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/billing/status/route.test.ts b/apps/sim/app/api/v2/billing/status/route.test.ts index 1144c42668b..554460feea9 100644 --- a/apps/sim/app/api/v2/billing/status/route.test.ts +++ b/apps/sim/app/api/v2/billing/status/route.test.ts @@ -23,7 +23,12 @@ import { WorkspaceApiKeyScopeAuthorizationError } from '@/lib/core/application' import { GET } from '@/app/api/v2/billing/status/route' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: 'workspace-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', 'workspace:workspace-1'] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/blocks/route.test.ts b/apps/sim/app/api/v2/blocks/route.test.ts index 232f6daeb89..8e7972d2776 100644 --- a/apps/sim/app/api/v2/blocks/route.test.ts +++ b/apps/sim/app/api/v2/blocks/route.test.ts @@ -24,7 +24,12 @@ import { cursorSortKey, encodeOffsetCursor } from '@/app/api/v2/lib/response' const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/connector-types/route.test.ts b/apps/sim/app/api/v2/connector-types/route.test.ts index 3be63b5c984..be52fc0bf40 100644 --- a/apps/sim/app/api/v2/connector-types/route.test.ts +++ b/apps/sim/app/api/v2/connector-types/route.test.ts @@ -25,7 +25,12 @@ import { GET } from '@/app/api/v2/connector-types/route' const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1'] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/credentials/[credentialId]/route.test.ts b/apps/sim/app/api/v2/credentials/[credentialId]/route.test.ts index b490aae5611..ea38360e830 100644 --- a/apps/sim/app/api/v2/credentials/[credentialId]/route.test.ts +++ b/apps/sim/app/api/v2/credentials/[credentialId]/route.test.ts @@ -50,7 +50,12 @@ const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555' const CREDENTIAL_ID = '7c9e6679-7425-40de-944b-e07fc1f90ae7' const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/credentials/route.test.ts b/apps/sim/app/api/v2/credentials/route.test.ts index 24fe6683d16..56abc1b16f1 100644 --- a/apps/sim/app/api/v2/credentials/route.test.ts +++ b/apps/sim/app/api/v2/credentials/route.test.ts @@ -39,6 +39,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, @@ -139,7 +140,7 @@ describe('POST /api/v2/credentials', () => { beforeEach(() => { v2RouteMocks.authenticate.mockResolvedValue({ ...auth, - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, keyType: 'personal', }) v2RouteMocks.preauthRate.mockResolvedValue(V2_PREAUTH_RATE_LIMIT_ALLOWED) @@ -184,7 +185,7 @@ describe('POST /api/v2/credentials', () => { expect(JSON.stringify(body)).not.toContain('client-secret') expect(JSON.stringify(body)).not.toContain('must-not-leak') expect(mocks.create).toHaveBeenCalledWith({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, input: { workspaceId: WORKSPACE_ID, providerId: 'zoom-service-account', @@ -236,7 +237,7 @@ describe('POST /api/v2/credentials', () => { expect(response.status).toBe(201) expect(mocks.create).toHaveBeenCalledWith({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, input: expect.objectContaining({ providerId: 'oci-api-key-service-account', tenancyOcid: 'ocid1.tenancy.oc1..tenant', diff --git a/apps/sim/app/api/v2/files/[fileId]/content/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/content/route.test.ts index bbdf598dfac..b5f2415c13d 100644 --- a/apps/sim/app/api/v2/files/[fileId]/content/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/content/route.test.ts @@ -51,6 +51,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/files/[fileId]/metadata/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/metadata/route.test.ts index 80a3a0cb24c..3a102dd1374 100644 --- a/apps/sim/app/api/v2/files/[fileId]/metadata/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/metadata/route.test.ts @@ -34,7 +34,12 @@ const WORKSPACE_ID = 'workspace-1' const FILE_ID = 'wf_1' const context = { params: Promise.resolve({ fileId: FILE_ID }) } const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/files/[fileId]/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/route.test.ts index 16a98c257ea..e5679223e51 100644 --- a/apps/sim/app/api/v2/files/[fileId]/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/route.test.ts @@ -57,6 +57,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/files/[fileId]/text/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/text/route.test.ts index 796025d11ea..2f873258124 100644 --- a/apps/sim/app/api/v2/files/[fileId]/text/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/text/route.test.ts @@ -31,7 +31,12 @@ const FILE_ID = 'wf_doc' const context = { params: Promise.resolve({ fileId: FILE_ID }) } const AUTH = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/files/[fileId]/unzip/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/unzip/route.test.ts index b4cefda7c95..7429a3fa486 100644 --- a/apps/sim/app/api/v2/files/[fileId]/unzip/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/unzip/route.test.ts @@ -31,7 +31,12 @@ const FILE_ID = 'wf_archive' const context = { params: Promise.resolve({ fileId: FILE_ID }) } const AUTH = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/files/[fileId]/versions/[version]/revert/route.test.ts b/apps/sim/app/api/v2/files/[fileId]/versions/[version]/revert/route.test.ts index c6a62c7bcb1..4386becfa5c 100644 --- a/apps/sim/app/api/v2/files/[fileId]/versions/[version]/revert/route.test.ts +++ b/apps/sim/app/api/v2/files/[fileId]/versions/[version]/revert/route.test.ts @@ -37,6 +37,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/files/route.test.ts b/apps/sim/app/api/v2/files/route.test.ts index e94b63a9cda..7b7bdc519c1 100644 --- a/apps/sim/app/api/v2/files/route.test.ts +++ b/apps/sim/app/api/v2/files/route.test.ts @@ -43,6 +43,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/files/uploads/[uploadId]/route.test.ts b/apps/sim/app/api/v2/files/uploads/[uploadId]/route.test.ts index 7a90a0f3ece..1fe7ef4ee48 100644 --- a/apps/sim/app/api/v2/files/uploads/[uploadId]/route.test.ts +++ b/apps/sim/app/api/v2/files/uploads/[uploadId]/route.test.ts @@ -51,6 +51,7 @@ const AUTH = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/files/uploads/route.test.ts b/apps/sim/app/api/v2/files/uploads/route.test.ts index 5801da94143..e6302263b9e 100644 --- a/apps/sim/app/api/v2/files/uploads/route.test.ts +++ b/apps/sim/app/api/v2/files/uploads/route.test.ts @@ -42,6 +42,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/[documentId]/chunks/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/[documentId]/chunks/route.test.ts index 11dcbacec82..f0cd8852b37 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/[documentId]/chunks/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/[documentId]/chunks/route.test.ts @@ -36,7 +36,12 @@ import { const WORKSPACE_ID = 'workspace-1' const OTHER_WORKSPACE_ID = 'workspace-2' -const PRINCIPAL = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' } as const +const PRINCIPAL = { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', +} as const const context = { params: Promise.resolve({ knowledgeBaseId: 'kb-1', documentId: 'doc-1' }) } const siblingContext = { params: Promise.resolve({ knowledgeBaseId: 'kb-1', documentId: 'doc-2' }) } diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/from-workspace-files/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/from-workspace-files/route.test.ts index 014eb7198dc..8312cea1f4a 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/from-workspace-files/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/documents/from-workspace-files/route.test.ts @@ -40,7 +40,7 @@ beforeEach(() => { v2RouteMocks.preauthRate.mockResolvedValue(V2_PREAUTH_RATE_LIMIT_ALLOWED) v2RouteMocks.operationRate.mockResolvedValue(V2_OPERATION_RATE_LIMIT_ALLOWED) v2RouteMocks.authenticate.mockResolvedValue({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, rateLimitSubjectIds: ['api-key:key-1'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/export/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/export/route.test.ts index 27d9a86fed5..0bba6dfcd00 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/export/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/export/route.test.ts @@ -41,7 +41,12 @@ const FILE_NAME = 'Support docs.simkb.zip' const context = { params: Promise.resolve({ knowledgeBaseId: KNOWLEDGE_BASE_ID }) } const AUTH = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/restore/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/restore/route.test.ts index ae0692714cc..203d6b1a677 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/restore/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/restore/route.test.ts @@ -59,7 +59,7 @@ beforeEach(() => { v2RouteMocks.preauthRate.mockResolvedValue(V2_PREAUTH_RATE_LIMIT_ALLOWED) v2RouteMocks.operationRate.mockResolvedValue(V2_OPERATION_RATE_LIMIT_ALLOWED) v2RouteMocks.authenticate.mockResolvedValue({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, rateLimitSubjectIds: ['api-key:key-1'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/[tagId]/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/[tagId]/route.test.ts index 07c388db409..2495df86e64 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/[tagId]/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/[tagId]/route.test.ts @@ -31,7 +31,7 @@ beforeEach(() => { v2RouteMocks.preauthRate.mockResolvedValue(V2_PREAUTH_RATE_LIMIT_ALLOWED) v2RouteMocks.operationRate.mockResolvedValue(V2_OPERATION_RATE_LIMIT_ALLOWED) v2RouteMocks.authenticate.mockResolvedValue({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, rateLimitSubjectIds: ['api-key:key-1'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/route.test.ts b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/route.test.ts index 25b0d7b7b20..5b68bd4be2a 100644 --- a/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/[knowledgeBaseId]/tags/route.test.ts @@ -54,7 +54,7 @@ describe('DELETE /api/v2/knowledge/[knowledgeBaseId]/tags', () => { v2RouteMocks.preauthRate.mockResolvedValue(V2_PREAUTH_RATE_LIMIT_ALLOWED) v2RouteMocks.operationRate.mockResolvedValue(V2_OPERATION_RATE_LIMIT_ALLOWED) v2RouteMocks.authenticate.mockResolvedValue({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, rateLimitSubjectIds: ['api-key:key-1'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/app/api/v2/knowledge/search/route.test.ts b/apps/sim/app/api/v2/knowledge/search/route.test.ts index 141b92315cb..f6e9eb01ddf 100644 --- a/apps/sim/app/api/v2/knowledge/search/route.test.ts +++ b/apps/sim/app/api/v2/knowledge/search/route.test.ts @@ -23,7 +23,12 @@ import { POST, V2_KNOWLEDGE_SEARCH_MAX_BODY_BYTES } from '@/app/api/v2/knowledge const mockSearch = knowledgeSearchUseCaseMockFns.mockSearchKnowledgeExecute const WORKSPACE_ID = 'workspace-1' -const PRINCIPAL = { kind: 'workspace_api_key', workspaceId: WORKSPACE_ID, keyId: 'key-1' } as const +const PRINCIPAL = { + kind: 'workspace_api_key', + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write', +} as const function buildRequest(body: string, headers: Record = {}) { return new NextRequest('http://localhost/api/v2/knowledge/search', { method: 'POST', diff --git a/apps/sim/app/api/v2/logs/[runId]/route.test.ts b/apps/sim/app/api/v2/logs/[runId]/route.test.ts index bad5dd64acc..e2a5123e3b8 100644 --- a/apps/sim/app/api/v2/logs/[runId]/route.test.ts +++ b/apps/sim/app/api/v2/logs/[runId]/route.test.ts @@ -27,6 +27,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', 'workspace:workspace-1'] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/logs/route.test.ts b/apps/sim/app/api/v2/logs/route.test.ts index a941da995fc..99afcf8b4bb 100644 --- a/apps/sim/app/api/v2/logs/route.test.ts +++ b/apps/sim/app/api/v2/logs/route.test.ts @@ -30,6 +30,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/logs/stats/route.test.ts b/apps/sim/app/api/v2/logs/stats/route.test.ts index f47a679ceb0..d0bfc25bdaa 100644 --- a/apps/sim/app/api/v2/logs/stats/route.test.ts +++ b/apps/sim/app/api/v2/logs/stats/route.test.ts @@ -21,7 +21,12 @@ import { GET } from '@/app/api/v2/logs/stats/route' const WORKSPACE_ID = '6fc7631d-88cd-46f8-9f0a-d4764daef7f8' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/meta/route.ts b/apps/sim/app/api/v2/meta/route.ts index 718b56305ea..39231e06382 100644 --- a/apps/sim/app/api/v2/meta/route.ts +++ b/apps/sim/app/api/v2/meta/route.ts @@ -24,7 +24,7 @@ export const GET = defineV2JsonRoute({ return { keyType: credential.keyType, expiresAt: credential.keyExpiresAt } }, useCase: readV2ApiCapabilities, - present: ({ v2Enabled, keyType, expiresAt }) => ({ - data: { v2Enabled, keyType, expiresAt: expiresAt?.toISOString() ?? null }, + present: ({ v2Enabled, keyType, expiresAt, scopes }) => ({ + data: { v2Enabled, keyType, expiresAt: expiresAt?.toISOString() ?? null, scopes }, }), }) diff --git a/apps/sim/app/api/v2/tables/[tableId]/cancel-runs/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/cancel-runs/route.test.ts index b5e744ad025..03375299a63 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/cancel-runs/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/cancel-runs/route.test.ts @@ -27,6 +27,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/columns/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/columns/route.test.ts index e73299a888d..72439197bff 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/columns/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/columns/route.test.ts @@ -29,6 +29,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/tables/[tableId]/dispatches/[dispatchId]/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/dispatches/[dispatchId]/route.test.ts index c858a26e029..a3fc4268677 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/dispatches/[dispatchId]/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/dispatches/[dispatchId]/route.test.ts @@ -24,6 +24,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/dispatches/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/dispatches/route.test.ts index c774aa3922c..84477e92b95 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/dispatches/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/dispatches/route.test.ts @@ -26,6 +26,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/groups/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/groups/route.test.ts index dab71e8084b..801a4df0d21 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/groups/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/groups/route.test.ts @@ -31,6 +31,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/tables/[tableId]/query/count/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/query/count/route.test.ts index f54a7345b85..ae1fa00df8c 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/query/count/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/query/count/route.test.ts @@ -26,6 +26,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/query/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/query/route.test.ts index ad11d57cc83..14de92ad88e 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/query/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/query/route.test.ts @@ -33,6 +33,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/restore/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/restore/route.test.ts index add64eb7c14..92f7d1508f7 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/restore/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/restore/route.test.ts @@ -32,6 +32,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/enrichment/[groupId]/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/enrichment/[groupId]/route.test.ts index 800723672fd..7850fb2ffbf 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/enrichment/[groupId]/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/enrichment/[groupId]/route.test.ts @@ -32,6 +32,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/route.test.ts index 235cb3d123f..64408eb1f35 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/[rowId]/route.test.ts @@ -26,6 +26,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/bulk-update/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/bulk-update/route.test.ts index 4bebca009aa..fee099c329f 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/bulk-update/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/bulk-update/route.test.ts @@ -25,6 +25,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/route.test.ts index 1ec1ab6cb88..80838bdf17b 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/route.test.ts @@ -37,6 +37,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/search/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/search/route.test.ts index 57c0b572318..ed18bb14906 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/search/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/search/route.test.ts @@ -25,6 +25,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/rows/upsert/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/rows/upsert/route.test.ts index 387f3f78955..03e2bbee2b3 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/rows/upsert/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/rows/upsert/route.test.ts @@ -25,6 +25,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/[tableId]/views/[viewId]/route.test.ts b/apps/sim/app/api/v2/tables/[tableId]/views/[viewId]/route.test.ts index a32f08f7aa6..5c481ca230c 100644 --- a/apps/sim/app/api/v2/tables/[tableId]/views/[viewId]/route.test.ts +++ b/apps/sim/app/api/v2/tables/[tableId]/views/[viewId]/route.test.ts @@ -33,6 +33,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/tables/folders/restore/route.test.ts b/apps/sim/app/api/v2/tables/folders/restore/route.test.ts index ff949051394..fc419b7ba6d 100644 --- a/apps/sim/app/api/v2/tables/folders/restore/route.test.ts +++ b/apps/sim/app/api/v2/tables/folders/restore/route.test.ts @@ -26,6 +26,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/move/route.test.ts b/apps/sim/app/api/v2/tables/move/route.test.ts index 68c40fcd4bb..b78232d2e40 100644 --- a/apps/sim/app/api/v2/tables/move/route.test.ts +++ b/apps/sim/app/api/v2/tables/move/route.test.ts @@ -25,6 +25,7 @@ const PRINCIPAL = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const AUTH = { principal: PRINCIPAL, diff --git a/apps/sim/app/api/v2/tables/route.test.ts b/apps/sim/app/api/v2/tables/route.test.ts index 411ca66e68b..5aac8ac7985 100644 --- a/apps/sim/app/api/v2/tables/route.test.ts +++ b/apps/sim/app/api/v2/tables/route.test.ts @@ -34,6 +34,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/tools/[toolId]/execute/route.test.ts b/apps/sim/app/api/v2/tools/[toolId]/execute/route.test.ts index 60babfe6faf..f3cebdbe75d 100644 --- a/apps/sim/app/api/v2/tools/[toolId]/execute/route.test.ts +++ b/apps/sim/app/api/v2/tools/[toolId]/execute/route.test.ts @@ -23,7 +23,12 @@ import { POST } from '@/app/api/v2/tools/[toolId]/execute/route' const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555' const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/tools/route.test.ts b/apps/sim/app/api/v2/tools/route.test.ts index 5a788c2fc30..c9e867dc61f 100644 --- a/apps/sim/app/api/v2/tools/route.test.ts +++ b/apps/sim/app/api/v2/tools/route.test.ts @@ -24,7 +24,12 @@ import { GET } from '@/app/api/v2/tools/route' const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555' const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/duplicate/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/duplicate/route.test.ts index af19ebb7de5..50516ca9ad9 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/duplicate/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/duplicate/route.test.ts @@ -24,7 +24,12 @@ import { POST } from '@/app/api/v2/workflows/[workflowId]/duplicate/route' const WORKFLOW_ID = 'workflow-1' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'ws-key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: 'workspace-1', + keyId: 'ws-key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:ws-key-1'] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/operations/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/operations/route.test.ts index f5c47cb69e9..b23a9766fc3 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/operations/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/operations/route.test.ts @@ -45,7 +45,12 @@ const DROPPED_INPUT = { const LINT = createEmptyWorkflowLintReport() const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'personal-key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'personal-key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:personal-key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/restore/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/restore/route.test.ts index fc110a96c34..48ca2c607c1 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/restore/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/restore/route.test.ts @@ -21,7 +21,12 @@ import { POST } from '@/app/api/v2/workflows/[workflowId]/restore/route' const WORKFLOW_ID = 'workflow-1' const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'personal-key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'personal-key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:personal-key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/route.test.ts index b66fdfd2395..19fa5f2b54d 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/route.test.ts @@ -50,6 +50,7 @@ const auth = { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'personal-key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:personal-key-1', 'user:user-1'] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/cancel/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/cancel/route.test.ts index 0ae665d6231..3255af4de16 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/cancel/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/cancel/route.test.ts @@ -29,6 +29,7 @@ const principal = { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/files/[fileId]/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/files/[fileId]/route.test.ts index c446d5adbe8..d5264deec6f 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/files/[fileId]/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/files/[fileId]/route.test.ts @@ -46,6 +46,7 @@ const workspaceKeyAuth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/route.test.ts index 3a78c29156b..12c3f8c0249 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/runs/[runId]/route.test.ts @@ -31,6 +31,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/runs/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/runs/route.test.ts index 5a01dd1a4eb..9f245d59492 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/runs/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/runs/route.test.ts @@ -30,6 +30,7 @@ const principal = { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write' as const, } const auth = { principal, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/state/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/state/route.test.ts index d4c1f6b9a3d..fe92314e2b3 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/state/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/state/route.test.ts @@ -48,7 +48,12 @@ const GRAPH = { } const personalAuth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'personal-key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'personal-key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:personal-key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, diff --git a/apps/sim/app/api/v2/workflows/[workflowId]/versions/route.test.ts b/apps/sim/app/api/v2/workflows/[workflowId]/versions/route.test.ts index b94a89bc1e1..5bdaf68c414 100644 --- a/apps/sim/app/api/v2/workflows/[workflowId]/versions/route.test.ts +++ b/apps/sim/app/api/v2/workflows/[workflowId]/versions/route.test.ts @@ -29,6 +29,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: 'workspace-1', keyId: 'workspace-key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:workspace-key-1', 'workspace:workspace-1'] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/workflows/move/route.test.ts b/apps/sim/app/api/v2/workflows/move/route.test.ts index 91be41c1891..8678a820ea7 100644 --- a/apps/sim/app/api/v2/workflows/move/route.test.ts +++ b/apps/sim/app/api/v2/workflows/move/route.test.ts @@ -20,7 +20,12 @@ import { POST } from '@/app/api/v2/workflows/move/route' const WORKSPACE_ID = 'workspace-1' const auth = { - principal: { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'ws-key-1' }, + principal: { + kind: 'workspace_api_key' as const, + workspaceId: WORKSPACE_ID, + keyId: 'ws-key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:ws-key-1'] as const, rateLimitSubscription: null, keyType: 'workspace' as const, diff --git a/apps/sim/app/api/v2/workflows/route.test.ts b/apps/sim/app/api/v2/workflows/route.test.ts index daea1653396..14b763c61cd 100644 --- a/apps/sim/app/api/v2/workflows/route.test.ts +++ b/apps/sim/app/api/v2/workflows/route.test.ts @@ -60,6 +60,7 @@ const workspaceAuth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'workspace-key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:workspace-key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/workspaces/[workspaceId]/invitations/route.test.ts b/apps/sim/app/api/v2/workspaces/[workspaceId]/invitations/route.test.ts index 55298f74ee7..854cf04c03d 100644 --- a/apps/sim/app/api/v2/workspaces/[workspaceId]/invitations/route.test.ts +++ b/apps/sim/app/api/v2/workspaces/[workspaceId]/invitations/route.test.ts @@ -23,7 +23,12 @@ import { OrchestrationError } from '@/lib/core/orchestration/types' import { POST } from '@/app/api/v2/workspaces/[workspaceId]/invitations/route' const workspaceId = 'workspace-123' -const principal = { kind: 'personal_api_key', userId: 'caller', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'caller', + keyId: 'key', + access: 'write', +} as const const call = (body: unknown, query = '') => POST( new NextRequest(`http://localhost/api/v2/workspaces/${workspaceId}/invitations${query}`, { diff --git a/apps/sim/app/api/v2/workspaces/[workspaceId]/permission-config/route.test.ts b/apps/sim/app/api/v2/workspaces/[workspaceId]/permission-config/route.test.ts index 514415f1da3..65fea9a3fb2 100644 --- a/apps/sim/app/api/v2/workspaces/[workspaceId]/permission-config/route.test.ts +++ b/apps/sim/app/api/v2/workspaces/[workspaceId]/permission-config/route.test.ts @@ -25,7 +25,12 @@ import { NoWorkspaceAccessError } from '@/lib/core/application' import { GET } from '@/app/api/v2/workspaces/[workspaceId]/permission-config/route' const workspaceId = 'workspace-123' -const principal = { kind: 'personal_api_key', userId: 'caller', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'caller', + keyId: 'key', + access: 'write', +} as const const result = { permissionGroupId: null, groupName: null, diff --git a/apps/sim/app/api/v2/workspaces/[workspaceId]/route.test.ts b/apps/sim/app/api/v2/workspaces/[workspaceId]/route.test.ts index c61f947421f..64bb92b2c8d 100644 --- a/apps/sim/app/api/v2/workspaces/[workspaceId]/route.test.ts +++ b/apps/sim/app/api/v2/workspaces/[workspaceId]/route.test.ts @@ -44,6 +44,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/v2/workspaces/route.test.ts b/apps/sim/app/api/v2/workspaces/route.test.ts index ea6b830c87d..3f91e60833a 100644 --- a/apps/sim/app/api/v2/workspaces/route.test.ts +++ b/apps/sim/app/api/v2/workspaces/route.test.ts @@ -47,6 +47,7 @@ const auth = { kind: 'workspace_api_key' as const, workspaceId: WORKSPACE_ID, keyId: 'key-1', + access: 'write' as const, }, rateLimitSubjectIds: ['api-key:key-1', `workspace:${WORKSPACE_ID}`] as const, rateLimitSubscription: null, diff --git a/apps/sim/app/api/workflows/[id]/execute/route.test.ts b/apps/sim/app/api/workflows/[id]/execute/route.test.ts index a6ce1ca061d..deef9d33abf 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.test.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.test.ts @@ -269,12 +269,14 @@ const PERSONAL_API_KEY_PRINCIPAL = { kind: 'personal_api_key', userId: 'personal-key-user-1', keyId: 'personal-key-1', + access: 'write', } as const const WORKSPACE_API_KEY_PRINCIPAL = { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'workspace-key-1', + access: 'write', } as const const EXECUTION_CALLERS: ExecutionCallerCase[] = [ @@ -2161,6 +2163,7 @@ describe('workflow execute async route', () => { kind: 'personal_api_key', userId: 'api-user-1', keyId: 'personal-key-1', + access: 'write', }, }) workflowsUtilsMockFns.mockWorkflowHasResponseBlock.mockReturnValueOnce(true) diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index 94d7625a68f..195fc27607d 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -1,4 +1,4 @@ -import type { WorkflowExecutionPrincipal } from '@sim/auth/principal' +import { isReadOnlyApiKeyPrincipal, type WorkflowExecutionPrincipal } from '@sim/auth/principal' import { db } from '@sim/db' import { workflow as workflowTable } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -16,7 +16,11 @@ import { WORKFLOW_EXECUTION_TIMEOUT_SECONDS_HEADER, } from '@/lib/api/contracts/workflows' import { hasExternalApiCredentials } from '@/lib/api/server/credential-headers' -import { PERSONAL_KEY_DENIED, WORKSPACE_KEY_SCOPE_DENIED } from '@/lib/api-key/policy-messages' +import { + PERSONAL_KEY_DENIED, + READ_ONLY_API_KEY_DENIED, + WORKSPACE_KEY_SCOPE_DENIED, +} from '@/lib/api-key/policy-messages' import { AuthType, checkHybridAuth } from '@/lib/auth/hybrid' import { releaseExecutionSlot } from '@/lib/billing/calculations/usage-reservation' import { @@ -550,6 +554,14 @@ async function handleExecutePost( return NextResponse.json({ error: 'Access denied' }, { status: 403 }) } + /** Running a workflow changes state, and this route authorizes outside the operation funnel. */ + if (auth.success && auth.principal && isReadOnlyApiKeyPrincipal(auth.principal)) { + return NextResponse.json( + { error: READ_ONLY_API_KEY_DENIED, details: { code: 'READ_ONLY_API_KEY' } }, + { status: 403 } + ) + } + const executionModeHeader = req.headers.get('X-Execution-Mode') const isAsyncMode = executionModeHeader === 'async' const trustedDeadlineHeader = diff --git a/apps/sim/app/api/workspaces/[id]/api-keys/route.test.ts b/apps/sim/app/api/workspaces/[id]/api-keys/route.test.ts index b4f988ef9b6..8376cb94f9f 100644 --- a/apps/sim/app/api/workspaces/[id]/api-keys/route.test.ts +++ b/apps/sim/app/api/workspaces/[id]/api-keys/route.test.ts @@ -57,6 +57,7 @@ describe('GET /api/workspaces/[id]/api-keys', () => { { id: 'key-1', name: 'Legacy key', + access: 'write', key: 'sim_plaintext_legacy_secret', createdAt: new Date('2026-07-01T00:00:00.000Z'), lastUsed: null, @@ -79,6 +80,7 @@ describe('GET /api/workspaces/[id]/api-keys', () => { { id: 'key-1', name: 'Legacy key', + access: 'write', displayKey: 'sim_••••legacy', createdAt: '2026-07-01T00:00:00.000Z', lastUsed: null, diff --git a/apps/sim/app/api/workspaces/[id]/api-keys/route.ts b/apps/sim/app/api/workspaces/[id]/api-keys/route.ts index 2dc2ea4ffdf..04b6bf2d816 100644 --- a/apps/sim/app/api/workspaces/[id]/api-keys/route.ts +++ b/apps/sim/app/api/workspaces/[id]/api-keys/route.ts @@ -21,7 +21,10 @@ import { workspaceApiKeyOperations, } from '@/lib/api-key/application/workspace-api-keys' import { workspaceApiKeyErrorPolicy } from '@/lib/api-key/management-error-policy' -import { performCreateWorkspaceApiKey } from '@/lib/api-key/orchestration' +import { + apiKeyCreationErrorStatus, + performCreateWorkspaceApiKey, +} from '@/lib/api-key/orchestration' import { getSession } from '@/lib/auth' import { PlatformEvents } from '@/lib/core/telemetry' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' @@ -90,25 +93,29 @@ export const POST = withRouteHandler( const parsed = await parseRequest(createWorkspaceApiKeyContract, request, context) if (!parsed.success) return parsed.response - const { name, source } = parsed.data.body + const { name, source, access, expiresAt } = parsed.data.body const result = await performCreateWorkspaceApiKey({ workspaceId, userId, name, source, + access, + expiresAt, actorName: session.user.name, actorEmail: session.user.email, }) if (!result.success || !result.key) { - const status = result.errorCode === 'conflict' ? 409 : 500 - return NextResponse.json({ error: result.error }, { status }) + return NextResponse.json( + { error: result.error }, + { status: apiKeyCreationErrorStatus(result.errorCode) } + ) } captureServerEvent( userId, 'api_key_created', - { workspace_id: workspaceId, key_name: name, source }, + { workspace_id: workspaceId, key_name: name, source, access, expires: expiresAt != null }, { groups: { workspace: workspaceId }, setOnce: { first_api_key_created_at: new Date().toISOString() }, diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx index 88a2a9afe14..033dd06fb15 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx @@ -1,7 +1,7 @@ 'use client' import { useMemo, useState } from 'react' -import { Chip, ChipConfirmModal, Label, Switch, Tooltip, toast } from '@sim/emcn' +import { Chip, ChipConfirmModal, ChipTag, Label, Switch, Tooltip, toast } from '@sim/emcn' import { CircleInfo, Plus } from '@sim/emcn/icons' import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' @@ -49,6 +49,27 @@ function formatLastUsed(dateString?: string | null): string { return formatDate(new Date(dateString)) } +/** The row caption: last use and expiry, after a tag when the key is read-only. */ +function ApiKeyRowBadge({ apiKey }: { apiKey: ApiKey }) { + const parts = [`last used ${formatLastUsed(apiKey.lastUsed).toLowerCase()}`] + if (apiKey.expiresAt) { + const expiresAt = new Date(apiKey.expiresAt) + parts.push( + expiresAt.getTime() <= Date.now() + ? 'expired' + : `expires ${formatDate(expiresAt).toLowerCase()}` + ) + } + return ( + + {apiKey.access === 'read' && Read only} + + {parts.join(' · ')} + + + ) +} + interface ApiKeyRowMenuProps { keyName: string onDelete: () => void @@ -265,11 +286,7 @@ export function ApiKeys({ scope = 'workspace' }: ApiKeysProps) { key={key.id} title={key.name} description={key.displayKey} - badge={ - - {`last used ${formatLastUsed(key.lastUsed).toLowerCase()}`} - - } + badge={} trailing={ - {`last used ${formatLastUsed(key.lastUsed).toLowerCase()}`} - - } + badge={} trailing={ - {`last used ${formatLastUsed(key.lastUsed).toLowerCase()}`} - - } + badge={} trailing={ void @@ -27,6 +45,8 @@ interface CreateApiKeyModalProps { canManageWorkspaceKeys?: boolean defaultKeyType?: 'personal' | 'workspace' source?: 'settings' | 'deploy_modal' + /** For a key created to run workflows: hides the access choice and always issues full access. */ + fullAccessOnly?: boolean onKeyCreated?: (key: CreatedApiKey) => void } @@ -45,10 +65,13 @@ export function CreateApiKeyModal({ canManageWorkspaceKeys = false, defaultKeyType = 'personal', source = 'settings', + fullAccessOnly = false, onKeyCreated, }: CreateApiKeyModalProps) { const [keyName, setKeyName] = useState('') const [keyType, setKeyType] = useState<'personal' | 'workspace'>(defaultKeyType) + const [access, setAccess] = useState('write') + const [expiry, setExpiry] = useState(DEFAULT_EXPIRY) const [createError, setCreateError] = useState(null) const [newKey, setNewKey] = useState(null) const [showNewKeyDialog, setShowNewKeyDialog] = useState(false) @@ -73,6 +96,8 @@ export function CreateApiKeyModal({ if (open) { setKeyName('') setKeyType(defaultKeyType) + setAccess('write') + setExpiry(DEFAULT_EXPIRY) setCreateError(null) } } @@ -99,15 +124,16 @@ export function CreateApiKeyModal({ setCreateError(null) try { if (keyType === 'workspace' && !workspaceId) return + const settings = { + name: trimmedName, + source, + access: fullAccessOnly ? 'write' : access, + expiresAt: expiresAtFor(expiry), + } as const const data = await createApiKeyMutation.mutateAsync( keyType === 'workspace' && workspaceId - ? { - workspaceId, - name: trimmedName, - keyType, - source, - } - : { keyType: 'personal', name: trimmedName, source } + ? { ...settings, workspaceId, keyType } + : { ...settings, keyType: 'personal' } ) setNewKey(data.key) @@ -169,6 +195,25 @@ export function CreateApiKeyModal({ autoComplete='off' required /> + {!fullAccessOnly && ( + + setAccess(value as ApiKeyAccessLevel)} + > + Full access + Read only + + + )} + setExpiry(value as ExpiryOption)} + options={EXPIRY_OPTIONS} + align='start' + /> {/* Hidden decoy fields to prevent browser autofill */} )} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx index 37e61f5fcb4..7b3d143108a 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/deploy-modal.tsx @@ -738,6 +738,7 @@ export function DeployModal({ canManageWorkspaceKeys={canManageWorkspaceKeys} defaultKeyType={defaultKeyType} source='deploy_modal' + fullAccessOnly /> {workflowId && ( diff --git a/apps/sim/ee/access-requests/lib/application/flow.integration.ts b/apps/sim/ee/access-requests/lib/application/flow.integration.ts index 3ca5e98d013..a6929e6da06 100644 --- a/apps/sim/ee/access-requests/lib/application/flow.integration.ts +++ b/apps/sim/ee/access-requests/lib/application/flow.integration.ts @@ -382,7 +382,12 @@ describe('access request member-to-admin flow on PostgreSQL', () => { const transactionsBefore = transaction.mock.calls.length await expect( createAccessRequest.execute({ - principal: { kind: 'workspace_api_key', workspaceId: 'primary', keyId: 'fixture-key' }, + principal: { + kind: 'workspace_api_key', + workspaceId: 'primary', + keyId: 'fixture-key', + access: 'write', + }, input: { scope, target }, }) ).rejects.toMatchObject({ detailCode: 'WORKSPACE_KEY_OPERATION_NOT_PERMITTED' }) diff --git a/apps/sim/executor/handlers/agent/memory-harness.integration.ts b/apps/sim/executor/handlers/agent/memory-harness.integration.ts index d03d64dcd57..807d003e79a 100644 --- a/apps/sim/executor/handlers/agent/memory-harness.integration.ts +++ b/apps/sim/executor/handlers/agent/memory-harness.integration.ts @@ -496,6 +496,7 @@ describe('Agent memory through PostgreSQL, storage, and provider transports', () kind: 'workspace_api_key', workspaceId: scope.workspaceId, keyId: 'harness-key', + access: 'write', }, input: { key, assertedWorkspaceId: scope.workspaceId }, }) diff --git a/apps/sim/hooks/queries/api-keys.ts b/apps/sim/hooks/queries/api-keys.ts index 2c47ec509a2..e050229a6dc 100644 --- a/apps/sim/hooks/queries/api-keys.ts +++ b/apps/sim/hooks/queries/api-keys.ts @@ -50,15 +50,22 @@ export function useCreateApiKey() { const queryClient = useQueryClient() return useMutation({ - mutationFn: async ({ workspaceId, name, keyType, source }: CreateApiKeyParams) => { + mutationFn: async ({ + workspaceId, + name, + keyType, + source, + access, + expiresAt, + }: CreateApiKeyParams) => { if (keyType === 'workspace') { return requestJson(createWorkspaceApiKeyContract, { params: { id: workspaceId }, - body: { name, source }, + body: { name, source, access, expiresAt }, }) } - return requestJson(createPersonalApiKeyContract, { body: { name } }) + return requestJson(createPersonalApiKeyContract, { body: { name, access, expiresAt } }) }, onSettled: (_data, _error, variables) => { if (variables.keyType === 'personal') { diff --git a/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts b/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts new file mode 100644 index 00000000000..a304c07f201 --- /dev/null +++ b/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts @@ -0,0 +1,390 @@ +/** + * Read-only and expiring API keys against real PostgreSQL, through the route + * handlers a caller reaches: the v2 builders, the Sim MCP server, v1, the legacy + * execute route, a workflow MCP server, and the resume and cancel legs. A + * read-only key must be refused every write on every path without changing a + * row, keep its reads, and an expired key must say it expired. The keys used + * here are minted through the settings routes, so the create path's bounds are + * exercised by the same suite. + */ +import { db } from '@sim/db' +import { + apiKey, + permissions, + user, + userTableDefinitions, + workflow, + workflowExecutionLogs, + workflowMcpServer, + workspace, +} from '@sim/db/schema' +import { deleteWorkspaceFixture, insertWorkspaceFixture } from '@sim/db/testing/workspace-fixtures' +import { authMock, authMockFns } from '@sim/testing' +import { generateId } from '@sim/utils/id' +import { eq } from 'drizzle-orm' +import { NextRequest } from 'next/server' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' + +vi.mock('@/lib/auth', () => authMock) + +import { hashApiKey } from '@/lib/api-key/crypto' +import { READ_ONLY_API_KEY_DENIED } from '@/lib/api-key/policy-messages' +import { POST as simMcpPost } from '@/app/api/mcp/route' +import { POST as workflowMcpPost } from '@/app/api/mcp/serve/[serverId]/route' +import { POST as legacyResume } from '@/app/api/resume/[workflowId]/[executionId]/[contextId]/route' +import { POST as createPersonalKey } from '@/app/api/users/me/api-keys/route' +import { POST as v1KnowledgeSearch } from '@/app/api/v1/knowledge/search/route' +import { POST as v1CreateTable, GET as v1ListTables } from '@/app/api/v1/tables/route' +import { GET as v2Meta } from '@/app/api/v2/meta/route' +import { POST as v2CreateTable, GET as v2ListTables } from '@/app/api/v2/tables/route' +import { POST as v2CancelRun } from '@/app/api/v2/workflows/[workflowId]/runs/[runId]/cancel/route' +import { POST as v2ResumeRun } from '@/app/api/v2/workflows/[workflowId]/runs/[runId]/resume/route' +import { POST as legacyExecute } from '@/app/api/workflows/[id]/execute/route' +import { POST as internalCancelRun } from '@/app/api/workflows/[id]/executions/[executionId]/cancel/route' +import { POST as createWorkspaceKey } from '@/app/api/workspaces/[id]/api-keys/route' + +const ORIGIN = 'http://localhost:3000' +const DAY_MS = 24 * 60 * 60 * 1000 + +const userId = generateId() +const workspaceId = generateId() +const workflowId = generateId() +const mcpServerId = generateId() +const legacyKey = `sk-sim-fixture-${generateId()}` +const expiredKey = `sk-sim-fixture-${generateId()}` + +let readPersonalKey = '' +let readWorkspaceKey = '' + +type RouteHandler = (request: NextRequest, context: { params: Promise }) => Promise + +interface CallOptions { + method?: string + key?: string + body?: unknown + params?: Record + headers?: Record +} + +async function call(handler: unknown, path: string, options: CallOptions = {}) { + const headers = new Headers({ 'x-forwarded-for': '127.0.0.1', ...options.headers }) + if (options.key) headers.set('x-api-key', options.key) + if (options.body !== undefined) headers.set('content-type', 'application/json') + const request = new NextRequest(`${ORIGIN}${path}`, { + method: options.method ?? (options.body === undefined ? 'GET' : 'POST'), + headers, + ...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }), + }) + const response = await (handler as RouteHandler)(request, { + params: Promise.resolve(options.params ?? {}) as Promise, + }) + const text = await response.text() + let body: unknown = text + try { + body = JSON.parse(text) + } catch {} + return { status: response.status, body } +} + +function tableBody(name: string) { + return { + workspaceId, + name, + schema: { columns: [{ name: 'title', type: 'string' }] }, + } +} + +async function tableCount(): Promise { + const rows = await db + .select({ id: userTableDefinitions.id }) + .from(userTableDefinitions) + .where(eq(userTableDefinitions.workspaceId, workspaceId)) + return rows.length +} + +async function executionCount(): Promise { + const rows = await db + .select({ id: workflowExecutionLogs.id }) + .from(workflowExecutionLogs) + .where(eq(workflowExecutionLogs.workflowId, workflowId)) + return rows.length +} + +function mcpToolCall(name: string, args: Record) { + return { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name, arguments: args } } +} + +const MCP_HEADERS = { accept: 'application/json, text/event-stream' } + +describe('read-only and expiring API keys in PostgreSQL', () => { + beforeAll(async () => { + const now = new Date() + await db.insert(user).values({ + id: userId, + name: 'Read-only key fixture', + email: `${userId}@read-only-key.test`, + emailVerified: true, + createdAt: now, + updatedAt: now, + }) + await insertWorkspaceFixture(db, { + id: workspaceId, + name: 'Read-only key fixture', + ownerId: userId, + billedAccountUserId: userId, + allowPersonalApiKeys: true, + }) + await db.insert(permissions).values({ + id: generateId(), + userId, + entityType: 'workspace', + entityId: workspaceId, + permissionType: 'admin', + }) + await db.insert(workflow).values({ + id: workflowId, + userId, + workspaceId, + name: 'Read-only key fixture', + lastSynced: now, + createdAt: now, + updatedAt: now, + }) + await db.insert(workflowMcpServer).values({ + id: mcpServerId, + workspaceId, + createdBy: userId, + name: 'Read-only key fixture', + }) + await db.insert(apiKey).values([ + { + id: generateId(), + userId, + name: 'Created before access levels', + key: legacyKey, + keyHash: hashApiKey(legacyKey), + type: 'personal', + }, + { + id: generateId(), + userId, + name: 'Expired', + key: expiredKey, + keyHash: hashApiKey(expiredKey), + type: 'personal', + expiresAt: new Date(Date.now() - 1000), + }, + ]) + authMockFns.mockGetSession.mockResolvedValue({ + user: { id: userId, name: 'Read-only key fixture', email: `${userId}@read-only-key.test` }, + session: { id: 'fixture-session' }, + }) + }) + + afterAll(async () => { + await deleteWorkspaceFixture(db, eq(workspace.id, workspaceId)) + await db.delete(user).where(eq(user.id, userId)) + await db.$client.end() + }) + + it('rejects an expiry outside one day to one year, and an unparseable one, without creating a key', async () => { + const before = await db.select({ id: apiKey.id }).from(apiKey).where(eq(apiKey.userId, userId)) + for (const expiresAt of [ + new Date(Date.now() + 60 * 60 * 1000).toISOString(), + new Date(Date.now() + 400 * DAY_MS).toISOString(), + new Date(Date.now() - DAY_MS).toISOString(), + 'next tuesday', + ]) { + const created = await call(createPersonalKey, '/api/users/me/api-keys', { + body: { name: `Bad expiry ${generateId()}`, access: 'read', expiresAt }, + }) + expect(created.status, expiresAt).toBe(400) + } + const invalidAccess = await call(createPersonalKey, '/api/users/me/api-keys', { + body: { name: `Bad access ${generateId()}`, access: 'admin' }, + }) + expect(invalidAccess.status).toBe(400) + const after = await db.select({ id: apiKey.id }).from(apiKey).where(eq(apiKey.userId, userId)) + expect(after).toHaveLength(before.length) + }) + + it('mints read-only personal and workspace keys that report their access and expiry', async () => { + const expiresAt = new Date(Date.now() + 30 * DAY_MS).toISOString() + const personal = await call(createPersonalKey, '/api/users/me/api-keys', { + body: { name: `Read personal ${generateId()}`, access: 'read', expiresAt }, + }) + expect(personal.status).toBe(200) + expect(personal.body).toMatchObject({ key: { access: 'read', expiresAt } }) + readPersonalKey = (personal.body as { key: { key: string } }).key.key + + const scoped = await call(createWorkspaceKey, `/api/workspaces/${workspaceId}/api-keys`, { + body: { name: `Read workspace ${generateId()}`, access: 'read', expiresAt: null }, + params: { id: workspaceId }, + }) + expect(scoped.status).toBe(200) + expect(scoped.body).toMatchObject({ key: { access: 'read', expiresAt: null } }) + readWorkspaceKey = (scoped.body as { key: { key: string } }).key.key + + for (const key of [readPersonalKey, readWorkspaceKey]) { + const meta = await call(v2Meta, '/api/v2/meta', { key }) + expect(meta.status).toBe(200) + expect(meta.body).toMatchObject({ data: { scopes: ['api:read'] } }) + } + const personalMeta = await call(v2Meta, '/api/v2/meta', { key: readPersonalKey }) + expect(personalMeta.body).toMatchObject({ data: { expiresAt } }) + }) + + it('keeps every read on v2, v1, and both MCP servers', async () => { + for (const key of [readPersonalKey, readWorkspaceKey]) { + const v2 = await call(v2ListTables, `/api/v2/tables?workspaceId=${workspaceId}`, { key }) + expect(v2.status).toBe(200) + + const v1 = await call(v1ListTables, `/api/v1/tables?workspaceId=${workspaceId}`, { key }) + expect(v1.status).toBe(200) + + const mcpRead = await call(simMcpPost, '/api/mcp', { + key, + headers: MCP_HEADERS, + body: mcpToolCall('call_read_operation', { + operation: 'listTables', + query: { workspaceId }, + }), + }) + expect(mcpRead.status).toBe(200) + expect(JSON.stringify(mcpRead.body)).not.toContain('READ_ONLY_API_KEY') + + const workflowMcpList = await call(workflowMcpPost, `/api/mcp/serve/${mcpServerId}`, { + key, + params: { serverId: mcpServerId }, + body: { jsonrpc: '2.0', id: 1, method: 'tools/list' }, + }) + expect(workflowMcpList.status).toBe(200) + } + + /** Search reads through POST, so the v1 write gate lets it through to the route's own checks. */ + const search = await call(v1KnowledgeSearch, '/api/v1/knowledge/search', { + key: readPersonalKey, + body: { workspaceId, knowledgeBaseIds: [generateId()], query: 'fixture' }, + }) + expect(JSON.stringify(search.body)).not.toContain('READ_ONLY_API_KEY') + }) + + it('refuses every write path with READ_ONLY_API_KEY and changes nothing', async () => { + const tablesBefore = await tableCount() + const runId = generateId() + + for (const key of [readPersonalKey, readWorkspaceKey]) { + const v2 = await call(v2CreateTable, '/api/v2/tables', { + key, + body: tableBody(`v2 ${generateId()}`), + }) + expect(v2.status).toBe(403) + expect(v2.body).toMatchObject({ + error: { code: 'FORBIDDEN', details: { code: 'READ_ONLY_API_KEY' } }, + }) + + const mcpWrite = await call(simMcpPost, '/api/mcp', { + key, + headers: MCP_HEADERS, + body: mcpToolCall('call_write_operation', { + operation: 'createTable', + body: tableBody(`mcp ${generateId()}`), + }), + }) + expect(mcpWrite.status).toBe(403) + expect(mcpWrite.body).toMatchObject({ error: { details: { code: 'READ_ONLY_API_KEY' } } }) + + const v1 = await call(v1CreateTable, '/api/v1/tables', { + key, + body: tableBody(`v1 ${generateId()}`), + }) + expect(v1.status).toBe(403) + expect(v1.body).toEqual({ + error: READ_ONLY_API_KEY_DENIED, + details: { code: 'READ_ONLY_API_KEY' }, + }) + + const execute = await call(legacyExecute, `/api/workflows/${workflowId}/execute`, { + key, + params: { id: workflowId }, + body: { input: {} }, + }) + expect(execute.status).toBe(403) + expect(execute.body).toMatchObject({ details: { code: 'READ_ONLY_API_KEY' } }) + + const toolCall = await call(workflowMcpPost, `/api/mcp/serve/${mcpServerId}`, { + key, + params: { serverId: mcpServerId }, + body: mcpToolCall('fixture_tool', {}), + }) + expect(toolCall.status).toBe(403) + expect(toolCall.body).toMatchObject({ error: { data: { code: 'READ_ONLY_API_KEY' } } }) + + const v2Resume = await call( + v2ResumeRun, + `/api/v2/workflows/${workflowId}/runs/${runId}/resume`, + { key, params: { workflowId, runId }, body: { input: {} } } + ) + expect(v2Resume.status).toBe(403) + expect(v2Resume.body).toMatchObject({ error: { details: { code: 'READ_ONLY_API_KEY' } } }) + + const v2Cancel = await call( + v2CancelRun, + `/api/v2/workflows/${workflowId}/runs/${runId}/cancel`, + { key, method: 'POST', params: { workflowId, runId } } + ) + expect(v2Cancel.status).toBe(403) + expect(v2Cancel.body).toMatchObject({ error: { details: { code: 'READ_ONLY_API_KEY' } } }) + + const internalCancel = await call( + internalCancelRun, + `/api/workflows/${workflowId}/executions/${runId}/cancel`, + { key, method: 'POST', params: { id: workflowId, executionId: runId } } + ) + expect(internalCancel.status).toBe(403) + expect(internalCancel.body).toMatchObject({ error: READ_ONLY_API_KEY_DENIED }) + + const resume = await call( + legacyResume, + `/api/resume/${workflowId}/${runId}/${generateId()}`, + { + key, + params: { workflowId, executionId: runId, contextId: generateId() }, + body: { input: {} }, + } + ) + expect(resume.status).toBe(403) + expect(resume.body).toMatchObject({ error: READ_ONLY_API_KEY_DENIED }) + } + + expect(await tableCount()).toBe(tablesBefore) + expect(await executionCount()).toBe(0) + }) + + it('treats a key created before access levels as full access', async () => { + const meta = await call(v2Meta, '/api/v2/meta', { key: legacyKey }) + expect(meta.body).toMatchObject({ + data: { scopes: ['api:read', 'api:write'], expiresAt: null }, + }) + + const tablesBefore = await tableCount() + const created = await call(v2CreateTable, '/api/v2/tables', { + key: legacyKey, + body: tableBody(`legacy ${generateId()}`), + }) + expect(created.status).toBe(200) + expect(await tableCount()).toBe(tablesBefore + 1) + }) + + it('answers an expired key with an expiry message on v2 and v1', async () => { + const v2 = await call(v2Meta, '/api/v2/meta', { key: expiredKey }) + expect(v2.status).toBe(401) + expect(v2.body).toMatchObject({ error: { message: 'API key has expired' } }) + + const v1 = await call(v1ListTables, `/api/v1/tables?workspaceId=${workspaceId}`, { + key: expiredKey, + }) + expect(v1.status).toBe(401) + expect(v1.body).toEqual({ error: 'API key has expired' }) + }) +}) diff --git a/apps/sim/lib/api-key/application/personal-api-keys.ts b/apps/sim/lib/api-key/application/personal-api-keys.ts index 21f3fa76bfd..224e97ce007 100644 --- a/apps/sim/lib/api-key/application/personal-api-keys.ts +++ b/apps/sim/lib/api-key/application/personal-api-keys.ts @@ -1,5 +1,9 @@ import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit' -import { type Principal, resolvePrincipalAuditAttribution } from '@sim/auth/principal' +import { + type ApiKeyAccess, + type Principal, + resolvePrincipalAuditAttribution, +} from '@sim/auth/principal' import { db } from '@sim/db' import { apiKey, user } from '@sim/db/schema' import { and, eq } from 'drizzle-orm' @@ -46,6 +50,7 @@ async function authorizePersonalKeys(principal: Principal, operation: UserAccoun interface PersonalApiKeyMetadata { id: string name: string + access: ApiKeyAccess createdAt: Date lastUsed: Date | null expiresAt: Date | null @@ -65,6 +70,7 @@ export const listPersonalApiKeys: OperationUseCase< .select({ id: apiKey.id, name: apiKey.name, + access: apiKey.access, key: apiKey.key, createdAt: apiKey.createdAt, lastUsed: apiKey.lastUsed, diff --git a/apps/sim/lib/api-key/application/workspace-api-keys.ts b/apps/sim/lib/api-key/application/workspace-api-keys.ts index 030757400cd..3c408c42deb 100644 --- a/apps/sim/lib/api-key/application/workspace-api-keys.ts +++ b/apps/sim/lib/api-key/application/workspace-api-keys.ts @@ -66,6 +66,7 @@ export const listWorkspaceApiKeys = defineAuthorizedWorkspaceUseCase({ .select({ id: apiKey.id, name: apiKey.name, + access: apiKey.access, key: apiKey.key, createdAt: apiKey.createdAt, lastUsed: apiKey.lastUsed, @@ -116,6 +117,7 @@ export const renameWorkspaceApiKey = defineAuthorizedWorkspaceUseCase({ .returning({ id: apiKey.id, name: apiKey.name, + access: apiKey.access, createdAt: apiKey.createdAt, updatedAt: apiKey.updatedAt, }) diff --git a/apps/sim/lib/api-key/auth.ts b/apps/sim/lib/api-key/auth.ts index 99009d27736..88999f7e93c 100644 --- a/apps/sim/lib/api-key/auth.ts +++ b/apps/sim/lib/api-key/auth.ts @@ -1,3 +1,4 @@ +import type { ApiKeyAccess } from '@sim/auth/principal' import { db } from '@sim/db' import { apiKey } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -140,6 +141,8 @@ export async function createWorkspaceApiKey(params: { workspaceId: string userId: string name: string + access: ApiKeyAccess + expiresAt: Date | null }) { const existingKey = await db .select({ id: apiKey.id }) @@ -175,10 +178,18 @@ export async function createWorkspaceApiKey(params: { key: encryptedKey, keyHash: hashApiKey(plainKey), type: 'workspace', + access: params.access, + expiresAt: params.expiresAt, createdAt: new Date(), updatedAt: new Date(), }) - .returning({ id: apiKey.id, name: apiKey.name, createdAt: apiKey.createdAt }) + .returning({ + id: apiKey.id, + name: apiKey.name, + access: apiKey.access, + createdAt: apiKey.createdAt, + expiresAt: apiKey.expiresAt, + }) - return { id: newKey.id, name: newKey.name, key: plainKey, createdAt: newKey.createdAt } + return { ...newKey, key: plainKey } } diff --git a/apps/sim/lib/api-key/orchestration/index.ts b/apps/sim/lib/api-key/orchestration/index.ts index fe7d2e40948..5cd9233b9ce 100644 --- a/apps/sim/lib/api-key/orchestration/index.ts +++ b/apps/sim/lib/api-key/orchestration/index.ts @@ -1,4 +1,5 @@ import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit' +import type { ApiKeyAccess } from '@sim/auth/principal' import { db } from '@sim/db' import { apiKey } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -11,16 +12,59 @@ import { PlatformEvents } from '@/lib/core/telemetry' const logger = createLogger('ApiKeyOrchestration') -export type ApiKeyOrchestrationErrorCode = 'conflict' | 'internal' +export type ApiKeyOrchestrationErrorCode = 'validation' | 'conflict' | 'internal' export interface CreatedApiKey { id: string name: string key: string + access: ApiKeyAccess createdAt: Date + expiresAt: Date | null } -export interface PerformCreateWorkspaceApiKeyParams { +/** The HTTP status a failed key creation answers with. */ +export function apiKeyCreationErrorStatus(code: ApiKeyOrchestrationErrorCode | undefined): number { + if (code === 'validation') return 400 + if (code === 'conflict') return 409 + return 500 +} + +const DAY_MS = 24 * 60 * 60 * 1000 +/** The shortest lifetime a key may be created with. */ +const MIN_API_KEY_LIFETIME_MS = DAY_MS +/** The longest lifetime a key may be created with: a year, with a day of slack for time zones. */ +const MAX_API_KEY_LIFETIME_MS = 366 * DAY_MS + +/** + * The settings every key is issued with. Both default to a key that has always + * existed: full access, never expiring. + */ +interface ApiKeyIssueSettings { + access?: ApiKeyAccess + /** ISO 8601 timestamp, or `null`/absent for a key that never expires. */ + expiresAt?: string | null +} + +type ResolvedExpiry = { ok: true; expiresAt: Date | null } | { ok: false; error: string } + +function resolveApiKeyExpiry(expiresAt: string | null | undefined): ResolvedExpiry { + if (expiresAt === null || expiresAt === undefined) return { ok: true, expiresAt: null } + const date = new Date(expiresAt) + const lifetimeMs = date.getTime() - Date.now() + if (!Number.isFinite(lifetimeMs)) { + return { ok: false, error: 'Expiration must be a valid date' } + } + if (lifetimeMs < MIN_API_KEY_LIFETIME_MS) { + return { ok: false, error: 'Expiration must be at least one day from now' } + } + if (lifetimeMs > MAX_API_KEY_LIFETIME_MS) { + return { ok: false, error: 'Expiration must be within one year' } + } + return { ok: true, expiresAt: date } +} + +export interface PerformCreateWorkspaceApiKeyParams extends ApiKeyIssueSettings { workspaceId: string userId: string name: string @@ -38,7 +82,7 @@ export interface PerformCreateWorkspaceApiKeyResult { key?: CreatedApiKey } -export interface PerformCreatePersonalApiKeyParams { +export interface PerformCreatePersonalApiKeyParams extends ApiKeyIssueSettings { userId: string name: string source?: string @@ -66,6 +110,9 @@ export interface PerformCreatePersonalApiKeyResult { export async function performCreatePersonalApiKey( params: PerformCreatePersonalApiKeyParams ): Promise { + const expiry = resolveApiKeyExpiry(params.expiresAt) + if (!expiry.ok) return { success: false, errorCode: 'validation', error: expiry.error } + const access = params.access ?? 'write' try { const existing = await db .select({ id: apiKey.id }) @@ -102,13 +149,17 @@ export async function performCreatePersonalApiKey( key: encryptedKey, keyHash: hashApiKey(plainKey), type: 'personal', + access, + expiresAt: expiry.expiresAt, createdAt: new Date(), updatedAt: new Date(), }) .returning({ id: apiKey.id, name: apiKey.name, + access: apiKey.access, createdAt: apiKey.createdAt, + expiresAt: apiKey.expiresAt, }) recordAudit({ @@ -124,6 +175,8 @@ export async function performCreatePersonalApiKey( metadata: { keyName: params.name, keyType: 'personal', + access, + expiresAt: expiry.expiresAt?.toISOString() ?? null, source: params.source ?? 'settings', }, request: params.request, @@ -141,11 +194,16 @@ export async function performCreatePersonalApiKey( export async function performCreateWorkspaceApiKey( params: PerformCreateWorkspaceApiKeyParams ): Promise { + const expiry = resolveApiKeyExpiry(params.expiresAt) + if (!expiry.ok) return { success: false, errorCode: 'validation', error: expiry.error } + const access = params.access ?? 'write' try { const key = await createWorkspaceApiKey({ workspaceId: params.workspaceId, userId: params.userId, name: params.name, + access, + expiresAt: expiry.expiresAt, }) if (params.captureAnalytics !== false) { @@ -177,6 +235,8 @@ export async function performCreateWorkspaceApiKey( metadata: { keyName: params.name, keyType: 'workspace', + access, + expiresAt: expiry.expiresAt?.toISOString() ?? null, source: params.source ?? 'settings', }, }) diff --git a/apps/sim/lib/api-key/policy-messages.ts b/apps/sim/lib/api-key/policy-messages.ts index af106780ecd..e7eb3837a52 100644 --- a/apps/sim/lib/api-key/policy-messages.ts +++ b/apps/sim/lib/api-key/policy-messages.ts @@ -1,8 +1,15 @@ /** - * Shared 403 messages so surfaces gating on API-key workspace scope or - * `workspace.allowPersonalApiKeys` reject with identical wording. + * Shared 403 messages so surfaces gating on API-key workspace scope, + * `workspace.allowPersonalApiKeys`, or a key's read-only access reject with + * identical wording. */ export const WORKSPACE_KEY_SCOPE_DENIED = 'API key is not authorized for this workspace' export const PERSONAL_KEY_DENIED = 'Personal API keys are not allowed for this workspace' + +/** The 401 an expired key answers with, so its holder knows to replace it rather than recheck it. */ +export const API_KEY_EXPIRED = 'API key has expired' + +export const READ_ONLY_API_KEY_DENIED = + 'This API key is read-only and cannot perform this operation' diff --git a/apps/sim/lib/api-key/service.ts b/apps/sim/lib/api-key/service.ts index 8dbe94cf520..5b09f5dfb07 100644 --- a/apps/sim/lib/api-key/service.ts +++ b/apps/sim/lib/api-key/service.ts @@ -1,8 +1,10 @@ +import type { ApiKeyAccess } from '@sim/auth/principal' import { db } from '@sim/db' import { apiKey as apiKeyTable, user as userTable } from '@sim/db/schema' import { createLogger, setRequestAuth } from '@sim/logger' import { and, eq, isNull, lt, or } from 'drizzle-orm' import { hashApiKey } from '@/lib/api-key/crypto' +import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' import { getAuthPool } from '@/lib/auth/database-context' import { createDetachedTouch } from '@/lib/core/utils/background' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' @@ -21,6 +23,7 @@ export interface ApiKeyAuthResult { userId?: string keyId?: string keyType?: 'personal' | 'workspace' + access?: ApiKeyAccess workspaceId?: string error?: string } @@ -32,6 +35,7 @@ interface HashCandidate { userId: string workspaceId: string | null type: string + access: ApiKeyAccess expiresAt: Date | null userBanned: boolean | null userSuspendedAt: Date | null @@ -41,8 +45,8 @@ interface HashCandidate { * Authenticate an API key from header with flexible filtering options. * * Looks up a single row by `sha256(apiKeyHeader)` and applies the scope / - * expiry / permission gates. Any miss — no matching hash or a failed gate — - * returns `INVALID`. + * expiry / permission gates. An expired key reports {@link API_KEY_EXPIRED}; + * any other miss — no matching hash or a failed gate — returns `INVALID`. */ export async function authenticateApiKeyFromHeader( apiKeyHeader: string, @@ -69,6 +73,7 @@ export async function authenticateApiKeyFromHeader( userId: apiKeyTable.userId, workspaceId: apiKeyTable.workspaceId, type: apiKeyTable.type, + access: apiKeyTable.access, expiresAt: apiKeyTable.expiresAt, userBanned: userTable.banned, userSuspendedAt: userTable.suspendedAt, @@ -95,7 +100,9 @@ export async function authenticateApiKeyFromHeader( if (options.userId && record.userId !== options.userId) return INVALID if (options.keyTypes?.length && !options.keyTypes.includes(keyType)) return INVALID - if (record.expiresAt && record.expiresAt < new Date()) return INVALID + if (record.expiresAt && record.expiresAt < new Date()) { + return { success: false, error: API_KEY_EXPIRED } + } if ( options.workspaceId && @@ -128,6 +135,7 @@ export async function authenticateApiKeyFromHeader( userId: record.userId, keyId: record.id, keyType, + access: record.access, workspaceId: record.workspaceId || options.workspaceId || undefined, } } catch (error) { diff --git a/apps/sim/lib/api/application/read-v2-api-capabilities.ts b/apps/sim/lib/api/application/read-v2-api-capabilities.ts index 97e2df8d8c6..11239f862e7 100644 --- a/apps/sim/lib/api/application/read-v2-api-capabilities.ts +++ b/apps/sim/lib/api/application/read-v2-api-capabilities.ts @@ -1,6 +1,11 @@ import { v2MetaOperations } from '@/lib/api/application/operations' import type { V2ApiKeyType } from '@/lib/api/contracts/v2/meta' -import { assertOperationPrincipal, type OperationUseCase } from '@/lib/core/application' +import type { OAuthApiScope } from '@/lib/auth/oauth-provider' +import { + assertOperationPrincipal, + credentialApiScopes, + type OperationUseCase, +} from '@/lib/core/application' /** * The credential facts the authenticating adapter has already established. @@ -18,6 +23,7 @@ export interface ReadV2ApiCapabilitiesResult { v2Enabled: boolean keyType: V2ApiKeyType expiresAt: Date | null + scopes: OAuthApiScope[] } /** @@ -39,6 +45,7 @@ export const readV2ApiCapabilities: OperationUseCase< v2Enabled: true, keyType: input.keyType, expiresAt: input.expiresAt, + scopes: credentialApiScopes(principal), } }, } diff --git a/apps/sim/lib/api/contracts/api-keys.ts b/apps/sim/lib/api/contracts/api-keys.ts index f80adfbd07f..21608de3e40 100644 --- a/apps/sim/lib/api/contracts/api-keys.ts +++ b/apps/sim/lib/api/contracts/api-keys.ts @@ -1,9 +1,13 @@ import { z } from 'zod' import { defineRouteContract } from '@/lib/api/contracts/types' +const apiKeyAccessSchema = z.enum(['read', 'write']) +export type ApiKeyAccessLevel = z.output + const apiKeyMetadataSchema = z.object({ id: z.string(), name: z.string(), + access: apiKeyAccessSchema, lastUsed: z.string().nullable().optional(), createdAt: z.string(), expiresAt: z.string().nullable().optional(), @@ -22,12 +26,25 @@ export const apiKeySchema = apiKeyMetadataSchema.extend({ export type ApiKey = z.output export type CreatedApiKey = z.output +/** + * A creation-time expiry, or `null` (and absent) for a key that never expires. + * The window it must fall in is enforced where the key is created, against the + * server's clock. + */ +const apiKeyExpiresAtInputSchema = z.iso.datetime({ offset: true }).nullable().optional() + export const createApiKeyBodySchema = z.object({ name: z.string().trim().min(1, 'Name is required'), source: z.enum(['settings', 'deploy_modal']).optional(), + access: apiKeyAccessSchema.default('write'), + expiresAt: apiKeyExpiresAtInputSchema, }) -export const createPersonalApiKeyBodySchema = createApiKeyBodySchema.pick({ name: true }) +export const createPersonalApiKeyBodySchema = createApiKeyBodySchema.pick({ + name: true, + access: true, + expiresAt: true, +}) export const apiKeyIdParamsSchema = z.object({ id: z.string({ error: 'API key ID is required' }).min(1, 'API key ID is required'), diff --git a/apps/sim/lib/api/contracts/v2/meta.ts b/apps/sim/lib/api/contracts/v2/meta.ts index 1d8c83df377..4e82909e20b 100644 --- a/apps/sim/lib/api/contracts/v2/meta.ts +++ b/apps/sim/lib/api/contracts/v2/meta.ts @@ -22,6 +22,11 @@ export const v2MetaSchema = z .describe( 'ISO 8601 timestamp when the calling credential expires, or null when it does not.' ), + scopes: z + .array(z.enum(['api:read', 'api:write', 'search:read'])) + .describe( + 'API scopes the calling credential holds. A read-only API key holds only api:read and is refused every operation that changes state; a full-access key holds api:read and api:write; an OAuth access token holds what it was granted.' + ), }) .meta({ id: 'V2Meta', diff --git a/apps/sim/lib/api/contracts/v2/openapi/resources.ts b/apps/sim/lib/api/contracts/v2/openapi/resources.ts index b8416de9b3a..c295f8d33b2 100644 --- a/apps/sim/lib/api/contracts/v2/openapi/resources.ts +++ b/apps/sim/lib/api/contracts/v2/openapi/resources.ts @@ -1855,7 +1855,7 @@ const declaredRoutes = [ operationId: 'getApiMeta', summary: 'Get API status', description: - 'Get the calling credential’s type and expiry. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.', + 'Get the calling credential’s type, expiry, and API scopes. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.', errors: META_ERRORS, success: { description: 'Availability and lifecycle facts about the calling credential.' }, }), @@ -1865,8 +1865,17 @@ const declaredRoutes = [ v2GetMetaContract.response.schema, 'GetApiMetaResponse', 'API status response', - 'API availability, credential type, and expiry for the caller.', - [{ data: { v2Enabled: true, keyType: 'personal', expiresAt: null } }] + 'API availability, credential type, expiry, and scopes for the caller.', + [ + { + data: { + v2Enabled: true, + keyType: 'personal', + expiresAt: null, + scopes: ['api:read', 'api:write'], + }, + }, + ] ), } ), diff --git a/apps/sim/lib/api/mcp/generated/v2-operations.ts b/apps/sim/lib/api/mcp/generated/v2-operations.ts index e21082c9268..0f2ad676008 100644 --- a/apps/sim/lib/api/mcp/generated/v2-operations.ts +++ b/apps/sim/lib/api/mcp/generated/v2-operations.ts @@ -1402,7 +1402,7 @@ export const V2_MCP_OPERATIONS = { contract: v2GetMetaContract, summary: 'Get API status', description: - 'Get the calling credential’s type and expiry. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.\n\nOAuth scope: `api:read`.', + 'Get the calling credential’s type, expiry, and API scopes. Requires a valid API key or OAuth access token. `v2Enabled` is true whenever this endpoint is served; the response does not enumerate resource permissions.\n\nOAuth scope: `api:read`.', handler: () => import('@/app/api/v2/meta/route').then((route) => route.GET), }, getNextKnowledgeTagSlot: { diff --git a/apps/sim/lib/api/mcp/route-handler.test.ts b/apps/sim/lib/api/mcp/route-handler.test.ts index 6b5c3f9c68b..061a166518d 100644 --- a/apps/sim/lib/api/mcp/route-handler.test.ts +++ b/apps/sim/lib/api/mcp/route-handler.test.ts @@ -19,7 +19,12 @@ const BASE = getBaseUrl() const handlers = createSimMcpHandlers() const auth = { - principal: { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1' }, + principal: { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-1', + access: 'write' as const, + }, rateLimitSubjectIds: ['api-key:key-1', 'user:user-1'] as const, rateLimitSubscription: null, keyType: 'personal' as const, @@ -93,7 +98,12 @@ describe('Sim MCP tools', () => { const result = await callTool('call_read_operation', { operation: 'getMeta' }) expect(result.isError).toBeFalsy() expect(JSON.parse(result.content[0].text)).toEqual({ - data: { v2Enabled: true, keyType: 'personal', expiresAt: null }, + data: { + v2Enabled: true, + keyType: 'personal', + expiresAt: null, + scopes: ['api:read', 'api:write'], + }, }) expect(v2RouteMocks.authenticate).toHaveBeenCalledTimes(2) expect(v2RouteMocks.authenticate).toHaveBeenLastCalledWith( diff --git a/apps/sim/lib/api/server/routes/v2-api-key-auth.test.ts b/apps/sim/lib/api/server/routes/v2-api-key-auth.test.ts index 643fa55a99d..6c9c46daaa2 100644 --- a/apps/sim/lib/api/server/routes/v2-api-key-auth.test.ts +++ b/apps/sim/lib/api/server/routes/v2-api-key-auth.test.ts @@ -54,6 +54,7 @@ describe('v2 API key authentication', () => { userId: 'user-1', workspaceId: null, type: 'personal', + access: 'write', expiresAt: null, userBanned: false, }, @@ -85,6 +86,7 @@ describe('v2 API key authentication', () => { userId: 'user-1', workspaceId: null, type: 'personal', + access: 'write', expiresAt: new Date('2027-01-01T00:00:00.000Z'), userBanned: false, }, @@ -102,6 +104,7 @@ describe('v2 API key authentication', () => { userId: 'creator-1', workspaceId: 'workspace-1', type: 'workspace', + access: 'write', expiresAt: null, userBanned: false, }, @@ -134,6 +137,7 @@ describe('v2 API key authentication', () => { userId: 'creator-1', workspaceId: 'workspace-1', type: 'workspace', + access: 'write', expiresAt: null, userBanned: true, }, @@ -170,6 +174,7 @@ describe('v2 API key authentication', () => { userId: 'user-1', workspaceId: null, type: 'personal', + access: 'write', expiresAt: null, userBanned: true, }, @@ -184,6 +189,7 @@ describe('v2 API key authentication', () => { userId: 'user-1', workspaceId: null, type: 'personal', + access: 'write', expiresAt: new Date(Date.now() - 1), userBanned: false, }, @@ -289,6 +295,7 @@ describe('v2 bearer token authentication', () => { userId: 'user-1', workspaceId: null, type: 'personal', + access: 'write', expiresAt: null, userBanned: false, }, @@ -344,7 +351,7 @@ describe('v2 bearer token authentication', () => { await expect( authenticateV2ApiKey({ apiKey: null, bearer: 'sim_oat_unused' }) ).resolves.toMatchObject({ - principal: { kind: 'personal_api_key', keyId: 'auth-disabled' }, + principal: { kind: 'personal_api_key', keyId: 'auth-disabled', access: 'write' }, keyType: 'personal', }) expect(dbChainMockFns.limit).not.toHaveBeenCalled() diff --git a/apps/sim/lib/api/server/routes/v2-api-key-auth.ts b/apps/sim/lib/api/server/routes/v2-api-key-auth.ts index 655700d71b5..26cf238c084 100644 --- a/apps/sim/lib/api/server/routes/v2-api-key-auth.ts +++ b/apps/sim/lib/api/server/routes/v2-api-key-auth.ts @@ -1,5 +1,6 @@ import { ANONYMOUS_USER_ID, + type ApiKeyAccess, type OAuthAccessTokenPrincipal, type PersonalApiKeyPrincipal, type WorkspaceApiKeyPrincipal, @@ -10,6 +11,7 @@ import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' import type { V2CredentialHeaders } from '@/lib/api/server/routes/v2-credential-headers' import { hashApiKey } from '@/lib/api-key/crypto' +import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' import { updateApiKeyLastUsed } from '@/lib/api-key/service' import { InvalidOAuthAccessTokenError, @@ -73,14 +75,16 @@ interface ApiKeyRow { userId: string workspaceId: string | null type: string + access: ApiKeyAccess expiresAt: Date | null userBanned: boolean | null userSuspendedAt: Date | null } function requireValidRow(row: ApiKeyRow | undefined): ApiKeyRow { - if (!row || (row.expiresAt && row.expiresAt < new Date())) { - throw new V2ApiKeyUnauthenticatedError() + if (!row) throw new V2ApiKeyUnauthenticatedError() + if (row.expiresAt && row.expiresAt < new Date()) { + throw new V2ApiKeyUnauthenticatedError(API_KEY_EXPIRED) } if (row.type === 'personal' && row.workspaceId === null) { if (row.userBanned === null) { @@ -110,6 +114,7 @@ async function authenticateApiKey(apiKeyHeader: string): Promise { v2RouteMocks.authenticate.mockImplementation(async () => { mocks.order.push('authenticate') return { - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, rateLimitSubjectIds: ['api-key:key-1', 'user:user-1'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/lib/api/server/routes/v2-json-route.test.ts b/apps/sim/lib/api/server/routes/v2-json-route.test.ts index b58799290af..1b896171485 100644 --- a/apps/sim/lib/api/server/routes/v2-json-route.test.ts +++ b/apps/sim/lib/api/server/routes/v2-json-route.test.ts @@ -42,6 +42,7 @@ const principal: PersonalApiKeyPrincipal = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', + access: 'write', } const auth = { principal, diff --git a/apps/sim/lib/api/server/routes/v2-json-route.ts b/apps/sim/lib/api/server/routes/v2-json-route.ts index ffab2e745f6..be2251f91d2 100644 --- a/apps/sim/lib/api/server/routes/v2-json-route.ts +++ b/apps/sim/lib/api/server/routes/v2-json-route.ts @@ -40,6 +40,7 @@ import { InsufficientScopeError, OAuthAccessTokenExpiredError, type OperationUseCase, + ReadOnlyApiKeyError, requireOAuthOperationScope, } from '@/lib/core/application' import { getRateLimit, RateLimiter, type SubscriptionPlan } from '@/lib/core/rate-limiter' @@ -357,7 +358,11 @@ async function admitAuthenticatedV2Request( try { requireOAuthOperationScope(auth.principal, operation) } catch (error) { - if (error instanceof InsufficientScopeError || error instanceof OAuthAccessTokenExpiredError) { + if ( + error instanceof InsufficientScopeError || + error instanceof ReadOnlyApiKeyError || + error instanceof OAuthAccessTokenExpiredError + ) { const response = v2CaughtOrchestrationError(error) if (response) return { success: false, response } } diff --git a/apps/sim/lib/auth/hybrid.test.ts b/apps/sim/lib/auth/hybrid.test.ts index c80887663d1..81a48d8d5a2 100644 --- a/apps/sim/lib/auth/hybrid.test.ts +++ b/apps/sim/lib/auth/hybrid.test.ts @@ -46,6 +46,7 @@ describe('checkHybridAuth credential precedence', () => { userId: 'api-user', keyId: 'key-1', keyType: 'personal', + access: 'write', }) const result = await checkHybridAuth( @@ -58,7 +59,7 @@ describe('checkHybridAuth credential precedence', () => { workspaceId: undefined, authType: AuthType.API_KEY, apiKeyType: 'personal', - principal: { kind: 'personal_api_key', userId: 'api-user', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'api-user', keyId: 'key-1', access: 'write' }, }) expect(mockUpdateApiKeyLastUsed).toHaveBeenCalledWith('key-1') expect(mockGetSession).not.toHaveBeenCalled() @@ -100,6 +101,7 @@ describe('checkHybridAuth credential precedence', () => { userId: 'api-user', keyId: 'key-1', keyType: 'personal', + access: 'write', }) const result = await checkHybridAuth( diff --git a/apps/sim/lib/auth/hybrid.ts b/apps/sim/lib/auth/hybrid.ts index 45ecfd011a6..a450850395e 100644 --- a/apps/sim/lib/auth/hybrid.ts +++ b/apps/sim/lib/auth/hybrid.ts @@ -2,6 +2,7 @@ import type { WorkflowExecutionPrincipal } from '@sim/auth/principal' import { createLogger } from '@sim/logger' import type { NextRequest } from 'next/server' import { API_KEY_HEADER, BEARER_PREFIX } from '@/lib/api/server/credential-headers' +import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' import { authenticateApiKeyFromHeader, updateApiKeyLastUsed } from '@/lib/api-key/service' import { getSession } from '@/lib/auth' import { type InternalSandboxProfile, verifyInternalToken } from '@/lib/auth/internal' @@ -214,12 +215,17 @@ export async function checkHybridAuth( const apiKeyHeader = request.headers.get(API_KEY_HEADER) ?? '' const result = await authenticateApiKeyFromHeader(apiKeyHeader) if (result.success) { - if (!result.keyId || !result.keyType || !result.userId) { + if (!result.keyId || !result.keyType || !result.userId || !result.access) { throw new Error('API key authentication returned incomplete identity') } let principal: WorkflowExecutionPrincipal if (result.keyType === 'personal') { - principal = { kind: 'personal_api_key', userId: result.userId, keyId: result.keyId } + principal = { + kind: 'personal_api_key', + userId: result.userId, + keyId: result.keyId, + access: result.access, + } } else { if (!result.workspaceId) { throw new Error('Workspace API key authentication returned no workspace scope') @@ -228,6 +234,7 @@ export async function checkHybridAuth( kind: 'workspace_api_key', workspaceId: result.workspaceId, keyId: result.keyId, + access: result.access, } } updateApiKeyLastUsed(result.keyId) @@ -243,7 +250,7 @@ export async function checkHybridAuth( return { success: false, - error: 'Invalid API key', + error: result.error === API_KEY_EXPIRED ? API_KEY_EXPIRED : 'Invalid API key', } } diff --git a/apps/sim/lib/auth/internal.test.ts b/apps/sim/lib/auth/internal.test.ts index a1136f0617a..6c47228dd6f 100644 --- a/apps/sim/lib/auth/internal.test.ts +++ b/apps/sim/lib/auth/internal.test.ts @@ -133,6 +133,7 @@ describe('internal executor delegation claims', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }, }) @@ -144,6 +145,7 @@ describe('internal executor delegation claims', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }, }) expect(decodeJwt(token).sub).toBeUndefined() @@ -257,6 +259,7 @@ describe('internal executor delegation claims', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }, }) ).rejects.toThrow('Actorless workflow principals cannot be represented as Sim users') diff --git a/apps/sim/lib/auth/principal.test.ts b/apps/sim/lib/auth/principal.test.ts index 18a30ffef75..791592f61b9 100644 --- a/apps/sim/lib/auth/principal.test.ts +++ b/apps/sim/lib/auth/principal.test.ts @@ -49,6 +49,7 @@ describe('principal subject users', () => { kind: 'personal_api_key', userId: 'key-user', keyId: 'key-1', + access: 'write', }) ).toBe('key-user') expect( @@ -124,6 +125,7 @@ describe('principal subject users', () => { resolvePrincipalSubjectUserId({ kind: 'workspace_api_key', keyId: 'key-1', + access: 'write', workspaceId: 'workspace-1', }) ).toBeUndefined() @@ -177,6 +179,7 @@ describe('principal subject users', () => { requirePrincipalSubjectUserId({ kind: 'workspace_api_key', keyId: 'key-1', + access: 'write', workspaceId: 'workspace-1', }) ).toThrow(PrincipalSubjectUserRequiredError) @@ -227,6 +230,43 @@ describe('principal persistence', () => { expect(restored.kind === 'delegated' && restored.issuedAt).toBeInstanceOf(Date) }) + /** + * A queued run is parsed by whichever deployment dequeues it, so a write key + * must keep the shape an older parser accepts, and a principal written before + * keys had an access level must come back as the full-access key it was. + */ + it('keeps API-key access across deploys without widening a read key', () => { + const writeKey = { + kind: 'workspace_api_key' as const, + workspaceId: 'workspace-1', + keyId: 'key-1', + access: 'write' as const, + } + const readKey = { + kind: 'personal_api_key' as const, + userId: 'user-1', + keyId: 'key-2', + access: 'read' as const, + } + + expect(serializePrincipal(writeKey).principal).not.toHaveProperty('access') + expect(parsePrincipal(structuredClone(serializePrincipal(writeKey)))).toEqual(writeKey) + expect(serializePrincipal(readKey).principal).toMatchObject({ access: 'read' }) + expect(parsePrincipal(structuredClone(serializePrincipal(readKey)))).toEqual(readKey) + expect( + parsePrincipal({ + version: 1, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-3' }, + }) + ).toEqual({ kind: 'personal_api_key', userId: 'user-1', keyId: 'key-3', access: 'write' }) + expect(() => + parsePrincipal({ + version: 1, + principal: { ...readKey, access: 'admin' }, + }) + ).toThrow('access must be read or write') + }) + it('rejects unknown versions, fields, and invalid dates', () => { expect(() => parsePrincipal({ @@ -453,6 +493,7 @@ describe('principal actors', () => { resolvePrincipalAuditAttribution({ kind: 'workspace_api_key', keyId: 'key-1', + access: 'write', workspaceId: 'workspace-1', }) ).toEqual({ @@ -484,7 +525,12 @@ describe('principal actors', () => { it('projects principals into their shared actor identity', () => { expect( - toPrincipalActor({ kind: 'personal_api_key', keyId: 'key-1', userId: 'user-1' }) + toPrincipalActor({ + kind: 'personal_api_key', + keyId: 'key-1', + access: 'write', + userId: 'user-1', + }) ).toEqual({ kind: 'personal_api_key', keyId: 'key-1', userId: 'user-1' }) expect( @@ -509,7 +555,7 @@ describe('principal actors', () => { it('uses the workspace billing owner for workspace-key attribution', () => { expect( resolvePrincipalAttribution( - { kind: 'workspace_api_key', keyId: 'key-1', workspaceId: 'workspace-1' }, + { kind: 'workspace_api_key', keyId: 'key-1', access: 'write', workspaceId: 'workspace-1' }, { workspaceBillingOwnerUserId: 'billing-owner-1' } ) ).toEqual({ @@ -526,6 +572,7 @@ describe('principal actors', () => { resolvePrincipalAttribution({ kind: 'personal_api_key', keyId: 'key-1', + access: 'write', userId: 'user-2', }) ).toMatchObject({ attributedUserId: 'user-2' }) @@ -588,6 +635,7 @@ describe('principal actors', () => { resolvePrincipalAttribution({ kind: 'workspace_api_key', keyId: 'key-1', + access: 'write', workspaceId: 'workspace-1', }) ).toThrow('Workspace API key attribution requires a workspace billing owner') diff --git a/apps/sim/lib/auth/sso/application/admit-sso-user.test.ts b/apps/sim/lib/auth/sso/application/admit-sso-user.test.ts index 5c36560532e..7893605d08a 100644 --- a/apps/sim/lib/auth/sso/application/admit-sso-user.test.ts +++ b/apps/sim/lib/auth/sso/application/admit-sso-user.test.ts @@ -383,6 +383,7 @@ describe('SSO JIT admission', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }, input: { providerId: 'acme-sso' }, }) diff --git a/apps/sim/lib/auth/sso/application/provider-settings.integration.ts b/apps/sim/lib/auth/sso/application/provider-settings.integration.ts index 024cce689d5..56e51123614 100644 --- a/apps/sim/lib/auth/sso/application/provider-settings.integration.ts +++ b/apps/sim/lib/auth/sso/application/provider-settings.integration.ts @@ -29,7 +29,12 @@ describe('Organization SSO administration through API credentials', () => { const domain = `sso-${suffix}.test` const providerId = `saml-${suffix}` const apiKeyValue = `sk-sim-${generateId()}` - const principal = { kind: 'personal_api_key' as const, userId, keyId: generateId() } + const principal = { + kind: 'personal_api_key' as const, + userId, + keyId: generateId(), + access: 'write' as const, + } let runtime: Awaited> async function loadRuntime() { @@ -1079,7 +1084,12 @@ describe('Organization SSO administration through API credentials', () => { const input = { ...config(), organizationId: generateId() } await expect( runtime.saveSsoProvider.execute({ - principal: { kind: 'workspace_api_key', keyId: generateId(), workspaceId: generateId() }, + principal: { + kind: 'workspace_api_key', + keyId: generateId(), + access: 'write', + workspaceId: generateId(), + }, input, }) ).rejects.toMatchObject({ detailCode: 'PRINCIPAL_KIND_NOT_PERMITTED' }) diff --git a/apps/sim/lib/computer-use/application/authorize.test.ts b/apps/sim/lib/computer-use/application/authorize.test.ts index 1716040894a..b4549ca00b4 100644 --- a/apps/sim/lib/computer-use/application/authorize.test.ts +++ b/apps/sim/lib/computer-use/application/authorize.test.ts @@ -75,7 +75,7 @@ describe('native computer authorization', () => { it('rejects non-session principals before protected loading', async () => { await expect( authorizeComputerUse.execute({ - principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + principal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, input, }) ).rejects.toThrow() diff --git a/apps/sim/lib/core/application/audit-source.test.ts b/apps/sim/lib/core/application/audit-source.test.ts index 6a5b0c9e6d2..f87de3d394f 100644 --- a/apps/sim/lib/core/application/audit-source.test.ts +++ b/apps/sim/lib/core/application/audit-source.test.ts @@ -19,9 +19,12 @@ describe('principalAuditSource', () => { it.each([ [{ kind: 'session', userId: 'user-1', sessionId: 'session-1' }, 'session'], - [{ kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, 'personal_api_key'], [ - { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1' }, + { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', access: 'write' }, + 'personal_api_key', + ], + [ + { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', access: 'write' }, 'workspace_api_key', ], ] as const)('names the credential class for %#', (principal, expected) => { diff --git a/apps/sim/lib/core/application/environment-reference.test.ts b/apps/sim/lib/core/application/environment-reference.test.ts index 8699f9afd48..893d9dd2b39 100644 --- a/apps/sim/lib/core/application/environment-reference.test.ts +++ b/apps/sim/lib/core/application/environment-reference.test.ts @@ -95,7 +95,7 @@ describe('resolvePrincipalEnvironmentVariable', () => { it('refuses a principal with no subject user', async () => { await expect( resolvePrincipalEnvironmentVariable( - { kind: 'workspace_api_key', workspaceId: WORKSPACE_ID, keyId: 'key-1' }, + { kind: 'workspace_api_key', workspaceId: WORKSPACE_ID, keyId: 'key-1', access: 'write' }, WORKSPACE_ID, 'CHAT_PW' ) diff --git a/apps/sim/lib/core/application/forbidden.ts b/apps/sim/lib/core/application/forbidden.ts index c4f3523596d..d44a69f37d6 100644 --- a/apps/sim/lib/core/application/forbidden.ts +++ b/apps/sim/lib/core/application/forbidden.ts @@ -75,6 +75,8 @@ export const FORBIDDEN_DETAIL_CODES = [ 'INTEGRATION_NOT_ALLOWED', /** The OAuth access token was not granted the scope this operation needs. */ 'INSUFFICIENT_SCOPE', + /** The API key is read-only and the operation changes state; use a full-access key. */ + 'READ_ONLY_API_KEY', /** The organization's identity provider owns this membership, so Sim will not change it. */ 'SCIM_MANAGED_MEMBERSHIP', ] as const diff --git a/apps/sim/lib/core/application/index.ts b/apps/sim/lib/core/application/index.ts index f94e40bce27..6fb4a6a78bf 100644 --- a/apps/sim/lib/core/application/index.ts +++ b/apps/sim/lib/core/application/index.ts @@ -17,8 +17,10 @@ export { forbiddenErrorDetails, } from '@/lib/core/application/forbidden' export { + credentialApiScopes, InsufficientScopeError, OAuthAccessTokenExpiredError, + ReadOnlyApiKeyError, requireOAuthOperationScope, } from '@/lib/core/application/oauth-authorization' export { diff --git a/apps/sim/lib/core/application/oauth-authorization.test.ts b/apps/sim/lib/core/application/oauth-authorization.test.ts index b674415a9b9..6a202dcc196 100644 --- a/apps/sim/lib/core/application/oauth-authorization.test.ts +++ b/apps/sim/lib/core/application/oauth-authorization.test.ts @@ -1,9 +1,10 @@ -import type { OAuthAccessTokenPrincipal } from '@sim/auth/principal' +import type { OAuthAccessTokenPrincipal, PersonalApiKeyPrincipal } from '@sim/auth/principal' import { describe, expect, it, vi } from 'vitest' import { defineAuthorizedWorkspaceUseCase } from '@/lib/core/application/authorized-workspace-use-case' import { InsufficientScopeError, OAuthAccessTokenExpiredError, + ReadOnlyApiKeyError, requireOAuthOperationScope, } from '@/lib/core/application/oauth-authorization' import { defineOperation } from '@/lib/core/application/operation' @@ -61,12 +62,48 @@ describe('semantic OAuth policy', () => { ).not.toThrow() expect(() => requireOAuthOperationScope( - { kind: 'personal_api_key', userId: 'user-1', keyId: 'k-1' }, + { kind: 'personal_api_key', userId: 'user-1', keyId: 'k-1', access: 'write' }, writeOperation ) ).not.toThrow() }) + it('holds a read-only key to api:read and refuses an operation that declares no scope', () => { + const readKey: PersonalApiKeyPrincipal = { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'k-1', + access: 'read', + } + const unscopedOperation = defineWorkspaceOperation({ + id: 'test.unscoped_key_operation', + capability: 'none', + minimumRole: 'read', + workspaceApiKey: 'deny', + principalKinds: ['session', 'personal_api_key'], + }) + + for (const oauthScope of ['api:read', 'search:read'] as const) { + expect(() => + requireOAuthOperationScope(readKey, { ...writeOperation, oauthScope }) + ).not.toThrow() + } + for (const operation of [writeOperation, unscopedOperation]) { + let refusal: unknown + try { + requireOAuthOperationScope(readKey, operation) + } catch (error) { + refusal = error + } + expect(refusal).toBeInstanceOf(ReadOnlyApiKeyError) + expect(refusal).not.toBeInstanceOf(InsufficientScopeError) + expect(refusal).toMatchObject({ detailCode: 'READ_ONLY_API_KEY' }) + } + expect(() => + requireOAuthOperationScope({ ...readKey, access: 'write' }, unscopedOperation) + ).not.toThrow() + }) + it('rejects expiry before considering scope', () => { expect(() => requireOAuthOperationScope({ ...principal, expiresAt: new Date(0) }, writeOperation) diff --git a/apps/sim/lib/core/application/oauth-authorization.ts b/apps/sim/lib/core/application/oauth-authorization.ts index e131deb9573..5c2cff2eed9 100644 --- a/apps/sim/lib/core/application/oauth-authorization.ts +++ b/apps/sim/lib/core/application/oauth-authorization.ts @@ -1,5 +1,12 @@ -import type { Principal } from '@sim/auth/principal' -import { type OAuthApiScope, oauthScopeSatisfies } from '@/lib/auth/oauth-provider' +import { isReadOnlyApiKeyPrincipal, type Principal } from '@sim/auth/principal' +import { READ_ONLY_API_KEY_DENIED } from '@/lib/api-key/policy-messages' +import { + OAUTH_API_READ_SCOPE, + OAUTH_API_WRITE_SCOPE, + OAUTH_SEARCH_READ_SCOPE, + type OAuthApiScope, + oauthScopeSatisfies, +} from '@/lib/auth/oauth-provider' import { delegatedApiScopes } from '@/lib/core/application/delegated-api-scopes' import { ForbiddenOperationError } from '@/lib/core/application/forbidden' import type { ApplicationOperation } from '@/lib/core/application/operation' @@ -12,6 +19,21 @@ export class InsufficientScopeError extends ForbiddenOperationError { } } +/** + * A read-only API key reached an operation its `api:read` grant does not cover. + * Not an {@link InsufficientScopeError}: an API key cannot step up to another + * scope, so the refusal must not carry an OAuth `insufficient_scope` challenge. + */ +export class ReadOnlyApiKeyError extends ForbiddenOperationError { + constructor() { + super('READ_ONLY_API_KEY', READ_ONLY_API_KEY_DENIED) + this.name = 'ReadOnlyApiKeyError' + } +} + +/** What a read-only API key is granted: the operations an `api:read` OAuth token reaches. */ +const READ_ONLY_API_KEY_SCOPES = [OAUTH_API_READ_SCOPE] as const + export class OAuthAccessTokenExpiredError extends OrchestrationError { constructor() { super('unauthorized', 'OAuth access token has expired') @@ -21,8 +43,10 @@ export class OAuthAccessTokenExpiredError extends OrchestrationError { /** * Enforces the client's grant independently of workspace membership and HTTP method: an OAuth - * token's scopes, or those {@link withDelegatedApiScopes} grants a delegated principal. A - * delegated principal may still reach an operation that declares no scope, which is internal. + * token's scopes, a read-only API key's `api:read`, or those {@link withDelegatedApiScopes} + * grants a delegated principal. A delegated principal may still reach an operation that declares + * no scope, which is internal; a read-only key may not, since nothing says that operation only + * reads. */ export function requireOAuthOperationScope( principal: Principal, @@ -30,6 +54,12 @@ export function requireOAuthOperationScope( ): void { const granted = grantedApiScopes(principal) if (!granted) return + if (isReadOnlyApiKeyPrincipal(principal)) { + if (!operation.oauthScope || !oauthScopeSatisfies(granted, operation.oauthScope)) { + throw new ReadOnlyApiKeyError() + } + return + } if (principal.kind === 'oauth_access_token') { if (principal.expiresAt.getTime() <= Date.now()) throw new OAuthAccessTokenExpiredError() if (!operation.oauthScope) { @@ -50,10 +80,29 @@ export function requireDelegatedApiScope(scope: OAuthApiScope): void { if (granted && !oauthScopeSatisfies(granted, scope)) throw new InsufficientScopeError(scope) } +const API_SCOPES: readonly OAuthApiScope[] = [ + OAUTH_API_READ_SCOPE, + OAUTH_API_WRITE_SCOPE, + OAUTH_SEARCH_READ_SCOPE, +] + +/** + * The API scopes a credential holds, as `/api/v2/meta` reports them. A credential + * no grant bounds, such as a write key, holds both `api:read` and `api:write`. + */ +export function credentialApiScopes(principal: Principal): OAuthApiScope[] { + const granted = grantedApiScopes(principal) + if (!granted) return [OAUTH_API_READ_SCOPE, OAUTH_API_WRITE_SCOPE] + return API_SCOPES.filter((scope) => granted.includes(scope)) +} + function grantedApiScopes(principal: Principal): readonly string[] | undefined { switch (principal.kind) { case 'oauth_access_token': return principal.scopes + case 'personal_api_key': + case 'workspace_api_key': + return principal.access === 'read' ? READ_ONLY_API_KEY_SCOPES : undefined case 'delegated': case 'resource_delegated': case 'organization_delegated': diff --git a/apps/sim/lib/core/application/operation.test.ts b/apps/sim/lib/core/application/operation.test.ts index 4292e213458..e2cd409e55d 100644 --- a/apps/sim/lib/core/application/operation.test.ts +++ b/apps/sim/lib/core/application/operation.test.ts @@ -33,7 +33,12 @@ describe('defineOperation', () => { describe('assertOperationPrincipal', () => { it('accepts a principal kind the operation names', () => { - const principal: Principal = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' } + const principal: Principal = { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', + } expect(() => assertOperationPrincipal(principal, readSelf)).not.toThrow() }) diff --git a/apps/sim/lib/core/application/organization-authorization.test.ts b/apps/sim/lib/core/application/organization-authorization.test.ts index 4a727ea8763..a754bf140d1 100644 --- a/apps/sim/lib/core/application/organization-authorization.test.ts +++ b/apps/sim/lib/core/application/organization-authorization.test.ts @@ -193,7 +193,7 @@ describe('organization operation authorization', () => { ) it.each([ principal, - { kind: 'personal_api_key' as const, userId: 'member', keyId: 'key' }, + { kind: 'personal_api_key' as const, userId: 'member', keyId: 'key', access: 'write' as const }, delegated, ])('keeps $kind access independent of the OAuth app restriction', async (caller) => { mocks.config.mockResolvedValue({ @@ -243,7 +243,7 @@ describe('organization operation authorization', () => { it('never accepts a workspace key as organization authority', async () => { await expect( authorizeOrganizationOperation( - { kind: 'workspace_api_key', keyId: 'key', workspaceId: 'org' }, + { kind: 'workspace_api_key', keyId: 'key', access: 'write', workspaceId: 'org' }, operation, { organizationId: 'org' } ) diff --git a/apps/sim/lib/core/application/workspace-authorization.test.ts b/apps/sim/lib/core/application/workspace-authorization.test.ts index b5e8fef8035..da5518a3903 100644 --- a/apps/sim/lib/core/application/workspace-authorization.test.ts +++ b/apps/sim/lib/core/application/workspace-authorization.test.ts @@ -519,6 +519,7 @@ describe('capabilityGovernedPrincipalUserId', () => { kind: 'personal_api_key', userId: 'user-2', keyId: 'key-1', + access: 'write', }) ).toBe('user-2') }) diff --git a/apps/sim/lib/credential-groups/application/list-credentials.test.ts b/apps/sim/lib/credential-groups/application/list-credentials.test.ts index 00a071f6fc3..38390532d77 100644 --- a/apps/sim/lib/credential-groups/application/list-credentials.test.ts +++ b/apps/sim/lib/credential-groups/application/list-credentials.test.ts @@ -173,6 +173,7 @@ describe('listCredentialGroupCredentials', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'workspace-key-1', + access: 'write', } await listCredentialGroupCredentials.execute({ principal, input }) diff --git a/apps/sim/lib/credential-groups/application/manage-groups.test.ts b/apps/sim/lib/credential-groups/application/manage-groups.test.ts index 75cdcccb137..13882270dd8 100644 --- a/apps/sim/lib/credential-groups/application/manage-groups.test.ts +++ b/apps/sim/lib/credential-groups/application/manage-groups.test.ts @@ -158,8 +158,18 @@ describe('Credential Group Settings application operations', () => { }) it.each([ - { kind: 'personal_api_key', userId: 'admin-1', keyId: 'personal-key' } as const, - { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'workspace-key' } as const, + { + kind: 'personal_api_key', + userId: 'admin-1', + keyId: 'personal-key', + access: 'write', + } as const, + { + kind: 'workspace_api_key', + workspaceId: 'workspace-1', + keyId: 'workspace-key', + access: 'write', + } as const, ])('refuses $kind account metadata before loading workspace context', async (principal) => { await expect( getWorkspaceAccountsSettings.execute({ principal, input: { workspaceId: 'workspace-1' } }) @@ -225,8 +235,18 @@ describe('Credential Group Settings application operations', () => { it.each([ enrollmentPrincipal, - { kind: 'personal_api_key', userId: 'admin-1', keyId: 'personal-key' } as const, - { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'workspace-key' } as const, + { + kind: 'personal_api_key', + userId: 'admin-1', + keyId: 'personal-key', + access: 'write', + } as const, + { + kind: 'workspace_api_key', + workspaceId: 'workspace-1', + keyId: 'workspace-key', + access: 'write', + } as const, ])('refuses $kind account setup before resolving protected context', async (principal) => { await expect( ensureWorkspaceAccounts.execute({ principal, input: { workspaceId: 'workspace-1' } }) diff --git a/apps/sim/lib/credentials/application/connection-target.test.ts b/apps/sim/lib/credentials/application/connection-target.test.ts index 80b5b3395b4..d616342c583 100644 --- a/apps/sim/lib/credentials/application/connection-target.test.ts +++ b/apps/sim/lib/credentials/application/connection-target.test.ts @@ -53,6 +53,7 @@ const principal = { kind: 'personal_api_key' as const, userId: 'user-1', keyId: 'key-1', + access: 'write' as const, } const context = { workspaceId: 'workspace-1', diff --git a/apps/sim/lib/credentials/application/sharing.integration.ts b/apps/sim/lib/credentials/application/sharing.integration.ts index 7bbba0f27d4..2df8384675d 100644 --- a/apps/sim/lib/credentials/application/sharing.integration.ts +++ b/apps/sim/lib/credentials/application/sharing.integration.ts @@ -11,7 +11,12 @@ describe('Credential sharing through user-held API credentials in PostgreSQL', ( const workspaceId = generateId() const organizationId = generateId() const credentialId = generateId() - const principal = { kind: 'personal_api_key' as const, userId: actorId, keyId: generateId() } + const principal = { + kind: 'personal_api_key' as const, + userId: actorId, + keyId: generateId(), + access: 'write' as const, + } let runtime: Awaited> async function loadRuntime() { @@ -126,7 +131,7 @@ describe('Credential sharing through user-held API credentials in PostgreSQL', ( it('denies workspace keys before looking up a credential', async () => { await expect( runtime.upsertCredentialMemberUseCase.execute({ - principal: { kind: 'workspace_api_key', workspaceId, keyId: generateId() }, + principal: { kind: 'workspace_api_key', workspaceId, keyId: generateId(), access: 'write' }, input: { credentialId: generateId(), userId: readerId, role: 'admin' }, }) ).rejects.toMatchObject({ detailCode: 'WORKSPACE_KEY_OPERATION_NOT_PERMITTED' }) diff --git a/apps/sim/lib/custom-tools/application/use-cases.test.ts b/apps/sim/lib/custom-tools/application/use-cases.test.ts index 9eb3d14594c..c4fe00d83ef 100644 --- a/apps/sim/lib/custom-tools/application/use-cases.test.ts +++ b/apps/sim/lib/custom-tools/application/use-cases.test.ts @@ -80,7 +80,12 @@ describe('custom tool application use cases', () => { it.each([ { kind: 'session' as const, userId: 'reader' }, - { kind: 'personal_api_key' as const, userId: 'reader', keyId: 'key-1' }, + { + kind: 'personal_api_key' as const, + userId: 'reader', + keyId: 'key-1', + access: 'write' as const, + }, ])( 'reads available tools as the $kind actor without billing-owner substitution', async (principal) => { @@ -291,6 +296,7 @@ describe('custom tool application use cases', () => { kind: 'workspace_api_key' as const, workspaceId: workspace.workspaceId, keyId: 'workspace-key-1', + access: 'write' as const, } const result = await createWorkspaceCustomToolUseCase.execute({ diff --git a/apps/sim/lib/data-drains/application/use-cases.test.ts b/apps/sim/lib/data-drains/application/use-cases.test.ts index 39f81292c8f..c5cfb0e06df 100644 --- a/apps/sim/lib/data-drains/application/use-cases.test.ts +++ b/apps/sim/lib/data-drains/application/use-cases.test.ts @@ -118,8 +118,8 @@ beforeEach(() => { describe('organization data drain application boundary', () => { it.each([ - { kind: 'workspace_api_key', workspaceId: 'org', keyId: 'key' }, - { kind: 'personal_api_key', userId: 'actor', keyId: 'key' }, + { kind: 'workspace_api_key', workspaceId: 'org', keyId: 'key', access: 'write' }, + { kind: 'personal_api_key', userId: 'actor', keyId: 'key', access: 'write' }, { ...principal, organizationId: 'elsewhere' }, { ...principal, audience: 'sim:knowledge' }, { ...principal, expiresAt: new Date(0) }, diff --git a/apps/sim/lib/desktop/source-request.integration.ts b/apps/sim/lib/desktop/source-request.integration.ts index 437cecdeb47..390e50aafc3 100644 --- a/apps/sim/lib/desktop/source-request.integration.ts +++ b/apps/sim/lib/desktop/source-request.integration.ts @@ -73,7 +73,12 @@ describe.skipIf(!redisUrl)('desktop source request transport', () => { it('rejects non-session callers and oversized requests', async () => { await expect( createDesktopSourceRequest.execute({ - principal: { kind: 'workspace_api_key', workspaceId: generateId(), keyId: generateId() }, + principal: { + kind: 'workspace_api_key', + workspaceId: generateId(), + keyId: generateId(), + access: 'write', + }, input: { requestId: generateShortId(32), payload: '{}' }, }) ).rejects.toThrow('Session authentication required') diff --git a/apps/sim/lib/execution/files.test.ts b/apps/sim/lib/execution/files.test.ts index d743ef80799..a51937ed304 100644 --- a/apps/sim/lib/execution/files.test.ts +++ b/apps/sim/lib/execution/files.test.ts @@ -535,7 +535,7 @@ describe('workflow input files', () => { } it.each([ { kind: 'session', userId: 'user', sessionId: 'session' }, - { kind: 'personal_api_key', userId: 'user', keyId: 'key' }, + { kind: 'personal_api_key', userId: 'user', keyId: 'key', access: 'write' }, { kind: 'oauth_access_token', userId: 'user', @@ -544,7 +544,7 @@ describe('workflow input files', () => { scopes: [], expiresAt: new Date(), }, - { kind: 'workspace_api_key', workspaceId, keyId: 'key' }, + { kind: 'workspace_api_key', workspaceId, keyId: 'key', access: 'write' }, { kind: 'delegated', serviceId: 'copilot', subjectUserId: 'user', ...delegation }, ])('lets authorized member principal $kind reference workspace files', (principal) => { expect(getStoredFileReferenceScope(principal)).toBe('workspace') diff --git a/apps/sim/lib/internal/file/execute-tool.test.ts b/apps/sim/lib/internal/file/execute-tool.test.ts index 0aa42882fc0..f0cfa920dd5 100644 --- a/apps/sim/lib/internal/file/execute-tool.test.ts +++ b/apps/sim/lib/internal/file/execute-tool.test.ts @@ -252,6 +252,7 @@ describe('executeFileTool', () => { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', + access: 'write', } const call = request('file_read', MANAGE_INPUTS.file_read) call.context.callerPrincipal = callerPrincipal @@ -267,7 +268,12 @@ describe('executeFileTool', () => { it('never falls back to a direct caller after invalid executor delegation', async () => { const call = request('file_read', MANAGE_INPUTS.file_read) - call.context.callerPrincipal = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' } + call.context.callerPrincipal = { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', + } mockCreateExecutorPrincipalFromExecutionContext.mockRejectedValueOnce( new InvalidInternalDelegationBindingError() ) @@ -282,7 +288,12 @@ describe('executeFileTool', () => { request('file_read', MANAGE_INPUTS.file_read, { context: { workflowId: '', - callerPrincipal: { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' }, + callerPrincipal: { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', + }, }, }) ) diff --git a/apps/sim/lib/internal/principals/executor.test.ts b/apps/sim/lib/internal/principals/executor.test.ts index 3d8ab01b840..87d77a7cd54 100644 --- a/apps/sim/lib/internal/principals/executor.test.ts +++ b/apps/sim/lib/internal/principals/executor.test.ts @@ -144,6 +144,7 @@ describe('createExecutorPrincipalFromExecutionContext', () => { kind: 'workspace_api_key' as const, workspaceId: 'workspace-canonical', keyId: 'workspace-key-1', + access: 'write' as const, }, }, { diff --git a/apps/sim/lib/invitations/application/send-invitation-batch.test.ts b/apps/sim/lib/invitations/application/send-invitation-batch.test.ts index ab95519db6a..ebf4092eb5e 100644 --- a/apps/sim/lib/invitations/application/send-invitation-batch.test.ts +++ b/apps/sim/lib/invitations/application/send-invitation-batch.test.ts @@ -168,7 +168,12 @@ describe('invitation batch application boundary', () => { it('rejects workspace API keys before any user or scope lookup', async () => { await expect( useCase.execute({ - principal: { kind: 'workspace_api_key', workspaceId: 'workspace', keyId: 'key' }, + principal: { + kind: 'workspace_api_key', + workspaceId: 'workspace', + keyId: 'key', + access: 'write', + }, input: orgInput, }) ).rejects.toMatchObject({ detailCode: 'WORKSPACE_KEY_OPERATION_NOT_PERMITTED' }) diff --git a/apps/sim/lib/knowledge/__integration__/application-acl.integration.ts b/apps/sim/lib/knowledge/__integration__/application-acl.integration.ts index 3d1fe53b622..4213fcf034f 100644 --- a/apps/sim/lib/knowledge/__integration__/application-acl.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/application-acl.integration.ts @@ -91,11 +91,17 @@ describe('indexed source content through real application access', () => { const ids = createKnowledgeAclFixtureIds() const { aliceId, bobId, workspaceId, knowledgeBaseId, connectorId, lockId, groups } = ids const alice: Principal = { kind: 'session', userId: aliceId, sessionId: 'fixture-alice' } - const bob: Principal = { kind: 'personal_api_key', userId: bobId, keyId: 'fixture-bob' } + const bob: Principal = { + kind: 'personal_api_key', + userId: bobId, + keyId: 'fixture-bob', + access: 'write', + } const workspaceKey: Principal = { kind: 'workspace_api_key', workspaceId, keyId: 'fixture-workspace', + access: 'write', } const content = 'Orion project: the release readiness checklist is complete. Engineers approved the customer migration plan and documented every operational dependency.' diff --git a/apps/sim/lib/knowledge/__integration__/coda-live.integration.ts b/apps/sim/lib/knowledge/__integration__/coda-live.integration.ts index a2d2b9cc993..b5e52ed2d7c 100644 --- a/apps/sim/lib/knowledge/__integration__/coda-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/coda-live.integration.ts @@ -264,6 +264,7 @@ describe.skipIf(!tokenPath || !fixturePath || !secondEmail)( kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture', + access: 'write', }) expect(await keySearch).not.toContain(documentId) const chunks = await listKnowledgeChunks.execute({ diff --git a/apps/sim/lib/knowledge/__integration__/confluence-live.integration.ts b/apps/sim/lib/knowledge/__integration__/confluence-live.integration.ts index e58d8f8a52c..ab388c0bdf3 100644 --- a/apps/sim/lib/knowledge/__integration__/confluence-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/confluence-live.integration.ts @@ -343,6 +343,7 @@ describe.skipIf(!fixtureFile)('live Confluence ingestion and permission parity', kind: 'workspace_api_key', workspaceId: input.workspaceId, keyId: 'confluence-live', + access: 'write', } expect( ( diff --git a/apps/sim/lib/knowledge/__integration__/filtered-search.integration.ts b/apps/sim/lib/knowledge/__integration__/filtered-search.integration.ts index e54b80a29c1..c80c160e85c 100644 --- a/apps/sim/lib/knowledge/__integration__/filtered-search.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/filtered-search.integration.ts @@ -33,11 +33,17 @@ describe.each([384, 768, 1024, 1536, 3072] as const)( const secondBaseId = generateId() const embeddingModel = dimensions === 384 ? 'ollama/all-minilm' : 'text-embedding-3-large' const alice: Principal = { kind: 'session', userId: ids.aliceId, sessionId: 'fixture-alice' } - const bob: Principal = { kind: 'personal_api_key', userId: ids.bobId, keyId: 'fixture-bob' } + const bob: Principal = { + kind: 'personal_api_key', + userId: ids.bobId, + keyId: 'fixture-bob', + access: 'write', + } const workspaceKey: Principal = { kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture-key', + access: 'write', } const restrictedAcl = confluencePageAcl({ providerId: 'google-drive', diff --git a/apps/sim/lib/knowledge/__integration__/gitlab-federated.integration.ts b/apps/sim/lib/knowledge/__integration__/gitlab-federated.integration.ts index 183e4328089..c5ecb8894b3 100644 --- a/apps/sim/lib/knowledge/__integration__/gitlab-federated.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/gitlab-federated.integration.ts @@ -68,6 +68,7 @@ describe.skipIf(!fixtureFile)('federated self-hosted GitLab Search', () => { kind: 'personal_api_key', userId: person.simId, keyId: 'gitlab-federated-fixture', + access: 'write', }) async function response( diff --git a/apps/sim/lib/knowledge/__integration__/gitlab-live.integration.ts b/apps/sim/lib/knowledge/__integration__/gitlab-live.integration.ts index 03cfab42c74..d5ad059856d 100644 --- a/apps/sim/lib/knowledge/__integration__/gitlab-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/gitlab-live.integration.ts @@ -125,11 +125,13 @@ describe.skipIf(!fixtureFile)('live self-hosted GitLab ingestion and permission kind: 'personal_api_key', userId: person.simId, keyId: 'gitlab-live-fixture', + access: 'write', }) const workspaceKey = (): Principal => ({ kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'gitlab-live-fixture', + access: 'write', }) async function waitForProjectAccess(person: GitLabPerson, expectedStatus: number) { diff --git a/apps/sim/lib/knowledge/__integration__/google-drive-live.integration.ts b/apps/sim/lib/knowledge/__integration__/google-drive-live.integration.ts index 99e6aa32199..100492de60f 100644 --- a/apps/sim/lib/knowledge/__integration__/google-drive-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/google-drive-live.integration.ts @@ -92,11 +92,13 @@ describe.skipIf(!keyPath || !folderId || !ownerEmail)( kind: 'personal_api_key', userId: ids.bobId, keyId: 'live-drive', + access: 'write', }) const workspaceKey = (): Principal => ({ kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'live-drive', + access: 'write', }) async function search(principal: Principal) { diff --git a/apps/sim/lib/knowledge/__integration__/google-drive-member-live.integration.ts b/apps/sim/lib/knowledge/__integration__/google-drive-member-live.integration.ts index 66b304cf182..84f4c34fde3 100644 --- a/apps/sim/lib/knowledge/__integration__/google-drive-member-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/google-drive-member-live.integration.ts @@ -124,6 +124,7 @@ describe.skipIf(!fixtureFile || !serviceAccountFile)( kind: 'workspace_api_key', workspaceId: input.workspaceId, keyId: 'drive-member-live', + access: 'write', }) const sourceConfig = () => ({ folderId: [sharedFolderId, privateFolderId], maxFiles: 0 }) diff --git a/apps/sim/lib/knowledge/__integration__/kb-block-search.integration.ts b/apps/sim/lib/knowledge/__integration__/kb-block-search.integration.ts index 294ee0ff1c4..ce6331e8847 100644 --- a/apps/sim/lib/knowledge/__integration__/kb-block-search.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/kb-block-search.integration.ts @@ -26,6 +26,7 @@ describe('API-key KB block fan-out', () => { kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture-key', + access: 'write', } const vector = [1, ...Array(1535).fill(0)] const queryVector = { diff --git a/apps/sim/lib/knowledge/__integration__/keyword-ranking.integration.ts b/apps/sim/lib/knowledge/__integration__/keyword-ranking.integration.ts index 94cf2553cc0..7951f4c7368 100644 --- a/apps/sim/lib/knowledge/__integration__/keyword-ranking.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/keyword-ranking.integration.ts @@ -159,6 +159,7 @@ describe('unauthenticated keyword ranking', () => { kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture-key', + access: 'write', } const alice: Principal = { kind: 'session', userId: ids.aliceId, sessionId: 'fixture-alice' } const restrictedAcl = confluencePageAcl({ diff --git a/apps/sim/lib/knowledge/__integration__/providers-live.integration.ts b/apps/sim/lib/knowledge/__integration__/providers-live.integration.ts index efdc7e4c37d..a95651ab98e 100644 --- a/apps/sim/lib/knowledge/__integration__/providers-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/providers-live.integration.ts @@ -168,6 +168,7 @@ describe.skipIf(!credentialsFile)('real embedding and scanned PDF providers', () kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'synthetic-provider-fixture', + access: 'write', }, input: { workspaceId: ids.workspaceId, @@ -615,7 +616,12 @@ describe.skipIf(!credentialsFile)('real embedding and scanned PDF providers', () expect(result.results[0]?.documentId).toBe(created.documentId) for (const deniedPrincipal of [ { ...principal, userId: ids.bobId }, - { kind: 'workspace_api_key' as const, workspaceId: ids.workspaceId, keyId: 'fixture' }, + { + kind: 'workspace_api_key' as const, + workspaceId: ids.workspaceId, + keyId: 'fixture', + access: 'write' as const, + }, ]) { await expect( readKnowledgeDocument.execute({ principal: deniedPrincipal, input }) diff --git a/apps/sim/lib/knowledge/__integration__/search-index-policy.integration.ts b/apps/sim/lib/knowledge/__integration__/search-index-policy.integration.ts index 0a286b3d43d..62c86edae97 100644 --- a/apps/sim/lib/knowledge/__integration__/search-index-policy.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/search-index-policy.integration.ts @@ -36,6 +36,7 @@ const workspaceKey: Principal = { kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture-key', + access: 'write', } const privateId = generateId() const sharedId = generateId() @@ -176,7 +177,7 @@ describe('canonical search knowledge-base policy', () => { ) for (const principal of [ writer, - { kind: 'personal_api_key', userId: ids.bobId, keyId: 'fixture-personal' }, + { kind: 'personal_api_key', userId: ids.bobId, keyId: 'fixture-personal', access: 'write' }, workspaceKey, copilot(ids.bobId), ] as Principal[]) { @@ -308,7 +309,12 @@ describe('canonical search knowledge-base policy', () => { .deletedAt ).not.toBeNull() await deleteKnowledgeBaseOperation.execute({ - principal: { kind: 'personal_api_key', userId: ids.aliceId, keyId: 'fixture-admin-key' }, + principal: { + kind: 'personal_api_key', + userId: ids.aliceId, + keyId: 'fixture-admin-key', + access: 'write', + }, input: { knowledgeBaseId: replacementId }, }) const restored = await restoreKnowledgeBase.execute({ diff --git a/apps/sim/lib/knowledge/__integration__/search-latency.integration.ts b/apps/sim/lib/knowledge/__integration__/search-latency.integration.ts index 8d19f607c59..af1c3f72cee 100644 --- a/apps/sim/lib/knowledge/__integration__/search-latency.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/search-latency.integration.ts @@ -345,6 +345,7 @@ async function searchWorkspaceKb( kind: 'workspace_api_key', workspaceId: fixture.workspaceId, keyId: 'fixture-search-key', + access: 'write', }, input: { workspaceId: fixture.workspaceId, diff --git a/apps/sim/lib/knowledge/__integration__/slack-live.integration.ts b/apps/sim/lib/knowledge/__integration__/slack-live.integration.ts index b9e90eb68b2..c2b46f617f4 100644 --- a/apps/sim/lib/knowledge/__integration__/slack-live.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/slack-live.integration.ts @@ -104,6 +104,7 @@ describe.skipIf(!fixtureFile)('live Slack content and human access', () => { kind: 'workspace_api_key', workspaceId: input.workspaceId, keyId: 'slack-live', + access: 'write', }) async function api(method: string, token: string, body: Record = {}) { diff --git a/apps/sim/lib/knowledge/__integration__/workspace-kb-document-access.integration.ts b/apps/sim/lib/knowledge/__integration__/workspace-kb-document-access.integration.ts index 4033a2f9219..ac563bda13c 100644 --- a/apps/sim/lib/knowledge/__integration__/workspace-kb-document-access.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/workspace-kb-document-access.integration.ts @@ -73,6 +73,7 @@ describe.each([ kind: 'workspace_api_key', workspaceId: ids.workspaceId, keyId: 'fixture-key', + access: 'write', } beforeAll(async () => { diff --git a/apps/sim/lib/mothership/agent-cli/csv-workflow-execution.live.test.ts b/apps/sim/lib/mothership/agent-cli/csv-workflow-execution.live.test.ts index b1acc836069..cd0a940d34d 100644 --- a/apps/sim/lib/mothership/agent-cli/csv-workflow-execution.live.test.ts +++ b/apps/sim/lib/mothership/agent-cli/csv-workflow-execution.live.test.ts @@ -86,7 +86,12 @@ vi.unmock('@/blocks/registry') vi.mock('@/lib/api/server/routes/v2-api-key-auth', async (importOriginal) => ({ ...(await importOriginal()), authenticateV2ApiKey: async () => ({ - principal: { kind: 'personal_api_key', userId: fixtures.userId, keyId: 'csv-key' }, + principal: { + kind: 'personal_api_key', + userId: fixtures.userId, + keyId: 'csv-key', + access: 'write', + }, rateLimitSubjectIds: ['user:csv-user'], rateLimitSubscription: null, keyType: 'personal', diff --git a/apps/sim/lib/mothership/agent-cli/file-upload-transport.test.ts b/apps/sim/lib/mothership/agent-cli/file-upload-transport.test.ts index 8a76ff8be91..4d90e9ea723 100644 --- a/apps/sim/lib/mothership/agent-cli/file-upload-transport.test.ts +++ b/apps/sim/lib/mothership/agent-cli/file-upload-transport.test.ts @@ -15,7 +15,12 @@ vi.mock('@/lib/uploads/upload-session/application', () => ({ import { createFileUploadTransport } from '@/lib/mothership/agent-cli/file-upload-transport' const workspaceId = '7727ef3f-8cf6-4686-b063-2bb006a10785' -const principal = { kind: 'personal_api_key', userId: 'reader', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'reader', + keyId: 'key', + access: 'write', +} as const const endpoint = 'https://sim.test' const path = '/api/v2/files/uploads' const source = { diff --git a/apps/sim/lib/mothership/agent-cli/saved-run-read.live.test.ts b/apps/sim/lib/mothership/agent-cli/saved-run-read.live.test.ts index f92196fcedc..64950ef7624 100644 --- a/apps/sim/lib/mothership/agent-cli/saved-run-read.live.test.ts +++ b/apps/sim/lib/mothership/agent-cli/saved-run-read.live.test.ts @@ -286,7 +286,12 @@ vi.mock('@sim/db', async () => { vi.mock('@/lib/api/server/routes/v2-api-key-auth', async (importOriginal) => ({ ...(await importOriginal()), authenticateV2ApiKey: async () => ({ - principal: { kind: 'personal_api_key', userId: 'run-reader', keyId: 'local-key' }, + principal: { + kind: 'personal_api_key', + userId: 'run-reader', + keyId: 'local-key', + access: 'write', + }, rateLimitSubjectIds: ['user:run-reader'], rateLimitSubscription: null, keyType: 'personal', @@ -2613,7 +2618,12 @@ describe.skipIf(!process.env.MSHIP_TEST_DATABASE_URL)( expect(sessions.size).toBe(2) if (mode === 'partial-files') { const existing = await readWorkspaceFileArtifact.execute({ - principal: { kind: 'personal_api_key', userId: 'run-reader', keyId: 'local-key' }, + principal: { + kind: 'personal_api_key', + userId: 'run-reader', + keyId: 'local-key', + access: 'write', + }, input: { workspaceId, reference: `files/existing-${exportName}`, maxBytes: 1024 }, }) expect(existing.buffer.toString('utf8')).toBe('Existing report must survive') @@ -2664,7 +2674,12 @@ describe.skipIf(!process.env.MSHIP_TEST_DATABASE_URL)( const reference = `uploads/${encodeURIComponent(filename)}` expect(prepared.context[0].content).toContain(reference) const read = await readWorkspaceFileText.execute({ - principal: { kind: 'personal_api_key', userId: 'run-reader', keyId: 'local-key' }, + principal: { + kind: 'personal_api_key', + userId: 'run-reader', + keyId: 'local-key', + access: 'write', + }, input: { workspaceId, reference }, }) expect(read.file.id).toBe(row.id) diff --git a/apps/sim/lib/posthog/events.ts b/apps/sim/lib/posthog/events.ts index 89f16cc55c9..a8240dfe7ec 100644 --- a/apps/sim/lib/posthog/events.ts +++ b/apps/sim/lib/posthog/events.ts @@ -335,6 +335,8 @@ export interface PostHogEventMap { key_name: string scope?: 'workspace' | 'personal' source?: 'settings' | 'deploy_modal' + access?: 'read' | 'write' + expires?: boolean } api_key_revoked: { diff --git a/apps/sim/lib/selectors/server/providers/mcp.test.ts b/apps/sim/lib/selectors/server/providers/mcp.test.ts index 10a7f29d644..25d70144821 100644 --- a/apps/sim/lib/selectors/server/providers/mcp.test.ts +++ b/apps/sim/lib/selectors/server/providers/mcp.test.ts @@ -22,7 +22,7 @@ function args(request: ExecuteServerSelectorArgs['request']): ExecuteServerSelec request, scope: { kind: 'workspace', workspaceId: 'destination' }, workspaceId: 'destination', - principal: { kind: 'personal_api_key', userId: 'user', keyId: 'key' }, + principal: { kind: 'personal_api_key', userId: 'user', keyId: 'key', access: 'write' }, requesterUserId: 'user', references: new Map(), protectedValues: createSelectorProtectedValues(), diff --git a/apps/sim/lib/table/application/analytics.test.ts b/apps/sim/lib/table/application/analytics.test.ts index bf7f903d197..e883c218e5f 100644 --- a/apps/sim/lib/table/application/analytics.test.ts +++ b/apps/sim/lib/table/application/analytics.test.ts @@ -76,13 +76,18 @@ describe('authorized table analytics', () => { it('rejects API keys', async () => { await expect( readTableAnalytics.execute({ - principal: { kind: 'workspace_api_key', workspaceId: 'workspace_test', keyId: 'key' }, + principal: { + kind: 'workspace_api_key', + workspaceId: 'workspace_test', + keyId: 'key', + access: 'write', + }, input, }) ).rejects.toThrow() await expect( readTableAnalytics.execute({ - principal: { kind: 'personal_api_key', userId: 'viewer', keyId: 'key' }, + principal: { kind: 'personal_api_key', userId: 'viewer', keyId: 'key', access: 'write' }, input, }) ).rejects.toThrow() diff --git a/apps/sim/lib/table/application/authorization.test.ts b/apps/sim/lib/table/application/authorization.test.ts index 494dbd96984..f4ad018612f 100644 --- a/apps/sim/lib/table/application/authorization.test.ts +++ b/apps/sim/lib/table/application/authorization.test.ts @@ -88,6 +88,7 @@ describe('table operation authorization', () => { kind: 'workspace_api_key', workspaceId: 'workspace-2', keyId: 'key-2', + access: 'write', }) }) diff --git a/apps/sim/lib/users/application/read-current-user.test.ts b/apps/sim/lib/users/application/read-current-user.test.ts index e722c0e0d8a..41d25eb9611 100644 --- a/apps/sim/lib/users/application/read-current-user.test.ts +++ b/apps/sim/lib/users/application/read-current-user.test.ts @@ -19,6 +19,7 @@ const personalKey: PersonalApiKeyPrincipal = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', + access: 'write', } describe('current-user reads', () => { diff --git a/apps/sim/lib/workflows/api/route-policies.test.ts b/apps/sim/lib/workflows/api/route-policies.test.ts index 93208e315cb..3c8a09b5cd8 100644 --- a/apps/sim/lib/workflows/api/route-policies.test.ts +++ b/apps/sim/lib/workflows/api/route-policies.test.ts @@ -88,6 +88,7 @@ describe('internal workflow read auth', () => { success: true, keyId: 'key-1', keyType: 'workspace', + access: 'write', userId: 'forged-route-user', workspaceId: 'workspace-1', }) @@ -103,6 +104,7 @@ describe('internal workflow read auth', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }) expect(mocks.updateLastUsed).toHaveBeenCalledWith('key-1') }) diff --git a/apps/sim/lib/workflows/api/route-policies.ts b/apps/sim/lib/workflows/api/route-policies.ts index 72bb9fc48eb..a81334592b1 100644 --- a/apps/sim/lib/workflows/api/route-policies.ts +++ b/apps/sim/lib/workflows/api/route-policies.ts @@ -18,6 +18,7 @@ import { type V2ErrorPolicy, v2OrchestrationErrorPolicy, } from '@/lib/api/server/routes' +import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' import { authenticateApiKeyFromHeader, updateApiKeyLastUsed } from '@/lib/api-key/service' import { asOrchestrationError, statusForOrchestrationError } from '@/lib/core/orchestration/types' import { WorkflowRunAlreadyTerminalError } from '@/lib/execution/workflow-run-already-terminal-error' @@ -100,17 +101,29 @@ type WorkflowApiKeyPrincipal = PersonalApiKeyPrincipal | WorkspaceApiKeyPrincipa async function authenticateWorkflowApiKey(rawApiKey: string): Promise { const result = await authenticateApiKeyFromHeader(rawApiKey) - if (!result.success || !result.keyId || !result.keyType) { - throw new InternalUnauthenticatedError('Unauthorized') + if (!result.success || !result.keyId || !result.keyType || !result.access) { + throw new InternalUnauthenticatedError( + result.error === API_KEY_EXPIRED ? API_KEY_EXPIRED : 'Unauthorized' + ) } updateApiKeyLastUsed(result.keyId) if (result.keyType === 'workspace') { if (!result.workspaceId) throw new Error('Workspace API key is missing its workspace scope') - return { kind: 'workspace_api_key', workspaceId: result.workspaceId, keyId: result.keyId } + return { + kind: 'workspace_api_key', + workspaceId: result.workspaceId, + keyId: result.keyId, + access: result.access, + } } if (!result.userId) throw new Error('Personal API key is missing its credential owner') - return { kind: 'personal_api_key', userId: result.userId, keyId: result.keyId } + return { + kind: 'personal_api_key', + userId: result.userId, + keyId: result.keyId, + access: result.access, + } } export const internalWorkflowSessionOrApiKeyAuth: InternalAuthPolicy< diff --git a/apps/sim/lib/workflows/application/mcp-output-schemas.test.ts b/apps/sim/lib/workflows/application/mcp-output-schemas.test.ts index cee1de5d264..80ef053d96a 100644 --- a/apps/sim/lib/workflows/application/mcp-output-schemas.test.ts +++ b/apps/sim/lib/workflows/application/mcp-output-schemas.test.ts @@ -12,7 +12,12 @@ import { createMcpToolOutputSnapshot } from '@/lib/mcp/output-schema' import { snapshotMcpToolOutputSchemas } from '@/lib/workflows/application/mcp-output-schemas' const discover = mcpUseCasesMockFns.mockDiscoverMcpServerToolsUseCase -const principal = { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1' } as const +const principal = { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', +} as const const options = { principal, workspaceId: 'workspace-1' } const ON_CALL_SCHEMA = { diff --git a/apps/sim/lib/workflows/executor/start-run-identity.test.ts b/apps/sim/lib/workflows/executor/start-run-identity.test.ts index 0c6217f4682..cd305baee11 100644 --- a/apps/sim/lib/workflows/executor/start-run-identity.test.ts +++ b/apps/sim/lib/workflows/executor/start-run-identity.test.ts @@ -16,6 +16,7 @@ describe('resolveStartBlockRunIdentity', () => { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', + access: 'write', }) ).resolves.toEqual({ subject: { @@ -75,6 +76,7 @@ describe('resolveStartBlockRunIdentity', () => { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', + access: 'write', }) ).resolves.toEqual({ subject: null }) expect(mockGetUserEmailById).not.toHaveBeenCalled() diff --git a/apps/sim/lib/workflows/references/import-configuration.test.ts b/apps/sim/lib/workflows/references/import-configuration.test.ts index 45204071d50..d129cc4620c 100644 --- a/apps/sim/lib/workflows/references/import-configuration.test.ts +++ b/apps/sim/lib/workflows/references/import-configuration.test.ts @@ -16,7 +16,12 @@ import { import { buildWorkflowImportPlan } from '@/lib/workflows/references/import-plan' import { getBlock } from '@/blocks/registry' -const principal = { kind: 'personal_api_key', userId: 'user', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'user', + keyId: 'key', + access: 'write', +} as const const agent = { type: 'agent', subBlocks: [{ id: 'tools', type: 'tool-input' }] } as BlockConfig const mcp = { type: 'mcp', diff --git a/apps/sim/lib/workflows/references/selector-values.test.ts b/apps/sim/lib/workflows/references/selector-values.test.ts index 9b3e5059087..1a779fc1d6b 100644 --- a/apps/sim/lib/workflows/references/selector-values.test.ts +++ b/apps/sim/lib/workflows/references/selector-values.test.ts @@ -15,7 +15,12 @@ import { workflowSelectorValidator, } from '@/lib/workflows/references/selector-values' -const principal = { kind: 'personal_api_key', userId: 'user', keyId: 'key' } as const +const principal = { + kind: 'personal_api_key', + userId: 'user', + keyId: 'key', + access: 'write', +} as const describe('workflow selector validation', () => { beforeEach(() => { diff --git a/apps/sim/lib/workspace-files/__integration__/file-path-references.integration.ts b/apps/sim/lib/workspace-files/__integration__/file-path-references.integration.ts index 37d428c27be..8122dee26fb 100644 --- a/apps/sim/lib/workspace-files/__integration__/file-path-references.integration.ts +++ b/apps/sim/lib/workspace-files/__integration__/file-path-references.integration.ts @@ -320,7 +320,7 @@ describe('single-file operations addressed by VFS path', () => { .where(eq(workspace.id, workspaceId)) try { const outcomes = await refusalsFor( - { kind: 'personal_api_key', userId: carol, keyId: generateId() }, + { kind: 'personal_api_key', userId: carol, keyId: generateId(), access: 'write' }, [await ambiguousPath(), 'files/missing.csv', 'files/report.csv'] ) expect(outcomes[0]).not.toBeNull() diff --git a/apps/sim/lib/workspace-files/application/authorization.test.ts b/apps/sim/lib/workspace-files/application/authorization.test.ts index a16565bbde2..5ce1b36085d 100644 --- a/apps/sim/lib/workspace-files/application/authorization.test.ts +++ b/apps/sim/lib/workspace-files/application/authorization.test.ts @@ -51,6 +51,7 @@ describe('file operation authorization', () => { kind: 'workspace_api_key', workspaceId: 'workspace-2', keyId: 'key-2', + access: 'write', }) }) diff --git a/apps/sim/lib/workspaces/__integration__/fork-sync.integration.ts b/apps/sim/lib/workspaces/__integration__/fork-sync.integration.ts index c2b3f30669a..f96bd924f25 100644 --- a/apps/sim/lib/workspaces/__integration__/fork-sync.integration.ts +++ b/apps/sim/lib/workspaces/__integration__/fork-sync.integration.ts @@ -68,7 +68,12 @@ import type { WorkflowState } from '@/stores/workflows/workflow/types' const userId = generateId() const sourceWorkspaceId = generateId() const sourceWorkflowId = generateId() -const principal = { kind: 'personal_api_key' as const, userId, keyId: generateId() } +const principal = { + kind: 'personal_api_key' as const, + userId, + keyId: generateId(), + access: 'write' as const, +} const createdWorkspaceIds: string[] = [] const graph: WorkflowState = { blocks: { diff --git a/apps/sim/lib/workspaces/__integration__/mapped-import.integration.ts b/apps/sim/lib/workspaces/__integration__/mapped-import.integration.ts index f3b45b96e9b..309a56105db 100644 --- a/apps/sim/lib/workspaces/__integration__/mapped-import.integration.ts +++ b/apps/sim/lib/workspaces/__integration__/mapped-import.integration.ts @@ -26,7 +26,12 @@ const userId = generateId() const workspaceId = generateId() const sandboxId = generateId() const permissionId = generateId() -const principal = { kind: 'personal_api_key', userId, keyId: generateId() } as const +const principal = { + kind: 'personal_api_key', + userId, + keyId: generateId(), + access: 'write', +} as const function input(name: string) { const state: WorkflowState = { diff --git a/apps/sim/lib/workspaces/__integration__/pagination.integration.ts b/apps/sim/lib/workspaces/__integration__/pagination.integration.ts index ef6d9548476..89c0cc48422 100644 --- a/apps/sim/lib/workspaces/__integration__/pagination.integration.ts +++ b/apps/sim/lib/workspaces/__integration__/pagination.integration.ts @@ -13,7 +13,12 @@ import { listWorkspaceForkChildren } from '@/ee/workspace-forking/application/di const userId = generateId() const workspaceId = generateId() const otherWorkspaceId = generateId() -const principal = { kind: 'personal_api_key' as const, userId, keyId: generateId() } +const principal = { + kind: 'personal_api_key' as const, + userId, + keyId: generateId(), + access: 'write' as const, +} const childIds = Array.from({ length: 4 }, () => generateId()).sort() const operationIds = Array.from({ length: 4 }, () => generateId()).sort() const timestamps = [ diff --git a/apps/sim/lib/workspaces/application/record-workspace-visit.test.ts b/apps/sim/lib/workspaces/application/record-workspace-visit.test.ts index e0371b89e37..55c2d31ef57 100644 --- a/apps/sim/lib/workspaces/application/record-workspace-visit.test.ts +++ b/apps/sim/lib/workspaces/application/record-workspace-visit.test.ts @@ -36,7 +36,7 @@ describe('recordWorkspaceVisit', () => { }) it('rejects API-key principals before loading the workspace', async () => { - const apiKey = { kind: 'personal_api_key', keyId: 'key-1', userId: 'user-1' } + const apiKey = { kind: 'personal_api_key', keyId: 'key-1', access: 'write', userId: 'user-1' } await expect( recordWorkspaceVisit.execute({ diff --git a/packages/auth/src/principal.ts b/packages/auth/src/principal.ts index c0b3978960c..7b187f2b5a6 100644 --- a/packages/auth/src/principal.ts +++ b/packages/auth/src/principal.ts @@ -37,10 +37,18 @@ export interface SessionPrincipal { sessionId: string } +/** + * What an API key may do. A `read` key is held to the operations the `api:read` + * OAuth scope reaches and refused everything else, including any operation + * that declares no scope at all. + */ +export type ApiKeyAccess = 'read' | 'write' + export interface PersonalApiKeyPrincipal { kind: 'personal_api_key' userId: string keyId: string + access: ApiKeyAccess } /** @@ -65,6 +73,7 @@ export interface WorkspaceApiKeyPrincipal { kind: 'workspace_api_key' workspaceId: string keyId: string + access: ApiKeyAccess } /** Operations a SCIM bearer credential may perform. Mirrors `ScimScope` in the schema. */ @@ -284,6 +293,16 @@ export type CredentialGroupEnrollmentPrincipal = CredentialGroupEnrollmentIdenti export type DelegatedServiceId = DelegatedPrincipal['serviceId'] +/** An API key created read-only, which every surface must hold to reads. */ +export function isReadOnlyApiKeyPrincipal( + principal: Principal +): principal is (PersonalApiKeyPrincipal | WorkspaceApiKeyPrincipal) & { access: 'read' } { + return ( + (principal.kind === 'personal_api_key' || principal.kind === 'workspace_api_key') && + principal.access === 'read' + ) +} + /** * A person reaching the API through a bearer credential of their own — a * personal API key or an OAuth access token. The two are one authorization @@ -349,11 +368,20 @@ export type WorkflowExecutionPrincipal = | SubjectDelegatedPrincipal | SystemPrincipal +/** + * A write key serializes without `access`, the shape every deployed parser + * accepts; only a read key carries it. + */ +type SerializedApiKeyPrincipal

= Omit< + P, + 'access' +> & { access?: 'read' } + type SerializedWorkflowExecutionPrincipal = | SessionPrincipal - | PersonalApiKeyPrincipal + | SerializedApiKeyPrincipal | (Omit & { expiresAt: string }) - | WorkspaceApiKeyPrincipal + | SerializedApiKeyPrincipal | SystemPrincipal | (Omit & { issuedAt: string @@ -448,13 +476,23 @@ function parseAuthenticatedEmailSubject(value: unknown): AuthenticatedEmailSubje } } +/** A principal persisted before keys had an access level was a write key. */ +function parseApiKeyAccess(value: unknown): ApiKeyAccess { + if (value === undefined || value === 'write') return 'write' + if (value === 'read') return 'read' + throw new Error('Serialized principal access must be read or write') +} + /** Encodes a workflow caller without persisting bearer credentials or invitation proofs. */ export function serializePrincipal(principal: WorkflowExecutionPrincipal): SerializedPrincipalV1 { switch (principal.kind) { case 'session': - case 'personal_api_key': - case 'workspace_api_key': return { version: 1, principal: { ...principal } } + case 'personal_api_key': + case 'workspace_api_key': { + const { access, ...rest } = principal + return { version: 1, principal: access === 'read' ? { ...rest, access } : rest } + } case 'oauth_access_token': return { version: 1, @@ -505,18 +543,20 @@ export function parsePrincipal(value: unknown): WorkflowExecutionPrincipal { sessionId: requireString(principal.sessionId, 'sessionId'), } case 'personal_api_key': - requireExactKeys(principal, ['kind', 'userId', 'keyId']) + requireExactKeys(principal, ['kind', 'userId', 'keyId'], ['access']) return { kind, userId: requireString(principal.userId, 'userId'), keyId: requireString(principal.keyId, 'keyId'), + access: parseApiKeyAccess(principal.access), } case 'workspace_api_key': - requireExactKeys(principal, ['kind', 'workspaceId', 'keyId']) + requireExactKeys(principal, ['kind', 'workspaceId', 'keyId'], ['access']) return { kind, workspaceId: requireString(principal.workspaceId, 'workspaceId'), keyId: requireString(principal.keyId, 'keyId'), + access: parseApiKeyAccess(principal.access), } case 'oauth_access_token': { requireExactKeys(principal, ['kind', 'userId', 'clientId', 'tokenId', 'scopes', 'expiresAt']) diff --git a/packages/db/migrations/0455_api_key_access.sql b/packages/db/migrations/0455_api_key_access.sql new file mode 100644 index 00000000000..c23130b667d --- /dev/null +++ b/packages/db/migrations/0455_api_key_access.sql @@ -0,0 +1,2 @@ +CREATE TYPE "public"."api_key_access" AS ENUM('read', 'write');--> statement-breakpoint +ALTER TABLE "api_key" ADD COLUMN "access" "api_key_access" DEFAULT 'write' NOT NULL; \ No newline at end of file diff --git a/packages/db/migrations/meta/0455_snapshot.json b/packages/db/migrations/meta/0455_snapshot.json new file mode 100644 index 00000000000..775efe4979b --- /dev/null +++ b/packages/db/migrations/meta/0455_snapshot.json @@ -0,0 +1,34550 @@ +{ + "id": "47f71127-867a-4c55-8869-0e00cd2c4429", + "prevId": "4265b908-fbe8-481a-9c67-67f8a79c2ee9", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oauth_config": { + "name": "oauth_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_revoked_at": { + "name": "refresh_revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_revoked_code": { + "name": "refresh_revoked_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_revoked_token_hash": { + "name": "refresh_revoked_token_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_account_on_account_id_provider_id": { + "name": "idx_account_on_account_id_provider_id", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agent_memory_turn": { + "name": "agent_memory_turn", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "memory_id": { + "name": "memory_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "node_id": { + "name": "node_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_order": { + "name": "execution_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "encrypted_state": { + "name": "encrypted_state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agent_memory_turn_invocation_unique": { + "name": "agent_memory_turn_invocation_unique", + "columns": [ + { + "expression": "memory_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "node_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "execution_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_memory_turn_workflow_idx": { + "name": "agent_memory_turn_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_memory_turn_memory_id_memory_id_fk": { + "name": "agent_memory_turn_memory_id_memory_id_fk", + "tableFrom": "agent_memory_turn", + "tableTo": "memory", + "columnsFrom": [ + "memory_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_memory_turn_workflow_id_workflow_id_fk": { + "name": "agent_memory_turn_workflow_id_workflow_id_fk", + "tableFrom": "agent_memory_turn", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.api_key": { + "name": "api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_hash": { + "name": "key_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'personal'" + }, + "access": { + "name": "access", + "type": "api_key_access", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'write'" + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "api_key_workspace_type_idx": { + "name": "api_key_workspace_type_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "api_key_user_type_idx": { + "name": "api_key_user_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "api_key_key_hash_idx": { + "name": "api_key_key_hash_idx", + "columns": [ + { + "expression": "key_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "api_key_user_id_user_id_fk": { + "name": "api_key_user_id_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_workspace_id_workspace_id_fk": { + "name": "api_key_workspace_id_workspace_id_fk", + "tableFrom": "api_key", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_created_by_user_id_fk": { + "name": "api_key_created_by_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_key_key_unique": { + "name": "api_key_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_type_check": { + "name": "workspace_type_check", + "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.assistant_tool_permission": { + "name": "assistant_tool_permission", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "read_policy": { + "name": "read_policy", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'allow'" + }, + "write_policy": { + "name": "write_policy", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ask'" + }, + "overrides": { + "name": "overrides", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "assistant_tool_permission_credential_idx": { + "name": "assistant_tool_permission_credential_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "assistant_tool_permission_user_idx": { + "name": "assistant_tool_permission_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "assistant_tool_permission_organization_id_organization_id_fk": { + "name": "assistant_tool_permission_organization_id_organization_id_fk", + "tableFrom": "assistant_tool_permission", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "assistant_tool_permission_user_id_user_id_fk": { + "name": "assistant_tool_permission_user_id_user_id_fk", + "tableFrom": "assistant_tool_permission", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "assistant_tool_permission_credential_id_credential_id_fk": { + "name": "assistant_tool_permission_credential_id_credential_id_fk", + "tableFrom": "assistant_tool_permission", + "tableTo": "credential", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "assistant_tool_permission_organization_id_user_id_credential_id_pk": { + "name": "assistant_tool_permission_organization_id_user_id_credential_id_pk", + "columns": [ + "organization_id", + "user_id", + "credential_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "assistant_tool_permission_policy_check": { + "name": "assistant_tool_permission_policy_check", + "value": "\"assistant_tool_permission\".\"read_policy\" IN ('allow', 'ask', 'block') AND \"assistant_tool_permission\".\"write_policy\" IN ('allow', 'ask', 'block')" + }, + "assistant_tool_permission_revision_check": { + "name": "assistant_tool_permission_revision_check", + "value": "\"assistant_tool_permission\".\"revision\" > 0" + } + }, + "isRLSEnabled": false + }, + "public.async_jobs": { + "name": "async_jobs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_at": { + "name": "run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "max_attempts": { + "name": "max_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 3 + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "output": { + "name": "output", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "async_jobs_status_started_at_idx": { + "name": "async_jobs_status_started_at_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "async_jobs_status_completed_at_idx": { + "name": "async_jobs_status_completed_at_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "completed_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "async_jobs_schedule_pending_run_at_idx": { + "name": "async_jobs_schedule_pending_run_at_idx", + "columns": [ + { + "expression": "run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"async_jobs\".\"type\" = 'schedule-execution' AND \"async_jobs\".\"status\" = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "async_jobs_schedule_processing_started_at_idx": { + "name": "async_jobs_schedule_processing_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"async_jobs\".\"type\" = 'schedule-execution' AND \"async_jobs\".\"status\" = 'processing'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "async_jobs_schedule_unreconciled_terminal_idx": { + "name": "async_jobs_schedule_unreconciled_terminal_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"async_jobs\".\"type\" = 'schedule-execution' AND \"async_jobs\".\"status\" IN ('completed', 'failed', 'cancelled') AND COALESCE(\"async_jobs\".\"metadata\" ->> 'scheduleReconciled', 'false') <> 'true'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.audit_log": { + "name": "audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_id": { + "name": "actor_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_name": { + "name": "actor_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_email": { + "name": "actor_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_name": { + "name": "resource_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "surface": { + "name": "surface", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "audit_log_workspace_created_idx": { + "name": "audit_log_workspace_created_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_log_workspace_created_at_id_idx": { + "name": "audit_log_workspace_created_at_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"created_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_log_actor_created_idx": { + "name": "audit_log_actor_created_idx", + "columns": [ + { + "expression": "actor_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_log_org_level_created_at_id_idx": { + "name": "audit_log_org_level_created_at_id_idx", + "columns": [ + { + "expression": "(\"metadata\"->>'organizationId')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"created_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"audit_log\".\"workspace_id\" IS NULL AND (\"audit_log\".\"metadata\"->>'organizationId') IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "audit_log_resource_idx": { + "name": "audit_log_resource_idx", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_log_action_idx": { + "name": "audit_log_action_idx", + "columns": [ + { + "expression": "action", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "audit_log_workspace_id_workspace_id_fk": { + "name": "audit_log_workspace_id_workspace_id_fk", + "tableFrom": "audit_log", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "audit_log_actor_id_user_id_fk": { + "name": "audit_log_actor_id_user_id_fk", + "tableFrom": "audit_log", + "tableTo": "user", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.aws_marketplace_license": { + "name": "aws_marketplace_license", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "license_arn": { + "name": "license_arn", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "product_code": { + "name": "product_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "customer_aws_account_id": { + "name": "customer_aws_account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agreement_id": { + "name": "agreement_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agreement_seen_at": { + "name": "agreement_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "renewed_agreement_id": { + "name": "renewed_agreement_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "aws_marketplace_license_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "dimension": { + "name": "dimension", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_verified_at": { + "name": "last_verified_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "last_verification_attempt_at": { + "name": "last_verification_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "license_event_received_at": { + "name": "license_event_received_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "claim_token_hash": { + "name": "claim_token_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claim_expires_at": { + "name": "claim_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "linked_by_user_id": { + "name": "linked_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contact_email": { + "name": "contact_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "company_name": { + "name": "company_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "aws_marketplace_license_arn_unique": { + "name": "aws_marketplace_license_arn_unique", + "columns": [ + { + "expression": "license_arn", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_claim_token_hash_unique": { + "name": "aws_marketplace_license_claim_token_hash_unique", + "columns": [ + { + "expression": "claim_token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_agreement_id_idx": { + "name": "aws_marketplace_license_agreement_id_idx", + "columns": [ + { + "expression": "agreement_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_renewed_agreement_id_idx": { + "name": "aws_marketplace_license_renewed_agreement_id_idx", + "columns": [ + { + "expression": "renewed_agreement_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_account_product_idx": { + "name": "aws_marketplace_license_account_product_idx", + "columns": [ + { + "expression": "customer_aws_account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "product_code", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_last_attempt_idx": { + "name": "aws_marketplace_license_last_attempt_idx", + "columns": [ + { + "expression": "last_verification_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_organization_id_idx": { + "name": "aws_marketplace_license_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "aws_marketplace_license_linked_by_user_id_idx": { + "name": "aws_marketplace_license_linked_by_user_id_idx", + "columns": [ + { + "expression": "linked_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "aws_marketplace_license_organization_id_organization_id_fk": { + "name": "aws_marketplace_license_organization_id_organization_id_fk", + "tableFrom": "aws_marketplace_license", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "aws_marketplace_license_linked_by_user_id_user_id_fk": { + "name": "aws_marketplace_license_linked_by_user_id_user_id_fk", + "tableFrom": "aws_marketplace_license", + "tableTo": "user", + "columnsFrom": [ + "linked_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.background_work_status": { + "name": "background_work_status", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "background_work_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "background_work_status_value", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "background_work_status_workspace_status_idx": { + "name": "background_work_status_workspace_status_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "background_work_status_workflow_status_idx": { + "name": "background_work_status_workflow_status_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "background_work_status_meta_child_ws_idx": { + "name": "background_work_status_meta_child_ws_idx", + "columns": [ + { + "expression": "(\"metadata\" ->> 'childWorkspaceId')", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "background_work_status_meta_other_ws_idx": { + "name": "background_work_status_meta_other_ws_idx", + "columns": [ + { + "expression": "(\"metadata\" ->> 'otherWorkspaceId')", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "background_work_status_workspace_id_workspace_id_fk": { + "name": "background_work_status_workspace_id_workspace_id_fk", + "tableFrom": "background_work_status", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "background_work_status_workflow_id_workflow_id_fk": { + "name": "background_work_status_workflow_id_workflow_id_fk", + "tableFrom": "background_work_status", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.changelog_change": { + "name": "changelog_change", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "release_id": { + "name": "release_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "changelog_change_release_position_unique": { + "name": "changelog_change_release_position_unique", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "changelog_change_release_id_changelog_release_id_fk": { + "name": "changelog_change_release_id_changelog_release_id_fk", + "tableFrom": "changelog_change", + "tableTo": "changelog_release", + "columnsFrom": [ + "release_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "changelog_change_workflow_id_workflow_id_fk": { + "name": "changelog_change_workflow_id_workflow_id_fk", + "tableFrom": "changelog_change", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "changelog_change_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "changelog_change_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "changelog_change", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "changelog_change_chat_id_copilot_chats_id_fk": { + "name": "changelog_change_chat_id_copilot_chats_id_fk", + "tableFrom": "changelog_change", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.changelog_release": { + "name": "changelog_release", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version_major": { + "name": "version_major", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "version_minor": { + "name": "version_minor", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "version_patch": { + "name": "version_patch", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "bump_reason": { + "name": "bump_reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "body_file_id": { + "name": "body_file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "published_at": { + "name": "published_at", + "type": "timestamp (3)", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "changelog_release_workspace_version_unique": { + "name": "changelog_release_workspace_version_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version_major", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version_minor", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version_patch", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "changelog_release_body_file_unique": { + "name": "changelog_release_body_file_unique", + "columns": [ + { + "expression": "body_file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "changelog_release_workspace_published_idx": { + "name": "changelog_release_workspace_published_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "published_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "changelog_release_workspace_id_workspace_id_fk": { + "name": "changelog_release_workspace_id_workspace_id_fk", + "tableFrom": "changelog_release", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "changelog_release_body_file_id_workspace_files_id_fk": { + "name": "changelog_release_body_file_id_workspace_files_id_fk", + "tableFrom": "changelog_release", + "tableTo": "workspace_files", + "columnsFrom": [ + "body_file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "changelog_release_created_by_user_id_fk": { + "name": "changelog_release_created_by_user_id_fk", + "tableFrom": "changelog_release", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "changelog_release_updated_by_user_id_fk": { + "name": "changelog_release_updated_by_user_id_fk", + "tableFrom": "changelog_release", + "tableTo": "user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "changelog_release_version_check": { + "name": "changelog_release_version_check", + "value": "\"changelog_release\".\"version_major\" >= 0 AND \"changelog_release\".\"version_minor\" >= 0 AND \"changelog_release\".\"version_patch\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.chat": { + "name": "chat", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "customizations": { + "name": "customizations", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "output_configs": { + "name": "output_configs", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "include_thinking": { + "name": "include_thinking", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_tool_calls": { + "name": "include_tool_calls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"chat\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_archived_at_partial_idx": { + "name": "chat_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"chat\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_chat_on_workflow_id_archived_at": { + "name": "idx_chat_on_workflow_id_archived_at", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_user_id_idx": { + "name": "chat_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_workflow_id_workflow_id_fk": { + "name": "chat_workflow_id_workflow_id_fk", + "tableFrom": "chat", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.client_credential_token": { + "name": "client_credential_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "encrypted_value": { + "name": "encrypted_value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token_digest": { + "name": "access_token_digest", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "client_credential_token_expires_at_idx": { + "name": "client_credential_token_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"client_credential_token\".\"access_token_digest\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "client_credential_token_access_token_digest_idx": { + "name": "client_credential_token_access_token_digest_idx", + "columns": [ + { + "expression": "access_token_digest", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"client_credential_token\".\"access_token_digest\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_async_tool_calls": { + "name": "copilot_async_tool_calls", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "checkpoint_id": { + "name": "checkpoint_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "tool_call_id": { + "name": "tool_call_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "args": { + "name": "args", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "executable_name": { + "name": "executable_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_workspace_id": { + "name": "target_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "approved_args": { + "name": "approved_args", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "assistant_action": { + "name": "assistant_action", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "execution_retryable": { + "name": "execution_retryable", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status": { + "name": "status", + "type": "copilot_async_tool_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "result": { + "name": "result", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "permission_decision": { + "name": "permission_decision", + "type": "copilot_tool_permission_decision", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "permission_decided_at": { + "name": "permission_decided_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "permission_requested_at": { + "name": "permission_requested_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "pickup_deadline_at": { + "name": "pickup_deadline_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "persist_seq": { + "name": "persist_seq", + "type": "bigint", + "primaryKey": false, + "notNull": false, + "default": "nextval('copilot_async_tool_calls_persist_seq')" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "claimed_by": { + "name": "claimed_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "browser_download_started_at": { + "name": "browser_download_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "execution_started_at": { + "name": "execution_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "execution_settled_at": { + "name": "execution_settled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "execution_owner_token": { + "name": "execution_owner_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "execution_lease_expires_at": { + "name": "execution_lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "execution_revoked_at": { + "name": "execution_revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "execution_attempts": { + "name": "execution_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "execution_deadline_at": { + "name": "execution_deadline_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "client_workflow_execution_id": { + "name": "client_workflow_execution_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sandbox_processes": { + "name": "sandbox_processes", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_async_tool_calls_checkpoint_id_idx": { + "name": "copilot_async_tool_calls_checkpoint_id_idx", + "columns": [ + { + "expression": "checkpoint_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_async_tool_calls_status_idx": { + "name": "copilot_async_tool_calls_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_async_tool_calls_run_status_idx": { + "name": "copilot_async_tool_calls_run_status_idx", + "columns": [ + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_async_tool_calls_tool_call_id_unique": { + "name": "copilot_async_tool_calls_tool_call_id_unique", + "columns": [ + { + "expression": "tool_call_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_async_tool_calls_run_id_copilot_runs_id_fk": { + "name": "copilot_async_tool_calls_run_id_copilot_runs_id_fk", + "tableFrom": "copilot_async_tool_calls", + "tableTo": "copilot_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_async_tool_calls_checkpoint_id_copilot_run_checkpoints_id_fk": { + "name": "copilot_async_tool_calls_checkpoint_id_copilot_run_checkpoints_id_fk", + "tableFrom": "copilot_async_tool_calls", + "tableTo": "copilot_run_checkpoints", + "columnsFrom": [ + "checkpoint_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_chats": { + "name": "copilot_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memory_space_id": { + "name": "memory_space_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "chat_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'copilot'" + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'claude-3-7-sonnet-latest'" + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_conversation_key": { + "name": "external_conversation_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_conversation_metadata": { + "name": "external_conversation_metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "preview_yaml": { + "name": "preview_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "resources": { + "name": "resources", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "auto_allowed_tools": { + "name": "auto_allowed_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "pinned": { + "name": "pinned", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_chats_organization_id_idx": { + "name": "copilot_chats_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_external_conversation_unique": { + "name": "copilot_chats_external_conversation_unique", + "columns": [ + { + "expression": "external_conversation_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"copilot_chats\".\"external_conversation_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_org_created_idx": { + "name": "copilot_chats_user_org_created_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workflow_id_idx": { + "name": "copilot_chats_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workflow_idx": { + "name": "copilot_chats_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workspace_idx": { + "name": "copilot_chats_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_created_at_idx": { + "name": "copilot_chats_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_updated_at_idx": { + "name": "copilot_chats_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workspace_created_at_id_idx": { + "name": "copilot_chats_workspace_created_at_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"created_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workspace_deleted_partial_idx": { + "name": "copilot_chats_user_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_chats\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_chats_user_id_user_id_fk": { + "name": "copilot_chats_user_id_user_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workflow_id_workflow_id_fk": { + "name": "copilot_chats_workflow_id_workflow_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workspace_id_workspace_id_fk": { + "name": "copilot_chats_workspace_id_workspace_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_organization_id_organization_id_fk": { + "name": "copilot_chats_organization_id_organization_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "copilot_chats_owner_check": { + "name": "copilot_chats_owner_check", + "value": "num_nonnulls(\"copilot_chats\".\"workspace_id\", \"copilot_chats\".\"organization_id\") <= 1" + }, + "copilot_chats_organization_workflow_check": { + "name": "copilot_chats_organization_workflow_check", + "value": "\"copilot_chats\".\"organization_id\" IS NULL OR \"copilot_chats\".\"workflow_id\" IS NULL" + } + }, + "isRLSEnabled": false + }, + "public.copilot_feedback": { + "name": "copilot_feedback", + "schema": "", + "columns": { + "feedback_id": { + "name": "feedback_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_response": { + "name": "agent_response", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_positive": { + "name": "is_positive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "feedback": { + "name": "feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_yaml": { + "name": "workflow_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_feedback_user_id_idx": { + "name": "copilot_feedback_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_chat_id_idx": { + "name": "copilot_feedback_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_user_chat_idx": { + "name": "copilot_feedback_user_chat_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_is_positive_idx": { + "name": "copilot_feedback_is_positive_idx", + "columns": [ + { + "expression": "is_positive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_created_at_idx": { + "name": "copilot_feedback_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_feedback_user_id_user_id_fk": { + "name": "copilot_feedback_user_id_user_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_feedback_chat_id_copilot_chats_id_fk": { + "name": "copilot_feedback_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_messages": { + "name": "copilot_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "display_content": { + "name": "display_content", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "stream_id": { + "name": "stream_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "seq": { + "name": "seq", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_messages_chat_message_unique": { + "name": "copilot_messages_chat_message_unique", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_messages_chat_created_at_idx": { + "name": "copilot_messages_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_messages\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_messages_chat_seq_idx": { + "name": "copilot_messages_chat_seq_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "seq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_messages\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_messages_chat_stream_idx": { + "name": "copilot_messages_chat_stream_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stream_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_messages\".\"stream_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_messages_user_created_at_idx": { + "name": "copilot_messages_user_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_messages\".\"role\" = 'user' AND \"copilot_messages\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_messages_chat_id_copilot_chats_id_fk": { + "name": "copilot_messages_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_messages", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_organization_request_stops": { + "name": "copilot_organization_request_stops", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stream_id": { + "name": "stream_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stopped_at": { + "name": "stopped_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "copilot_organization_request_stops_user_id_user_id_fk": { + "name": "copilot_organization_request_stops_user_id_user_id_fk", + "tableFrom": "copilot_organization_request_stops", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_organization_request_stops_organization_id_organization_id_fk": { + "name": "copilot_organization_request_stops_organization_id_organization_id_fk", + "tableFrom": "copilot_organization_request_stops", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "copilot_organization_request_stops_user_id_organization_id_stream_id_pk": { + "name": "copilot_organization_request_stops_user_id_organization_id_stream_id_pk", + "columns": [ + "user_id", + "organization_id", + "stream_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_request_stops": { + "name": "copilot_request_stops", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stream_id": { + "name": "stream_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stopped_at": { + "name": "stopped_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "copilot_request_stops_user_id_user_id_fk": { + "name": "copilot_request_stops_user_id_user_id_fk", + "tableFrom": "copilot_request_stops", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_request_stops_workspace_id_workspace_id_fk": { + "name": "copilot_request_stops_workspace_id_workspace_id_fk", + "tableFrom": "copilot_request_stops", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "copilot_request_stops_user_id_workspace_id_stream_id_pk": { + "name": "copilot_request_stops_user_id_workspace_id_stream_id_pk", + "columns": [ + "user_id", + "workspace_id", + "stream_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_run_checkpoints": { + "name": "copilot_run_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "run_id": { + "name": "run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "pending_tool_call_id": { + "name": "pending_tool_call_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversation_snapshot": { + "name": "conversation_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "agent_state": { + "name": "agent_state", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "provider_request": { + "name": "provider_request", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_run_checkpoints_pending_tool_call_id_idx": { + "name": "copilot_run_checkpoints_pending_tool_call_id_idx", + "columns": [ + { + "expression": "pending_tool_call_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_run_checkpoints_run_pending_tool_unique": { + "name": "copilot_run_checkpoints_run_pending_tool_unique", + "columns": [ + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pending_tool_call_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_run_checkpoints_run_id_copilot_runs_id_fk": { + "name": "copilot_run_checkpoints_run_id_copilot_runs_id_fk", + "tableFrom": "copilot_run_checkpoints", + "tableTo": "copilot_runs", + "columnsFrom": [ + "run_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_runs": { + "name": "copilot_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_execution_version": { + "name": "tool_execution_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "tool_admission_closed_at": { + "name": "tool_admission_closed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "parent_run_id": { + "name": "parent_run_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stream_id": { + "name": "stream_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agent": { + "name": "agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "copilot_run_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "request_context": { + "name": "request_context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "desktop_device_id": { + "name": "desktop_device_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "copilot_runs_parent_run_id_idx": { + "name": "copilot_runs_parent_run_id_idx", + "columns": [ + { + "expression": "parent_run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_chat_started_at_idx": { + "name": "copilot_runs_chat_started_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_user_id_idx": { + "name": "copilot_runs_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_workflow_id_idx": { + "name": "copilot_runs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_status_idx": { + "name": "copilot_runs_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_chat_execution_idx": { + "name": "copilot_runs_chat_execution_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_execution_started_at_idx": { + "name": "copilot_runs_execution_started_at_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_workspace_completed_at_id_idx": { + "name": "copilot_runs_workspace_completed_at_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"completed_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_stream_id_unique": { + "name": "copilot_runs_stream_id_unique", + "columns": [ + { + "expression": "stream_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_runs_desktop_device_started_at_idx": { + "name": "copilot_runs_desktop_device_started_at_idx", + "columns": [ + { + "expression": "desktop_device_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"copilot_runs\".\"desktop_device_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_runs_chat_id_copilot_chats_id_fk": { + "name": "copilot_runs_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_runs_user_id_user_id_fk": { + "name": "copilot_runs_user_id_user_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_runs_workflow_id_workflow_id_fk": { + "name": "copilot_runs_workflow_id_workflow_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_runs_workspace_id_workspace_id_fk": { + "name": "copilot_runs_workspace_id_workspace_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_runs_organization_id_organization_id_fk": { + "name": "copilot_runs_organization_id_organization_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_runs_desktop_device_id_desktop_devices_id_fk": { + "name": "copilot_runs_desktop_device_id_desktop_devices_id_fk", + "tableFrom": "copilot_runs", + "tableTo": "desktop_devices", + "columnsFrom": [ + "desktop_device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_service_usage": { + "name": "copilot_service_usage", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "stream_id": { + "name": "stream_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tool_call_id": { + "name": "tool_call_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "service": { + "name": "service", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cost_usd": { + "name": "cost_usd", + "type": "numeric(12, 8)", + "primaryKey": false, + "notNull": false + }, + "worker_origin": { + "name": "worker_origin", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "copilot_service_usage_pending_idx": { + "name": "copilot_service_usage_pending_idx", + "columns": [ + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "delivered_at IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.credential": { + "name": "credential", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_app_id": { + "name": "slack_app_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "credential_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "unredacted": { + "name": "unredacted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env_key": { + "name": "env_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env_owner_user_id": { + "name": "env_owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_service_account_key": { + "name": "encrypted_service_account_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_personal_token": { + "name": "encrypted_personal_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "authorization_app_id": { + "name": "authorization_app_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_group_enrollment_id": { + "name": "credential_group_enrollment_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_group_option_id": { + "name": "credential_group_option_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mcp_server_id": { + "name": "mcp_server_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mcp_oauth_config_version": { + "name": "mcp_oauth_config_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "managed_oauth_scope_version": { + "name": "managed_oauth_scope_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provider_subject_id": { + "name": "provider_subject_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_tenant_id": { + "name": "provider_tenant_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "managed_oauth_status": { + "name": "managed_oauth_status", + "type": "managed_oauth_credential_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "granted_scopes": { + "name": "granted_scopes", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "provider_metadata": { + "name": "provider_metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "encrypted_oauth_token_set": { + "name": "encrypted_oauth_token_set", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mcp_tools": { + "name": "mcp_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "mcp_tools_refreshed_at": { + "name": "mcp_tools_refreshed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "granted_at": { + "name": "granted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_refreshed_at": { + "name": "last_refreshed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "credential_organization_id_idx": { + "name": "credential_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_organization_account_unique": { + "name": "credential_organization_account_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential\".\"account_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_org_personal_token_unique": { + "name": "credential_org_personal_token_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_subject_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential\".\"type\" = 'personal_token'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_workspace_id_idx": { + "name": "credential_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_type_idx": { + "name": "credential_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_provider_id_idx": { + "name": "credential_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_account_id_idx": { + "name": "credential_account_id_idx", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_env_owner_user_id_idx": { + "name": "credential_env_owner_user_id_idx", + "columns": [ + { + "expression": "env_owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_idx": { + "name": "credential_group_enrollment_idx", + "columns": [ + { + "expression": "credential_group_enrollment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_mcp_server_idx": { + "name": "credential_mcp_server_idx", + "columns": [ + { + "expression": "mcp_server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_option_identity_unique": { + "name": "credential_group_option_identity_unique", + "columns": [ + { + "expression": "credential_group_enrollment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "credential_group_option_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_subject_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"provider_tenant_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential\".\"type\" = 'managed_oauth'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_managed_mcp_enrollment_server_identity_unique": { + "name": "credential_managed_mcp_enrollment_server_identity_unique", + "columns": [ + { + "expression": "credential_group_enrollment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "mcp_server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"provider_subject_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"provider_tenant_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential\".\"type\" = 'managed_mcp'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_workspace_account_unique": { + "name": "credential_workspace_account_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "account_id IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_workspace_env_unique": { + "name": "credential_workspace_env_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "env_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "type = 'env_workspace'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_workspace_personal_env_unique": { + "name": "credential_workspace_personal_env_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "env_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "env_owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "type = 'env_personal'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_personal_token_identity_unique": { + "name": "credential_personal_token_identity_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_subject_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "type = 'personal_token'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credential_workspace_id_workspace_id_fk": { + "name": "credential_workspace_id_workspace_id_fk", + "tableFrom": "credential", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_organization_id_organization_id_fk": { + "name": "credential_organization_id_organization_id_fk", + "tableFrom": "credential", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_slack_app_id_slack_app_id_fk": { + "name": "credential_slack_app_id_slack_app_id_fk", + "tableFrom": "credential", + "tableTo": "slack_app", + "columnsFrom": [ + "slack_app_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "credential_account_id_account_id_fk": { + "name": "credential_account_id_account_id_fk", + "tableFrom": "credential", + "tableTo": "account", + "columnsFrom": [ + "account_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_env_owner_user_id_user_id_fk": { + "name": "credential_env_owner_user_id_user_id_fk", + "tableFrom": "credential", + "tableTo": "user", + "columnsFrom": [ + "env_owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_credential_group_enrollment_id_credential_group_enrollment_id_fk": { + "name": "credential_credential_group_enrollment_id_credential_group_enrollment_id_fk", + "tableFrom": "credential", + "tableTo": "credential_group_enrollment", + "columnsFrom": [ + "credential_group_enrollment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_mcp_server_id_mcp_servers_id_fk": { + "name": "credential_mcp_server_id_mcp_servers_id_fk", + "tableFrom": "credential", + "tableTo": "mcp_servers", + "columnsFrom": [ + "mcp_server_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_created_by_user_id_fk": { + "name": "credential_created_by_user_id_fk", + "tableFrom": "credential", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "credential_owner_check": { + "name": "credential_owner_check", + "value": "num_nonnulls(\"credential\".\"workspace_id\", \"credential\".\"organization_id\") = 1" + }, + "credential_organization_type_check": { + "name": "credential_organization_type_check", + "value": "\"credential\".\"organization_id\" IS NULL OR \"credential\".\"type\" IN ('oauth', 'managed_oauth', 'managed_mcp', 'service_account', 'personal_token')" + }, + "credential_personal_token_source_check": { + "name": "credential_personal_token_source_check", + "value": "(type::text <> 'personal_token') OR (\n created_by IS NOT NULL\n AND provider_id IS NOT NULL\n AND provider_id = 'gitlab'\n AND provider_subject_id IS NOT NULL\n AND provider_tenant_id IS NOT NULL\n AND encrypted_personal_token IS NOT NULL\n AND granted_scopes IS NOT NULL\n AND cardinality(granted_scopes) > 0\n AND account_id IS NULL\n AND env_key IS NULL\n AND env_owner_user_id IS NULL\n AND authorization_app_id IS NULL\n AND encrypted_oauth_token_set IS NULL\n AND encrypted_service_account_key IS NULL\n AND unredacted = false\n )" + }, + "credential_oauth_source_check": { + "name": "credential_oauth_source_check", + "value": "(type <> 'oauth') OR (account_id IS NOT NULL AND provider_id IS NOT NULL)" + }, + "credential_managed_oauth_source_check": { + "name": "credential_managed_oauth_source_check", + "value": "(type::text <> 'managed_oauth') OR (\n account_id IS NULL\n AND provider_id IS NOT NULL\n AND authorization_app_id IS NOT NULL\n AND provider_subject_id IS NOT NULL\n AND managed_oauth_status IS NOT NULL\n AND granted_scopes IS NOT NULL\n AND encrypted_oauth_token_set IS NOT NULL\n AND granted_at IS NOT NULL\n )" + }, + "credential_managed_oauth_group_binding_check": { + "name": "credential_managed_oauth_group_binding_check", + "value": "(type::text <> 'managed_oauth') OR (\n credential_group_enrollment_id IS NOT NULL\n AND credential_group_option_id IS NOT NULL\n AND managed_oauth_scope_version IS NOT NULL\n AND managed_oauth_scope_version > 0\n )" + }, + "credential_managed_mcp_source_check": { + "name": "credential_managed_mcp_source_check", + "value": "(type::text <> 'managed_mcp') OR (\n id LIKE 'mcp-cg-%'\n AND account_id IS NULL\n AND provider_id IS NULL\n AND authorization_app_id IS NULL\n AND credential_group_enrollment_id IS NOT NULL\n AND credential_group_option_id IS NULL\n AND mcp_server_id IS NOT NULL\n AND managed_oauth_status IS NOT NULL\n AND (managed_oauth_status <> 'active' OR (\n encrypted_oauth_token_set IS NOT NULL\n AND mcp_tools IS NOT NULL\n ))\n AND granted_at IS NOT NULL\n AND managed_oauth_scope_version IS NULL\n AND granted_scopes IS NULL\n AND provider_metadata IS NULL\n AND created_by IS NULL\n AND env_key IS NULL\n AND env_owner_user_id IS NULL\n AND encrypted_service_account_key IS NULL\n AND unredacted = false\n )" + }, + "credential_creator_source_check": { + "name": "credential_creator_source_check", + "value": "(type::text = 'managed_mcp') OR created_by IS NOT NULL" + }, + "credential_workspace_env_source_check": { + "name": "credential_workspace_env_source_check", + "value": "(type <> 'env_workspace') OR (env_key IS NOT NULL AND env_owner_user_id IS NULL)" + }, + "credential_personal_env_source_check": { + "name": "credential_personal_env_source_check", + "value": "(type <> 'env_personal') OR (env_key IS NOT NULL AND env_owner_user_id IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.credential_group": { + "name": "credential_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_id": { + "name": "public_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "options": { + "name": "options", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "encrypted_provider_configuration": { + "name": "encrypted_provider_configuration", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "credential_group_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "credential_group_organization_unique": { + "name": "credential_group_organization_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_public_id_unique": { + "name": "credential_group_public_id_unique", + "columns": [ + { + "expression": "public_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_workspace_unique": { + "name": "credential_group_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credential_group_workspace_id_workspace_id_fk": { + "name": "credential_group_workspace_id_workspace_id_fk", + "tableFrom": "credential_group", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_group_organization_id_organization_id_fk": { + "name": "credential_group_organization_id_organization_id_fk", + "tableFrom": "credential_group", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_group_created_by_user_id_fk": { + "name": "credential_group_created_by_user_id_fk", + "tableFrom": "credential_group", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "credential_group_owner_check": { + "name": "credential_group_owner_check", + "value": "num_nonnulls(\"credential_group\".\"workspace_id\", \"credential_group\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.credential_group_enrollment": { + "name": "credential_group_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "credential_group_id": { + "name": "credential_group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "credential_group_enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'invited'" + }, + "invitation_token_hash": { + "name": "invitation_token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invitation_expires_at": { + "name": "invitation_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "invited_at": { + "name": "invited_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "sent_at": { + "name": "sent_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_delivery_error": { + "name": "last_delivery_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "credential_group_enrollment_group_user_unique": { + "name": "credential_group_enrollment_group_user_unique", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential_group_enrollment\".\"user_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_user_id_idx": { + "name": "credential_group_enrollment_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_group_email_unique": { + "name": "credential_group_enrollment_group_email_unique", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_invitation_token_hash_unique": { + "name": "credential_group_enrollment_invitation_token_hash_unique", + "columns": [ + { + "expression": "invitation_token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_group_status_idx": { + "name": "credential_group_enrollment_group_status_idx", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_group_enrollment_group_invited_at_id_idx": { + "name": "credential_group_enrollment_group_invited_at_id_idx", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "invited_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credential_group_enrollment_credential_group_id_credential_group_id_fk": { + "name": "credential_group_enrollment_credential_group_id_credential_group_id_fk", + "tableFrom": "credential_group_enrollment", + "tableTo": "credential_group", + "columnsFrom": [ + "credential_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_group_enrollment_user_id_user_id_fk": { + "name": "credential_group_enrollment_user_id_user_id_fk", + "tableFrom": "credential_group_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_group_enrollment_created_by_user_id_fk": { + "name": "credential_group_enrollment_created_by_user_id_fk", + "tableFrom": "credential_group_enrollment", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "credential_group_enrollment_normalized_email_check": { + "name": "credential_group_enrollment_normalized_email_check", + "value": "\"credential_group_enrollment\".\"email\" = lower(btrim(\"credential_group_enrollment\".\"email\")) AND length(\"credential_group_enrollment\".\"email\") BETWEEN 3 AND 320" + }, + "credential_group_enrollment_invitation_token_hash_length_check": { + "name": "credential_group_enrollment_invitation_token_hash_length_check", + "value": "length(\"credential_group_enrollment\".\"invitation_token_hash\") = 64" + } + }, + "isRLSEnabled": false + }, + "public.credential_member": { + "name": "credential_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "credential_member_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "credential_member_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "credential_member_user_id_idx": { + "name": "credential_member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_member_role_idx": { + "name": "credential_member_role_idx", + "columns": [ + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_member_status_idx": { + "name": "credential_member_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_member_unique": { + "name": "credential_member_unique", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credential_member_credential_id_credential_id_fk": { + "name": "credential_member_credential_id_credential_id_fk", + "tableFrom": "credential_member", + "tableTo": "credential", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_member_user_id_user_id_fk": { + "name": "credential_member_user_id_user_id_fk", + "tableFrom": "credential_member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_member_invited_by_user_id_fk": { + "name": "credential_member_invited_by_user_id_fk", + "tableFrom": "credential_member", + "tableTo": "user", + "columnsFrom": [ + "invited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_block": { + "name": "custom_block", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "icon_url": { + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "inputs": { + "name": "inputs", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "outputs": { + "name": "outputs", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "trace_child_runs": { + "name": "trace_child_runs", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_block_workflow_id_idx": { + "name": "custom_block_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "custom_block_organization_type_unique": { + "name": "custom_block_organization_type_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_block_organization_id_organization_id_fk": { + "name": "custom_block_organization_id_organization_id_fk", + "tableFrom": "custom_block", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_block_workflow_id_workflow_id_fk": { + "name": "custom_block_workflow_id_workflow_id_fk", + "tableFrom": "custom_block", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_block_created_by_user_id_fk": { + "name": "custom_block_created_by_user_id_fk", + "tableFrom": "custom_block", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_tools": { + "name": "custom_tools", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_tools_workspace_title_unique": { + "name": "custom_tools_workspace_title_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_tools_workspace_id_workspace_id_fk": { + "name": "custom_tools_workspace_id_workspace_id_fk", + "tableFrom": "custom_tools", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_tools_user_id_user_id_fk": { + "name": "custom_tools_user_id_user_id_fk", + "tableFrom": "custom_tools", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.dashboard": { + "name": "dashboard", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "dashboard_workspace_id_unique": { + "name": "dashboard_workspace_id_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "dashboard_workspace_id_workspace_id_fk": { + "name": "dashboard_workspace_id_workspace_id_fk", + "tableFrom": "dashboard", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dashboard_created_by_user_id_fk": { + "name": "dashboard_created_by_user_id_fk", + "tableFrom": "dashboard", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "dashboard_updated_by_user_id_fk": { + "name": "dashboard_updated_by_user_id_fk", + "tableFrom": "dashboard", + "tableTo": "user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.data_drain_runs": { + "name": "data_drain_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "drain_id": { + "name": "drain_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "data_drain_run_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "data_drain_run_trigger", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "finished_at": { + "name": "finished_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "rows_exported": { + "name": "rows_exported", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "bytes_written": { + "name": "bytes_written", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cursor_before": { + "name": "cursor_before", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cursor_after": { + "name": "cursor_after", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "locators": { + "name": "locators", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": { + "data_drain_runs_drain_started_idx": { + "name": "data_drain_runs_drain_started_idx", + "columns": [ + { + "expression": "drain_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "data_drain_runs_drain_id_data_drains_id_fk": { + "name": "data_drain_runs_drain_id_data_drains_id_fk", + "tableFrom": "data_drain_runs", + "tableTo": "data_drains", + "columnsFrom": [ + "drain_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.data_drains": { + "name": "data_drains", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "data_drain_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "destination_type": { + "name": "destination_type", + "type": "data_drain_destination", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "destination_config": { + "name": "destination_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "destination_credentials": { + "name": "destination_credentials", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schedule_cadence": { + "name": "schedule_cadence", + "type": "data_drain_cadence", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "cursor": { + "name": "cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_success_at": { + "name": "last_success_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "data_drains_due_idx": { + "name": "data_drains_due_idx", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "data_drains_org_name_unique": { + "name": "data_drains_org_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "data_drains_organization_id_organization_id_fk": { + "name": "data_drains_organization_id_organization_id_fk", + "tableFrom": "data_drains", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "data_drains_created_by_user_id_fk": { + "name": "data_drains_created_by_user_id_fk", + "tableFrom": "data_drains", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deleted_account_identity": { + "name": "deleted_account_identity", + "schema": "", + "columns": { + "identity_hash": { + "name": "identity_hash", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "deleted_account_identity_expires_at_idx": { + "name": "deleted_account_identity_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.desktop_devices": { + "name": "desktop_devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "app_version": { + "name": "app_version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "capabilities": { + "name": "capabilities", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "desktop_devices_user_id_idx": { + "name": "desktop_devices_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "desktop_devices_session_id_idx": { + "name": "desktop_devices_session_id_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "desktop_devices_user_id_user_id_fk": { + "name": "desktop_devices_user_id_user_id_fk", + "tableFrom": "desktop_devices", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "desktop_devices_session_id_session_id_fk": { + "name": "desktop_devices_session_id_session_id_fk", + "tableFrom": "desktop_devices", + "tableTo": "session", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.docs_embeddings": { + "name": "docs_embeddings", + "schema": "", + "columns": { + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_text": { + "name": "chunk_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_document": { + "name": "source_document", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_link": { + "name": "source_link", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_text": { + "name": "header_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_level": { + "name": "header_level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "chunk_text_tsv": { + "name": "chunk_text_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "docs_emb_source_document_idx": { + "name": "docs_emb_source_document_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_header_level_idx": { + "name": "docs_emb_header_level_idx", + "columns": [ + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_source_header_idx": { + "name": "docs_emb_source_header_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_model_idx": { + "name": "docs_emb_model_idx", + "columns": [ + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_created_at_idx": { + "name": "docs_emb_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_embedding_vector_hnsw_idx": { + "name": "docs_embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "docs_emb_metadata_gin_idx": { + "name": "docs_emb_metadata_gin_idx", + "columns": [ + { + "expression": "metadata", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "docs_emb_chunk_text_fts_idx": { + "name": "docs_emb_chunk_text_fts_idx", + "columns": [ + { + "expression": "chunk_text_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "docs_embedding_not_null_check": { + "name": "docs_embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + }, + "docs_header_level_check": { + "name": "docs_header_level_check", + "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" + } + }, + "isRLSEnabled": false + }, + "public.document": { + "name": "document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_url": { + "name": "file_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "storage_key": { + "name": "storage_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_size": { + "name": "file_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "character_count": { + "name": "character_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_status": { + "name": "processing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_attempts": { + "name": "processing_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_queued_at": { + "name": "processing_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_queue_token": { + "name": "processing_queue_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_deferred_until": { + "name": "processing_deferred_until", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_completed_at": { + "name": "processing_completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "processing_recovery_after": { + "name": "processing_recovery_after", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "user_excluded": { + "name": "user_excluded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "number1": { + "name": "number1", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number2": { + "name": "number2", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number3": { + "name": "number3", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number4": { + "name": "number4", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number5": { + "name": "number5", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "date1": { + "name": "date1", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "date2": { + "name": "date2", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "boolean1": { + "name": "boolean1", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "boolean2": { + "name": "boolean2", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "boolean3": { + "name": "boolean3", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_provenance_version": { + "name": "secret_provenance_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "acl": { + "name": "acl", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{ws}'::text[]" + }, + "acl_requirements": { + "name": "acl_requirements", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "acl_verified_at": { + "name": "acl_verified_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "source_modified_at": { + "name": "source_modified_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "source_seen_at": { + "name": "source_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "doc_uploaded_by_idx": { + "name": "doc_uploaded_by_idx", + "columns": [ + { + "expression": "uploaded_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"uploaded_by\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_kb_source_modified_idx": { + "name": "doc_kb_source_modified_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_modified_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"deleted_at\" IS NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_acl_gin_idx": { + "name": "doc_acl_gin_idx", + "columns": [ + { + "expression": "acl", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "array_ops" + } + ], + "isUnique": false, + "where": "\"document\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "gin", + "with": {} + }, + "doc_filename_idx": { + "name": "doc_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_processing_status_idx": { + "name": "doc_processing_status_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_processing_recovery_idx": { + "name": "doc_connector_processing_recovery_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "uploaded_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"processing_status\" IN ('pending', 'processing', 'failed') AND \"document\".\"connector_id\" IS NOT NULL AND \"document\".\"content_hash\" IS NOT NULL AND \"document\".\"storage_key\" IS NOT NULL AND \"document\".\"user_excluded\" = false AND \"document\".\"archived_at\" IS NULL AND \"document\".\"deleted_at\" IS NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_connector_processing_status_idx": { + "name": "doc_connector_processing_status_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"processing_status\" IN ('pending', 'processing', 'failed') AND \"document\".\"connector_id\" IS NOT NULL AND \"document\".\"user_excluded\" = false AND \"document\".\"archived_at\" IS NULL AND \"document\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_external_id_idx": { + "name": "doc_connector_external_id_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"document\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_source_lookup_idx": { + "name": "doc_connector_source_lookup_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_reconciliation_v2_idx": { + "name": "doc_connector_reconciliation_v2_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"user_excluded\" = false AND \"document\".\"archived_at\" IS NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_active_kb_token_count_idx": { + "name": "doc_active_kb_token_count_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "token_count", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"user_excluded\" = false AND \"document\".\"archived_at\" IS NULL AND \"document\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_storage_key_idx": { + "name": "doc_storage_key_idx", + "columns": [ + { + "expression": "storage_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"storage_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_archived_at_partial_idx": { + "name": "doc_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_deleted_at_partial_idx": { + "name": "doc_deleted_at_partial_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_tombstone_idx": { + "name": "doc_connector_tombstone_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"archived_at\" IS NULL AND (\"document\".\"deleted_at\" IS NOT NULL OR \"document\".\"content_hash\" IS NULL)", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_connector_live_idx": { + "name": "doc_connector_live_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"document\".\"user_excluded\" = false AND \"document\".\"archived_at\" IS NULL AND \"document\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag1_lower_idx": { + "name": "doc_kb_tag1_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag1\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag2_lower_idx": { + "name": "doc_kb_tag2_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag2\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag3_lower_idx": { + "name": "doc_kb_tag3_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag3\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag4_lower_idx": { + "name": "doc_kb_tag4_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag4\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag5_lower_idx": { + "name": "doc_kb_tag5_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag5\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag6_lower_idx": { + "name": "doc_kb_tag6_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag6\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_kb_tag7_lower_idx": { + "name": "doc_kb_tag7_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag7\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_number1_idx": { + "name": "doc_number1_idx", + "columns": [ + { + "expression": "number1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_number2_idx": { + "name": "doc_number2_idx", + "columns": [ + { + "expression": "number2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_number3_idx": { + "name": "doc_number3_idx", + "columns": [ + { + "expression": "number3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_number4_idx": { + "name": "doc_number4_idx", + "columns": [ + { + "expression": "number4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_number5_idx": { + "name": "doc_number5_idx", + "columns": [ + { + "expression": "number5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_date1_idx": { + "name": "doc_date1_idx", + "columns": [ + { + "expression": "date1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_date2_idx": { + "name": "doc_date2_idx", + "columns": [ + { + "expression": "date2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "doc_boolean1_idx": { + "name": "doc_boolean1_idx", + "columns": [ + { + "expression": "boolean1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_boolean2_idx": { + "name": "doc_boolean2_idx", + "columns": [ + { + "expression": "boolean2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_boolean3_idx": { + "name": "doc_boolean3_idx", + "columns": [ + { + "expression": "boolean3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_knowledge_base_id_knowledge_base_id_fk": { + "name": "document_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "document_connector_id_knowledge_connector_id_fk": { + "name": "document_connector_id_knowledge_connector_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "document_uploaded_by_user_id_fk": { + "name": "document_uploaded_by_user_id_fk", + "tableFrom": "document", + "tableTo": "user", + "columnsFrom": [ + "uploaded_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "doc_acl_token_shape_check": { + "name": "doc_acl_token_shape_check", + "value": "array_position(\"document\".\"acl\", NULL) IS NULL AND (cardinality(\"document\".\"acl\") = 0 OR (cardinality(\"document\".\"acl\") = array_length(string_to_array(array_to_string(\"document\".\"acl\", E'\\n'), E'\\n'), 1) AND array_to_string(\"document\".\"acl\", E'\\n') ~ '^((ws|pub|link|u:[^\\nA-Z]+@[^\\nA-Z]+|[gs]:[^\\n:]+:[^\\n:]+:[^\\n]+)(\\n(ws|pub|link|u:[^\\nA-Z]+@[^\\nA-Z]+|[gs]:[^\\n:]+:[^\\n:]+:[^\\n]+))*)$'))" + } + }, + "isRLSEnabled": false + }, + "public.document_secret_provenance": { + "name": "document_secret_provenance", + "schema": "", + "columns": { + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "source_hash": { + "name": "source_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entries": { + "name": "entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "document_secret_provenance_document_id_document_id_fk": { + "name": "document_secret_provenance_document_id_document_id_fk", + "tableFrom": "document_secret_provenance", + "tableTo": "document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "document_secret_provenance_status_check": { + "name": "document_secret_provenance_status_check", + "value": "\"document_secret_provenance\".\"status\" IN ('exact', 'unknown')" + } + }, + "isRLSEnabled": false + }, + "public.embedding": { + "name": "embedding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_index": { + "name": "chunk_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chunk_hash": { + "name": "chunk_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret_provenance_version": { + "name": "secret_provenance_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "content_length": { + "name": "content_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "embedding_384": { + "name": "embedding_384", + "type": "vector(384)", + "primaryKey": false, + "notNull": false + }, + "embedding_768": { + "name": "embedding_768", + "type": "vector(768)", + "primaryKey": false, + "notNull": false + }, + "embedding_1024": { + "name": "embedding_1024", + "type": "vector(1024)", + "primaryKey": false, + "notNull": false + }, + "embedding_3072": { + "name": "embedding_3072", + "type": "vector(3072)", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "start_offset": { + "name": "start_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_offset": { + "name": "end_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "number1": { + "name": "number1", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number2": { + "name": "number2", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number3": { + "name": "number3", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number4": { + "name": "number4", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "number5": { + "name": "number5", + "type": "double precision", + "primaryKey": false, + "notNull": false + }, + "date1": { + "name": "date1", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "date2": { + "name": "date2", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "boolean1": { + "name": "boolean1", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "boolean2": { + "name": "boolean2", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "boolean3": { + "name": "boolean3", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content_tsv": { + "name": "content_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"embedding\".\"content\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "emb_doc_chunk_idx": { + "name": "emb_doc_chunk_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chunk_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_model_idx": { + "name": "emb_kb_model_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_enabled_idx": { + "name": "emb_kb_enabled_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_enabled_idx": { + "name": "emb_doc_enabled_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag1_lower_idx": { + "name": "emb_kb_tag1_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag1\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag2_lower_idx": { + "name": "emb_kb_tag2_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag2\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag3_lower_idx": { + "name": "emb_kb_tag3_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag3\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag4_lower_idx": { + "name": "emb_kb_tag4_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag4\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag5_lower_idx": { + "name": "emb_kb_tag5_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag5\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag6_lower_idx": { + "name": "emb_kb_tag6_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag6\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_tag7_lower_idx": { + "name": "emb_kb_tag7_lower_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"tag7\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_number1_idx": { + "name": "emb_number1_idx", + "columns": [ + { + "expression": "number1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_number2_idx": { + "name": "emb_number2_idx", + "columns": [ + { + "expression": "number2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_number3_idx": { + "name": "emb_number3_idx", + "columns": [ + { + "expression": "number3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_number4_idx": { + "name": "emb_number4_idx", + "columns": [ + { + "expression": "number4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_number5_idx": { + "name": "emb_number5_idx", + "columns": [ + { + "expression": "number5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_date1_idx": { + "name": "emb_date1_idx", + "columns": [ + { + "expression": "date1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "emb_date2_idx": { + "name": "emb_date2_idx", + "columns": [ + { + "expression": "date2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "emb_boolean1_idx": { + "name": "emb_boolean1_idx", + "columns": [ + { + "expression": "boolean1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_boolean2_idx": { + "name": "emb_boolean2_idx", + "columns": [ + { + "expression": "boolean2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_boolean3_idx": { + "name": "emb_boolean3_idx", + "columns": [ + { + "expression": "boolean3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_content_fts_idx": { + "name": "emb_content_fts_idx", + "columns": [ + { + "expression": "content_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": { + "fastupdate": "off" + } + } + }, + "foreignKeys": { + "embedding_knowledge_base_id_knowledge_base_id_fk": { + "name": "embedding_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "embedding", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_width_check": { + "name": "embedding_width_check", + "value": "num_nonnulls(\"embedding\", \"embedding_384\", \"embedding_768\", \"embedding_1024\", \"embedding_3072\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.embedding_search": { + "name": "embedding_search", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "acl": { + "name": "acl", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "binary": { + "name": "binary", + "type": "bit(1536)", + "primaryKey": false, + "notNull": false + }, + "binary_384": { + "name": "binary_384", + "type": "bit(384)", + "primaryKey": false, + "notNull": false + }, + "binary_768": { + "name": "binary_768", + "type": "bit(768)", + "primaryKey": false, + "notNull": false + }, + "binary_1024": { + "name": "binary_1024", + "type": "bit(1024)", + "primaryKey": false, + "notNull": false + }, + "binary_3072": { + "name": "binary_3072", + "type": "bit(3072)", + "primaryKey": false, + "notNull": false + }, + "vector": { + "name": "vector", + "type": "halfvec(1536)", + "primaryKey": false, + "notNull": false + }, + "vector_384": { + "name": "vector_384", + "type": "halfvec(384)", + "primaryKey": false, + "notNull": false + }, + "vector_512": { + "name": "vector_512", + "type": "halfvec(512)", + "primaryKey": false, + "notNull": false + }, + "vector_768": { + "name": "vector_768", + "type": "halfvec(768)", + "primaryKey": false, + "notNull": false + }, + "vector_1024": { + "name": "vector_1024", + "type": "halfvec(1024)", + "primaryKey": false, + "notNull": false + }, + "vector_3072": { + "name": "vector_3072", + "type": "halfvec(3072)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "embedding_search_kb_idx": { + "name": "embedding_search_kb_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "embedding_search_document_lookup_idx": { + "name": "embedding_search_document_lookup_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"embedding_search\".\"enabled\"", + "concurrently": true, + "method": "btree", + "with": {} + }, + "embedding_search_cosine_hnsw_idx": { + "name": "embedding_search_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "embedding_search_512_cosine_hnsw_idx": { + "name": "embedding_search_512_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector_512", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "embedding_search_384_cosine_hnsw_idx": { + "name": "embedding_search_384_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector_384", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "embedding_search_768_cosine_hnsw_idx": { + "name": "embedding_search_768_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector_768", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "embedding_search_1024_cosine_hnsw_idx": { + "name": "embedding_search_1024_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector_1024", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "embedding_search_3072_cosine_hnsw_idx": { + "name": "embedding_search_3072_cosine_hnsw_idx", + "columns": [ + { + "expression": "vector_3072", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "halfvec_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + } + }, + "foreignKeys": { + "embedding_search_id_embedding_id_fk": { + "name": "embedding_search_id_embedding_id_fk", + "tableFrom": "embedding_search", + "tableTo": "embedding", + "columnsFrom": [ + "id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_search_width_check": { + "name": "embedding_search_width_check", + "value": "num_nonnulls(\"binary\", \"binary_384\", \"binary_768\", \"binary_1024\", \"binary_3072\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.embedding_secret_provenance": { + "name": "embedding_secret_provenance", + "schema": "", + "columns": { + "embedding_id": { + "name": "embedding_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entries": { + "name": "entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "embedding_secret_provenance_embedding_id_embedding_id_fk": { + "name": "embedding_secret_provenance_embedding_id_embedding_id_fk", + "tableFrom": "embedding_secret_provenance", + "tableTo": "embedding", + "columnsFrom": [ + "embedding_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_secret_provenance_status_check": { + "name": "embedding_secret_provenance_status_check", + "value": "\"embedding_secret_provenance\".\"status\" IN ('exact', 'unknown')" + } + }, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_user_id_user_id_fk": { + "name": "environment_user_id_user_id_fk", + "tableFrom": "environment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_user_id_unique": { + "name": "environment_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.execution_large_value_dependencies": { + "name": "execution_large_value_dependencies", + "schema": "", + "columns": { + "parent_key": { + "name": "parent_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "child_key": { + "name": "child_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "execution_large_value_dependencies_workspace_parent_key_idx": { + "name": "execution_large_value_dependencies_workspace_parent_key_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_value_dependencies_workspace_child_key_idx": { + "name": "execution_large_value_dependencies_workspace_child_key_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "child_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "execution_large_value_dependencies_workspace_id_workspace_id_fk": { + "name": "execution_large_value_dependencies_workspace_id_workspace_id_fk", + "tableFrom": "execution_large_value_dependencies", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "execution_large_value_dependencies_parent_key_child_key_pk": { + "name": "execution_large_value_dependencies_parent_key_child_key_pk", + "columns": [ + "parent_key", + "child_key" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.execution_large_value_references": { + "name": "execution_large_value_references", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "execution_large_value_reference_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "execution_large_value_references_workspace_execution_source_idx": { + "name": "execution_large_value_references_workspace_execution_source_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_value_references_workflow_id_idx": { + "name": "execution_large_value_references_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "execution_large_value_references_workspace_id_workspace_id_fk": { + "name": "execution_large_value_references_workspace_id_workspace_id_fk", + "tableFrom": "execution_large_value_references", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "execution_large_value_references_workflow_id_workflow_id_fk": { + "name": "execution_large_value_references_workflow_id_workflow_id_fk", + "tableFrom": "execution_large_value_references", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "execution_large_value_references_key_execution_id_source_pk": { + "name": "execution_large_value_references_key_execution_id_source_pk", + "columns": [ + "key", + "execution_id", + "source" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.execution_large_values": { + "name": "execution_large_values", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_execution_id": { + "name": "owner_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "execution_large_values_owner_execution_id_idx": { + "name": "execution_large_values_owner_execution_id_idx", + "columns": [ + { + "expression": "owner_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_values_cleanup_idx": { + "name": "execution_large_values_cleanup_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"execution_large_values\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_values_tombstone_cleanup_idx": { + "name": "execution_large_values_tombstone_cleanup_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"execution_large_values\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_values_workflow_id_idx": { + "name": "execution_large_values_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_large_values_workspace_id_idx": { + "name": "execution_large_values_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "execution_large_values_workspace_id_workspace_id_fk": { + "name": "execution_large_values_workspace_id_workspace_id_fk", + "tableFrom": "execution_large_values", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "execution_large_values_workflow_id_workflow_id_fk": { + "name": "execution_large_values_workflow_id_workflow_id_fk", + "tableFrom": "execution_large_values", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.file_search_dependency": { + "name": "file_search_dependency", + "schema": "", + "columns": { + "build_id": { + "name": "build_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_content_updated_at": { + "name": "source_content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "file_search_dependency_file_idx": { + "name": "file_search_dependency_file_idx", + "columns": [ + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "build_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "file_search_dependency_owner_idx": { + "name": "file_search_dependency_owner_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "build_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "file_search_dependency_build_id_workspace_file_search_build_id_fk": { + "name": "file_search_dependency_build_id_workspace_file_search_build_id_fk", + "tableFrom": "file_search_dependency", + "tableTo": "workspace_file_search_build", + "columnsFrom": [ + "build_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "file_search_dependency_build_id_file_id_pk": { + "name": "file_search_dependency_build_id_file_id_pk", + "columns": [ + "build_id", + "file_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.file_search_dispatch_queue": { + "name": "file_search_dispatch_queue", + "schema": "", + "columns": { + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enqueued_at": { + "name": "enqueued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_dispatched_at": { + "name": "last_dispatched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "file_search_dispatch_schedule_idx": { + "name": "file_search_dispatch_schedule_idx", + "columns": [ + { + "expression": "last_dispatched_at", + "isExpression": false, + "asc": true, + "nulls": "first" + }, + { + "expression": "enqueued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "file_search_dispatch_queue_entity_type_entity_id_pk": { + "name": "file_search_dispatch_queue_entity_type_entity_id_pk", + "columns": [ + "entity_type", + "entity_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "file_search_dispatch_owner_check": { + "name": "file_search_dispatch_owner_check", + "value": "\"file_search_dispatch_queue\".\"entity_type\" IN ('workspace', 'project') AND length(\"file_search_dispatch_queue\".\"entity_id\") > 0" + } + }, + "isRLSEnabled": false + }, + "public.folder": { + "name": "folder", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_type": { + "name": "resource_type", + "type": "folder_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "locked": { + "name": "locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "folder_project_id_idx": { + "name": "folder_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "folder_project_resource_parent_name_active_unique": { + "name": "folder_project_resource_parent_name_active_unique", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"parent_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"folder\".\"deleted_at\" IS NULL AND \"folder\".\"project_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "folder_user_idx": { + "name": "folder_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "folder_workspace_resource_parent_idx": { + "name": "folder_workspace_resource_parent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "folder_parent_sort_idx": { + "name": "folder_parent_sort_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "folder_deleted_at_idx": { + "name": "folder_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "folder_workspace_deleted_partial_idx": { + "name": "folder_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"folder\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "folder_workspace_resource_parent_name_active_unique": { + "name": "folder_workspace_resource_parent_name_active_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"parent_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"folder\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "folder_project_id_project_id_fk": { + "name": "folder_project_id_project_id_fk", + "tableFrom": "folder", + "tableTo": "project", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "folder_user_id_user_id_fk": { + "name": "folder_user_id_user_id_fk", + "tableFrom": "folder", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_workspace_id_workspace_id_fk": { + "name": "folder_workspace_id_workspace_id_fk", + "tableFrom": "folder", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_parent_id_folder_id_fk": { + "name": "folder_parent_id_folder_id_fk", + "tableFrom": "folder", + "tableTo": "folder", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "folder_workspace_parent_owner_fk": { + "name": "folder_workspace_parent_owner_fk", + "tableFrom": "folder", + "tableTo": "folder", + "columnsFrom": [ + "parent_id", + "workspace_id", + "resource_type" + ], + "columnsTo": [ + "id", + "workspace_id", + "resource_type" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "folder_project_parent_owner_fk": { + "name": "folder_project_parent_owner_fk", + "tableFrom": "folder", + "tableTo": "folder", + "columnsFrom": [ + "parent_id", + "project_id", + "resource_type" + ], + "columnsTo": [ + "id", + "project_id", + "resource_type" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "folder_workspace_owner_type_unique": { + "name": "folder_workspace_owner_type_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "workspace_id", + "resource_type" + ] + }, + "folder_project_owner_type_unique": { + "name": "folder_project_owner_type_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "project_id", + "resource_type" + ] + } + }, + "policies": {}, + "checkConstraints": { + "folder_owner_check": { + "name": "folder_owner_check", + "value": "num_nonnulls(\"folder\".\"workspace_id\", \"folder\".\"project_id\") = 1 AND (\"folder\".\"project_id\" IS NULL OR \"folder\".\"resource_type\" = 'file')" + } + }, + "isRLSEnabled": false + }, + "public.idempotency_key": { + "name": "idempotency_key", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "result": { + "name": "result", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idempotency_key_created_at_idx": { + "name": "idempotency_key_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "invitation_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'organization'" + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "membership_intent": { + "name": "membership_intent", + "type": "invitation_membership_intent", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'internal'" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_organization_id_idx": { + "name": "invitation_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_status_idx": { + "name": "invitation_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_pending_email_org_unique": { + "name": "invitation_pending_email_org_unique", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"invitation\".\"status\" = 'pending' AND \"invitation\".\"organization_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "invitation_token_unique": { + "name": "invitation_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation_workspace_grant": { + "name": "invitation_workspace_grant", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "invitation_id": { + "name": "invitation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_workspace_grant_unique": { + "name": "invitation_workspace_grant_unique", + "columns": [ + { + "expression": "invitation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_workspace_grant_workspace_id_idx": { + "name": "invitation_workspace_grant_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_workspace_grant_invitation_id_invitation_id_fk": { + "name": "invitation_workspace_grant_invitation_id_invitation_id_fk", + "tableFrom": "invitation_workspace_grant", + "tableTo": "invitation", + "columnsFrom": [ + "invitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_workspace_grant_workspace_id_workspace_id_fk": { + "name": "invitation_workspace_grant_workspace_id_workspace_id_fk", + "tableFrom": "invitation_workspace_grant", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_execution_logs": { + "name": "job_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "schedule_id": { + "name": "schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost": { + "name": "cost", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "occurrence_at": { + "name": "occurrence_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "outcome": { + "name": "outcome", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_request_id": { + "name": "billing_request_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_execution_logs_schedule_occurrence_unique": { + "name": "job_execution_logs_schedule_occurrence_unique", + "columns": [ + { + "expression": "schedule_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurrence_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_billing_request_unique": { + "name": "job_execution_logs_billing_request_unique", + "columns": [ + { + "expression": "billing_request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"job_execution_logs\".\"billing_request_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_open_idx": { + "name": "job_execution_logs_open_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"job_execution_logs\".\"status\" IN ('queued', 'running')", + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_workspace_started_at_idx": { + "name": "job_execution_logs_workspace_started_at_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_workspace_ended_at_id_idx": { + "name": "job_execution_logs_workspace_ended_at_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"ended_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_execution_id_unique": { + "name": "job_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_execution_logs_trigger_idx": { + "name": "job_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_execution_logs_schedule_id_workflow_schedule_id_fk": { + "name": "job_execution_logs_schedule_id_workflow_schedule_id_fk", + "tableFrom": "job_execution_logs", + "tableTo": "workflow_schedule", + "columnsFrom": [ + "schedule_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "job_execution_logs_workspace_id_workspace_id_fk": { + "name": "job_execution_logs_workspace_id_workspace_id_fk", + "tableFrom": "job_execution_logs", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base": { + "name": "knowledge_base", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_search_index": { + "name": "is_search_index", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "embedding_dimension": { + "name": "embedding_dimension", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1536 + }, + "chunking_config": { + "name": "chunking_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_organization_id_idx": { + "name": "kb_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_organization_search_index_unique": { + "name": "kb_organization_search_index_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knowledge_base\".\"is_search_index\" = true AND \"knowledge_base\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_organization_name_active_unique": { + "name": "kb_organization_name_active_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knowledge_base\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_id_idx": { + "name": "kb_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_user_workspace_idx": { + "name": "kb_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_folder_id_idx": { + "name": "kb_folder_id_idx", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_deleted_at_idx": { + "name": "kb_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_deleted_partial_idx": { + "name": "kb_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_base\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_name_active_unique": { + "name": "kb_workspace_name_active_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knowledge_base\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_search_index_unique": { + "name": "kb_workspace_search_index_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knowledge_base\".\"is_search_index\" = true AND \"knowledge_base\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_user_id_user_id_fk": { + "name": "knowledge_base_user_id_user_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_workspace_id_workspace_id_fk": { + "name": "knowledge_base_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_organization_id_organization_id_fk": { + "name": "knowledge_base_organization_id_organization_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_folder_id_folder_id_fk": { + "name": "knowledge_base_folder_id_folder_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "folder", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kb_owner_check": { + "name": "kb_owner_check", + "value": "num_nonnulls(\"knowledge_base\".\"workspace_id\", \"knowledge_base\".\"organization_id\") = 1" + }, + "kb_organization_search_index_check": { + "name": "kb_organization_search_index_check", + "value": "\"knowledge_base\".\"organization_id\" IS NULL OR \"knowledge_base\".\"is_search_index\"" + }, + "kb_organization_folder_check": { + "name": "kb_organization_folder_check", + "value": "\"knowledge_base\".\"organization_id\" IS NULL OR \"knowledge_base\".\"folder_id\" IS NULL" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_base_import": { + "name": "knowledge_base_import", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_key": { + "name": "source_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "documents_total": { + "name": "documents_total", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "documents_imported": { + "name": "documents_imported", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "documents_failed": { + "name": "documents_failed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "vectors_reused": { + "name": "vectors_reused", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "failures": { + "name": "failures", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knowledge_base_import_watchdog_idx": { + "name": "knowledge_base_import_watchdog_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knowledge_base_import_knowledge_base_id_idx": { + "name": "knowledge_base_import_knowledge_base_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_import_workspace_id_workspace_id_fk": { + "name": "knowledge_base_import_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base_import", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_import_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_import_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_import", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_tag_definitions": { + "name": "knowledge_base_tag_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_slot": { + "name": "tag_slot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_type": { + "name": "field_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_tag_definitions_kb_slot_idx": { + "name": "kb_tag_definitions_kb_slot_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag_slot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_display_name_idx": { + "name": "kb_tag_definitions_kb_display_name_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_tag_definitions", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_connector": { + "name": "knowledge_connector", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connector_type": { + "name": "connector_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_api_key": { + "name": "encrypted_api_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_config": { + "name": "source_config", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "sync_mode": { + "name": "sync_mode", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'full'" + }, + "sync_interval_minutes": { + "name": "sync_interval_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1440 + }, + "access_mode": { + "name": "access_mode", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'workspace'" + }, + "credential_group_id": { + "name": "credential_group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_group_option_id": { + "name": "credential_group_option_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "member_sync_status": { + "name": "member_sync_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "member_sync_lock_token": { + "name": "member_sync_lock_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "member_sync_lock_lease_at": { + "name": "member_sync_lock_lease_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_member_sync_at": { + "name": "next_member_sync_at", + "type": "timestamp (3)", + "primaryKey": false, + "notNull": false + }, + "last_member_sync_at": { + "name": "last_member_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_member_sync_error": { + "name": "last_member_sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "member_sync_consecutive_failures": { + "name": "member_sync_consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "access_rewrite_pending": { + "name": "access_rewrite_pending", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image_removal_pending": { + "name": "image_removal_pending", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "member_tombstone_cursor": { + "name": "member_tombstone_cursor", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "member_resurrection_cursor": { + "name": "member_resurrection_cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_sync_error": { + "name": "last_sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_sync_doc_count": { + "name": "last_sync_doc_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "listing_checkpoint": { + "name": "listing_checkpoint", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "directory_checkpoint": { + "name": "directory_checkpoint", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "next_sync_at": { + "name": "next_sync_at", + "type": "timestamp (3)", + "primaryKey": false, + "notNull": false + }, + "next_directory_sync_at": { + "name": "next_directory_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "consecutive_failures": { + "name": "consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "sync_lock_token": { + "name": "sync_lock_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_lock_lease_at": { + "name": "sync_lock_lease_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "detached_at": { + "name": "detached_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "detach_reserved_bytes": { + "name": "detach_reserved_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": { + "kc_knowledge_base_id_idx": { + "name": "kc_knowledge_base_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kc_status_next_sync_idx": { + "name": "kc_status_next_sync_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_sync_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kc_archived_at_partial_idx": { + "name": "kc_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kc_deleted_at_partial_idx": { + "name": "kc_deleted_at_partial_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kc_member_sync_due_idx": { + "name": "kc_member_sync_due_idx", + "columns": [ + { + "expression": "member_sync_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_member_sync_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector\".\"access_mode\" = 'members' AND \"knowledge_connector\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kc_directory_sync_due_idx": { + "name": "kc_directory_sync_due_idx", + "columns": [ + { + "expression": "next_directory_sync_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector\".\"access_mode\" = 'admin' AND \"knowledge_connector\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_connector_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_connector_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_connector", + "tableTo": "knowledge_base", + "columnsFrom": [ + "knowledge_base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_connector_credential_group_id_credential_group_id_fk": { + "name": "knowledge_connector_credential_group_id_credential_group_id_fk", + "tableFrom": "knowledge_connector", + "tableTo": "credential_group", + "columnsFrom": [ + "credential_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kc_access_mode_check": { + "name": "kc_access_mode_check", + "value": "\"knowledge_connector\".\"access_mode\" IN ('workspace', 'members', 'admin')" + }, + "kc_member_sync_status_check": { + "name": "kc_member_sync_status_check", + "value": "\"knowledge_connector\".\"member_sync_status\" IN ('idle', 'pending', 'running', 'error', 'disabled')" + }, + "kc_sync_lock_exclusive_check": { + "name": "kc_sync_lock_exclusive_check", + "value": "NOT (\"knowledge_connector\".\"sync_lock_token\" IS NOT NULL AND \"knowledge_connector\".\"member_sync_lock_token\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_member": { + "name": "knowledge_connector_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject_token": { + "name": "subject_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "consecutive_failures": { + "name": "consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_started_at": { + "name": "last_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_complete_listing_at": { + "name": "last_complete_listing_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_listed_count": { + "name": "last_listed_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "member_synced_through": { + "name": "member_synced_through", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope_renewed_at": { + "name": "scope_renewed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope_renewal_cursor": { + "name": "scope_renewal_cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope_renewal_started_at": { + "name": "scope_renewal_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "change_cursor": { + "name": "change_cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "listing_checkpoint": { + "name": "listing_checkpoint", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kcm_organization_id_idx": { + "name": "kcm_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcm_connector_credential_unique": { + "name": "kcm_connector_credential_unique", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcm_connector_queue_idx": { + "name": "kcm_connector_queue_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "first" + }, + { + "expression": "last_started_at", + "isExpression": false, + "asc": true, + "nulls": "first" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcm_credential_idx": { + "name": "kcm_credential_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_connector_member_workspace_id_workspace_id_fk": { + "name": "knowledge_connector_member_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_connector_member", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_connector_member_organization_id_organization_id_fk": { + "name": "knowledge_connector_member_organization_id_organization_id_fk", + "tableFrom": "knowledge_connector_member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_connector_member_connector_id_knowledge_connector_id_fk": { + "name": "knowledge_connector_member_connector_id_knowledge_connector_id_fk", + "tableFrom": "knowledge_connector_member", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_connector_member_credential_id_credential_id_fk": { + "name": "knowledge_connector_member_credential_id_credential_id_fk", + "tableFrom": "knowledge_connector_member", + "tableTo": "credential", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcm_owner_check": { + "name": "kcm_owner_check", + "value": "num_nonnulls(\"knowledge_connector_member\".\"workspace_id\", \"knowledge_connector_member\".\"organization_id\") = 1" + }, + "kcm_status_check": { + "name": "kcm_status_check", + "value": "\"knowledge_connector_member\".\"status\" IN ('active', 'suspended', 'disabled')" + }, + "kcm_subject_token_shape_check": { + "name": "kcm_subject_token_shape_check", + "value": "\"knowledge_connector_member\".\"subject_token\" ~ '^s:[^:]+:[^:]+:.+$'" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_member_sync_log": { + "name": "knowledge_connector_member_sync_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "members_claimed": { + "name": "members_claimed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "members_completed": { + "name": "members_completed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "members_incomplete": { + "name": "members_incomplete", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "members_failed": { + "name": "members_failed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_failed": { + "name": "docs_failed", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "processing_dispatch_failed": { + "name": "processing_dispatch_failed", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "docs_listed": { + "name": "docs_listed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_added": { + "name": "docs_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_updated": { + "name": "docs_updated", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_unchanged": { + "name": "docs_unchanged", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_hydrated_once": { + "name": "docs_hydrated_once", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "observations_added": { + "name": "observations_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "observations_renewed": { + "name": "observations_renewed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "observations_removed": { + "name": "observations_removed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_tombstoned": { + "name": "docs_tombstoned", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_resurrected": { + "name": "docs_resurrected", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_purged": { + "name": "docs_purged", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "credentials_audited": { + "name": "credentials_audited", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_failure_class": { + "name": "database_failure_class", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "kcmsl_connector_started_at_idx": { + "name": "kcmsl_connector_started_at_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"started_at\" DESC", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcmsl_started_at_partial_idx": { + "name": "kcmsl_started_at_partial_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector_member_sync_log\".\"status\" = 'started'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_connector_member_sync_log_connector_id_knowledge_connector_id_fk": { + "name": "knowledge_connector_member_sync_log_connector_id_knowledge_connector_id_fk", + "tableFrom": "knowledge_connector_member_sync_log", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcmsl_status_check": { + "name": "kcmsl_status_check", + "value": "\"knowledge_connector_member_sync_log\".\"status\" IN ('started', 'partial', 'completed', 'failed')" + }, + "kcmsl_database_failure_class_check": { + "name": "kcmsl_database_failure_class_check", + "value": "\"knowledge_connector_member_sync_log\".\"database_failure_class\" IN ('capacity', 'conflict', 'connection')" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_partition": { + "name": "knowledge_connector_partition", + "schema": "", + "columns": { + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "partition_key": { + "name": "partition_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "generation_id": { + "name": "generation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context": { + "name": "context", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "cursor": { + "name": "cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry_at": { + "name": "retry_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_served_at": { + "name": "last_served_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure": { + "name": "failure", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "permission_cursor": { + "name": "permission_cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "permission_attempts": { + "name": "permission_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "permission_retry_at": { + "name": "permission_retry_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permission_last_served_at": { + "name": "permission_last_served_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "permission_started_at": { + "name": "permission_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "permission_failure": { + "name": "permission_failure", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "kcp_content_due_idx": { + "name": "kcp_content_due_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "generation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "retry_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_served_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcp_permission_due_idx": { + "name": "kcp_permission_due_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "generation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_retry_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_last_served_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_connector_partition_connector_id_knowledge_connector_id_fk": { + "name": "knowledge_connector_partition_connector_id_knowledge_connector_id_fk", + "tableFrom": "knowledge_connector_partition", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "kcp_pk": { + "name": "kcp_pk", + "columns": [ + "connector_id", + "partition_key" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcp_partition_key_check": { + "name": "kcp_partition_key_check", + "value": "octet_length(\"knowledge_connector_partition\".\"partition_key\") BETWEEN 1 AND 1024" + }, + "kcp_context_check": { + "name": "kcp_context_check", + "value": "jsonb_typeof(\"knowledge_connector_partition\".\"context\") = 'object' AND octet_length(\"knowledge_connector_partition\".\"context\"::text) <= 16384" + }, + "kcp_status_check": { + "name": "kcp_status_check", + "value": "\"knowledge_connector_partition\".\"status\" IN ('pending', 'complete', 'blocked')" + }, + "kcp_cursor_check": { + "name": "kcp_cursor_check", + "value": "(\"knowledge_connector_partition\".\"cursor\" IS NULL OR octet_length(\"knowledge_connector_partition\".\"cursor\") <= 393216) AND (\"knowledge_connector_partition\".\"permission_cursor\" IS NULL OR octet_length(\"knowledge_connector_partition\".\"permission_cursor\") <= 393216)" + }, + "kcp_attempts_check": { + "name": "kcp_attempts_check", + "value": "\"knowledge_connector_partition\".\"attempts\" >= 0 AND \"knowledge_connector_partition\".\"permission_attempts\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_permission_grant": { + "name": "knowledge_connector_permission_grant", + "schema": "", + "columns": { + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_key": { + "name": "group_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject_token": { + "name": "subject_token", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "kcpg_subject_idx": { + "name": "kcpg_subject_idx", + "columns": [ + { + "expression": "subject_token", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "group_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "kcpg_snapshot_fk": { + "name": "kcpg_snapshot_fk", + "tableFrom": "knowledge_connector_permission_grant", + "tableTo": "knowledge_connector_permission_snapshot", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "connector_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "kcpg_pk": { + "name": "kcpg_pk", + "columns": [ + "connector_id", + "group_key", + "subject_token" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcpg_group_check": { + "name": "kcpg_group_check", + "value": "length(\"knowledge_connector_permission_grant\".\"group_key\") BETWEEN 1 AND 255" + }, + "kcpg_subject_check": { + "name": "kcpg_subject_check", + "value": "\"knowledge_connector_permission_grant\".\"subject_token\" ~ '^u:[^[:space:]A-Z]+@[^[:space:]A-Z]+$'" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_permission_snapshot": { + "name": "knowledge_connector_permission_snapshot", + "schema": "", + "columns": { + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "kcps_connector_fk": { + "name": "kcps_connector_fk", + "tableFrom": "knowledge_connector_permission_snapshot", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcps_revision_check": { + "name": "kcps_revision_check", + "value": "\"knowledge_connector_permission_snapshot\".\"revision\" > 0" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_connector_sync_log": { + "name": "knowledge_connector_sync_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connector_id": { + "name": "connector_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "docs_added": { + "name": "docs_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_updated": { + "name": "docs_updated", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_deleted": { + "name": "docs_deleted", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_unchanged": { + "name": "docs_unchanged", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_skipped": { + "name": "docs_skipped", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "docs_failed": { + "name": "docs_failed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "listed_count": { + "name": "listed_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "database_failure_class": { + "name": "database_failure_class", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "kcsl_connector_started_at_idx": { + "name": "kcsl_connector_started_at_idx", + "columns": [ + { + "expression": "connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"started_at\" DESC", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcsl_started_at_partial_idx": { + "name": "kcsl_started_at_partial_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector_sync_log\".\"status\" = 'started'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "kcsl_terminal_started_at_idx": { + "name": "kcsl_terminal_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knowledge_connector_sync_log\".\"status\" IN ('completed', 'failed')", + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_connector_sync_log_connector_id_knowledge_connector_id_fk": { + "name": "knowledge_connector_sync_log_connector_id_knowledge_connector_id_fk", + "tableFrom": "knowledge_connector_sync_log", + "tableTo": "knowledge_connector", + "columnsFrom": [ + "connector_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "kcsl_database_failure_class_check": { + "name": "kcsl_database_failure_class_check", + "value": "\"knowledge_connector_sync_log\".\"database_failure_class\" IN ('capacity', 'conflict', 'connection')" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_document_observation": { + "name": "knowledge_document_observation", + "schema": "", + "columns": { + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "member_id": { + "name": "member_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "kdo_member_idx": { + "name": "kdo_member_idx", + "columns": [ + { + "expression": "member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_document_observation_document_id_document_id_fk": { + "name": "knowledge_document_observation_document_id_document_id_fk", + "tableFrom": "knowledge_document_observation", + "tableTo": "document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_document_observation_member_id_knowledge_connector_member_id_fk": { + "name": "knowledge_document_observation_member_id_knowledge_connector_member_id_fk", + "tableFrom": "knowledge_document_observation", + "tableTo": "knowledge_connector_member", + "columnsFrom": [ + "member_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knowledge_document_observation_document_id_member_id_pk": { + "name": "knowledge_document_observation_document_id_member_id_pk", + "columns": [ + "document_id", + "member_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_external_directory": { + "name": "knowledge_external_directory", + "schema": "", + "columns": { + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sync_lock_token": { + "name": "sync_lock_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_lock_lease_at": { + "name": "sync_lock_lease_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_started_at": { + "name": "last_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_complete_sync_at": { + "name": "last_complete_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "ked_workspace_identity_unique": { + "name": "ked_workspace_identity_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "ked_organization_identity_unique": { + "name": "ked_organization_identity_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_external_directory_workspace_id_workspace_id_fk": { + "name": "knowledge_external_directory_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_external_directory", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_external_directory_organization_id_organization_id_fk": { + "name": "knowledge_external_directory_organization_id_organization_id_fk", + "tableFrom": "knowledge_external_directory", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "ked_owner_check": { + "name": "ked_owner_check", + "value": "num_nonnulls(\"knowledge_external_directory\".\"workspace_id\", \"knowledge_external_directory\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_external_group": { + "name": "knowledge_external_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_group_id": { + "name": "external_group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "keg_organization_identity_unique": { + "name": "keg_organization_identity_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "keg_organization_synced_idx": { + "name": "keg_organization_synced_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_synced_at", + "isExpression": false, + "asc": true, + "nulls": "first" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "keg_identity_unique": { + "name": "keg_identity_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "keg_workspace_synced_idx": { + "name": "keg_workspace_synced_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_synced_at", + "isExpression": false, + "asc": true, + "nulls": "first" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_external_group_organization_id_organization_id_fk": { + "name": "knowledge_external_group_organization_id_organization_id_fk", + "tableFrom": "knowledge_external_group", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "keg_workspace_fk": { + "name": "keg_workspace_fk", + "tableFrom": "knowledge_external_group", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "keg_owner_check": { + "name": "keg_owner_check", + "value": "num_nonnulls(\"knowledge_external_group\".\"workspace_id\", \"knowledge_external_group\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.knowledge_external_group_member": { + "name": "knowledge_external_group_member", + "schema": "", + "columns": { + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject_token": { + "name": "subject_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kegm_subject_token_idx": { + "name": "kegm_subject_token_idx", + "columns": [ + { + "expression": "subject_token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "kegm_group_fk": { + "name": "kegm_group_fk", + "tableFrom": "knowledge_external_group_member", + "tableTo": "knowledge_external_group", + "columnsFrom": [ + "group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knowledge_external_group_member_group_id_subject_token_pk": { + "name": "knowledge_external_group_member_group_id_subject_token_pk", + "columns": [ + "group_id", + "subject_token" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_projection_dirty": { + "name": "knowledge_projection_dirty", + "schema": "", + "columns": { + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "generation": { + "name": "generation", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "content": { + "name": "content", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "marked_at": { + "name": "marked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knowledge_projection_dirty_marked_at_idx": { + "name": "knowledge_projection_dirty_marked_at_idx", + "columns": [ + { + "expression": "marked_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_projection_dirty_document_id_document_id_fk": { + "name": "knowledge_projection_dirty_document_id_document_id_fk", + "tableFrom": "knowledge_projection_dirty", + "tableTo": "document", + "columnsFrom": [ + "document_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mcp_server_oauth": { + "name": "mcp_server_oauth", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "mcp_server_id": { + "name": "mcp_server_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_information": { + "name": "client_information", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tokens": { + "name": "tokens", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "code_verifier": { + "name": "code_verifier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state_created_at": { + "name": "state_created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_refreshed_at": { + "name": "last_refreshed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_server_oauth_server_unique": { + "name": "mcp_server_oauth_server_unique", + "columns": [ + { + "expression": "mcp_server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_server_oauth_state_idx": { + "name": "mcp_server_oauth_state_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_server_oauth_mcp_server_id_mcp_servers_id_fk": { + "name": "mcp_server_oauth_mcp_server_id_mcp_servers_id_fk", + "tableFrom": "mcp_server_oauth", + "tableTo": "mcp_servers", + "columnsFrom": [ + "mcp_server_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_server_oauth_user_id_user_id_fk": { + "name": "mcp_server_oauth_user_id_user_id_fk", + "tableFrom": "mcp_server_oauth", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "mcp_server_oauth_workspace_id_workspace_id_fk": { + "name": "mcp_server_oauth_workspace_id_workspace_id_fk", + "tableFrom": "mcp_server_oauth", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_server_oauth_organization_id_organization_id_fk": { + "name": "mcp_server_oauth_organization_id_organization_id_fk", + "tableFrom": "mcp_server_oauth", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "mcp_server_oauth_owner_check": { + "name": "mcp_server_oauth_owner_check", + "value": "num_nonnulls(\"mcp_server_oauth\".\"workspace_id\", \"mcp_server_oauth\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.mcp_servers": { + "name": "mcp_servers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_group_id": { + "name": "credential_group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "managed_connector_id": { + "name": "managed_connector_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oauth_config_version": { + "name": "oauth_config_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transport": { + "name": "transport", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'headers'" + }, + "oauth_client_id": { + "name": "oauth_client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oauth_client_secret": { + "name": "oauth_client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "headers": { + "name": "headers", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30000 + }, + "retries": { + "name": "retries", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_connected": { + "name": "last_connected", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "connection_status": { + "name": "connection_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'disconnected'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status_config": { + "name": "status_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "tool_count": { + "name": "tool_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_tools_refresh": { + "name": "last_tools_refresh", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_requests": { + "name": "total_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_servers_organization_id_idx": { + "name": "mcp_servers_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_enabled_idx": { + "name": "mcp_servers_workspace_enabled_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_credential_group_idx": { + "name": "mcp_servers_credential_group_idx", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_credential_group_managed_connector_unique": { + "name": "mcp_servers_credential_group_managed_connector_unique", + "columns": [ + { + "expression": "credential_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "managed_connector_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"mcp_servers\".\"credential_group_id\" IS NOT NULL AND \"mcp_servers\".\"managed_connector_id\" IS NOT NULL AND \"mcp_servers\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_deleted_partial_idx": { + "name": "mcp_servers_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"mcp_servers\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_servers_workspace_id_workspace_id_fk": { + "name": "mcp_servers_workspace_id_workspace_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_organization_id_organization_id_fk": { + "name": "mcp_servers_organization_id_organization_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_credential_group_id_credential_group_id_fk": { + "name": "mcp_servers_credential_group_id_credential_group_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "credential_group", + "columnsFrom": [ + "credential_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "mcp_servers_created_by_user_id_fk": { + "name": "mcp_servers_created_by_user_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "mcp_servers_owner_check": { + "name": "mcp_servers_owner_check", + "value": "num_nonnulls(\"mcp_servers\".\"workspace_id\", \"mcp_servers\".\"organization_id\") = 1" + }, + "mcp_servers_organization_managed_check": { + "name": "mcp_servers_organization_managed_check", + "value": "\"mcp_servers\".\"organization_id\" IS NULL OR \"mcp_servers\".\"credential_group_id\" IS NOT NULL" + }, + "mcp_servers_credential_group_managed_connector_check": { + "name": "mcp_servers_credential_group_managed_connector_check", + "value": "\"mcp_servers\".\"credential_group_id\" IS NULL OR \"mcp_servers\".\"managed_connector_id\" IS NOT NULL" + }, + "mcp_servers_managed_connector_oauth_check": { + "name": "mcp_servers_managed_connector_oauth_check", + "value": "\"mcp_servers\".\"managed_connector_id\" IS NULL OR \"mcp_servers\".\"auth_type\" = 'oauth'" + } + }, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_user_id_unique": { + "name": "member_user_id_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_organization_id_idx": { + "name": "member_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member_profile": { + "name": "member_profile", + "schema": "", + "columns": { + "member_id": { + "name": "member_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "department": { + "name": "department", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start_date": { + "name": "start_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "manager_member_id": { + "name": "manager_member_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_profile_manager_member_id_idx": { + "name": "member_profile_manager_member_id_idx", + "columns": [ + { + "expression": "manager_member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_profile_updated_by_idx": { + "name": "member_profile_updated_by_idx", + "columns": [ + { + "expression": "updated_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_profile_member_id_member_id_fk": { + "name": "member_profile_member_id_member_id_fk", + "tableFrom": "member_profile", + "tableTo": "member", + "columnsFrom": [ + "member_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_profile_manager_member_id_member_id_fk": { + "name": "member_profile_manager_member_id_member_id_fk", + "tableFrom": "member_profile", + "tableTo": "member", + "columnsFrom": [ + "manager_member_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "member_profile_updated_by_user_id_fk": { + "name": "member_profile_updated_by_user_id_fk", + "tableFrom": "member_profile", + "tableTo": "user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "member_profile_not_own_manager": { + "name": "member_profile_not_own_manager", + "value": "\"member_profile\".\"manager_member_id\" <> \"member_profile\".\"member_id\"" + } + }, + "isRLSEnabled": false + }, + "public.memory": { + "name": "memory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "storage_version": { + "name": "storage_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "encrypted_context_summary": { + "name": "encrypted_context_summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_provenance_version": { + "name": "secret_provenance_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "memory_key_idx": { + "name": "memory_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workspace_key_idx": { + "name": "memory_workspace_key_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workspace_deleted_partial_idx": { + "name": "memory_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"memory\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_workspace_id_workspace_id_fk": { + "name": "memory_workspace_id_workspace_id_fk", + "tableFrom": "memory", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory_artifact": { + "name": "memory_artifact", + "schema": "", + "columns": { + "memory_id": { + "name": "memory_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "memory_artifact_key_idx": { + "name": "memory_artifact_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_artifact_memory_id_memory_id_fk": { + "name": "memory_artifact_memory_id_memory_id_fk", + "tableFrom": "memory_artifact", + "tableTo": "memory", + "columnsFrom": [ + "memory_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "memory_artifact_key_execution_large_values_key_fk": { + "name": "memory_artifact_key_execution_large_values_key_fk", + "tableFrom": "memory_artifact", + "tableTo": "execution_large_values", + "columnsFrom": [ + "key" + ], + "columnsTo": [ + "key" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "memory_artifact_memory_id_key_pk": { + "name": "memory_artifact_memory_id_key_pk", + "columns": [ + "memory_id", + "key" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory_item": { + "name": "memory_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "memory_id": { + "name": "memory_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sequence": { + "name": "sequence", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "memory_item_sequence_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "append_key": { + "name": "append_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "turn_id": { + "name": "turn_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provenance_status": { + "name": "provenance_status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provenance_entries": { + "name": "provenance_entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "memory_item_append_unique": { + "name": "memory_item_append_unique", + "columns": [ + { + "expression": "memory_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "append_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_item_sequence_idx": { + "name": "memory_item_sequence_idx", + "columns": [ + { + "expression": "memory_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sequence", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_item_memory_id_memory_id_fk": { + "name": "memory_item_memory_id_memory_id_fk", + "tableFrom": "memory_item", + "tableTo": "memory", + "columnsFrom": [ + "memory_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "memory_item_kind_check": { + "name": "memory_item_kind_check", + "value": "\"memory_item\".\"kind\" IN ('message', 'exchange')" + }, + "memory_item_provenance_status_check": { + "name": "memory_item_provenance_status_check", + "value": "\"memory_item\".\"provenance_status\" IN ('exact', 'unknown')" + } + }, + "isRLSEnabled": false + }, + "public.memory_secret_provenance": { + "name": "memory_secret_provenance", + "schema": "", + "columns": { + "memory_id": { + "name": "memory_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entries": { + "name": "entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "memory_secret_provenance_memory_id_memory_id_fk": { + "name": "memory_secret_provenance_memory_id_memory_id_fk", + "tableFrom": "memory_secret_provenance", + "tableTo": "memory", + "columnsFrom": [ + "memory_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "memory_secret_provenance_status_check": { + "name": "memory_secret_provenance_status_check", + "value": "\"memory_secret_provenance\".\"status\" IN ('exact', 'unknown')" + } + }, + "isRLSEnabled": false + }, + "public.mothership_benchmark_runs": { + "name": "mothership_benchmark_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "benchmark_id": { + "name": "benchmark_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "evaluation_key": { + "name": "evaluation_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reviews": { + "name": "reviews", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "reviewed_at": { + "name": "reviewed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "correct": { + "name": "correct", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "automatic_correct": { + "name": "automatic_correct", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "total": { + "name": "total", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "artifacts": { + "name": "artifacts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mothership_benchmark_runs_benchmark_created_idx": { + "name": "mothership_benchmark_runs_benchmark_created_idx", + "columns": [ + { + "expression": "benchmark_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mothership_benchmark_runs_benchmark_id_mothership_benchmarks_id_fk": { + "name": "mothership_benchmark_runs_benchmark_id_mothership_benchmarks_id_fk", + "tableFrom": "mothership_benchmark_runs", + "tableTo": "mothership_benchmarks", + "columnsFrom": [ + "benchmark_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "mothership_benchmark_runs_score_check": { + "name": "mothership_benchmark_runs_score_check", + "value": "\"mothership_benchmark_runs\".\"total\" > 0 AND \"mothership_benchmark_runs\".\"correct\" >= 0 AND \"mothership_benchmark_runs\".\"correct\" <= \"mothership_benchmark_runs\".\"total\"" + }, + "mothership_benchmark_runs_version_check": { + "name": "mothership_benchmark_runs_version_check", + "value": "\"mothership_benchmark_runs\".\"version\" > 0" + }, + "mothership_benchmark_runs_automatic_score_check": { + "name": "mothership_benchmark_runs_automatic_score_check", + "value": "\"mothership_benchmark_runs\".\"automatic_correct\" >= 0 AND \"mothership_benchmark_runs\".\"automatic_correct\" <= \"mothership_benchmark_runs\".\"total\"" + } + }, + "isRLSEnabled": false + }, + "public.mothership_benchmarks": { + "name": "mothership_benchmarks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "run_as_user_id": { + "name": "run_as_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_workspace_id": { + "name": "source_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "artifacts": { + "name": "artifacts", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "running_stage": { + "name": "running_stage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "attempt_id": { + "name": "attempt_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "planner_chat_id": { + "name": "planner_chat_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mothership_benchmarks_owner_created_idx": { + "name": "mothership_benchmarks_owner_created_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mothership_benchmarks_workspace_idx": { + "name": "mothership_benchmarks_workspace_idx", + "columns": [ + { + "expression": "source_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mothership_benchmarks_organization_id_organization_id_fk": { + "name": "mothership_benchmarks_organization_id_organization_id_fk", + "tableFrom": "mothership_benchmarks", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_benchmarks_user_id_user_id_fk": { + "name": "mothership_benchmarks_user_id_user_id_fk", + "tableFrom": "mothership_benchmarks", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_benchmarks_run_as_user_id_user_id_fk": { + "name": "mothership_benchmarks_run_as_user_id_user_id_fk", + "tableFrom": "mothership_benchmarks", + "tableTo": "user", + "columnsFrom": [ + "run_as_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_benchmarks_source_workspace_id_workspace_id_fk": { + "name": "mothership_benchmarks_source_workspace_id_workspace_id_fk", + "tableFrom": "mothership_benchmarks", + "tableTo": "workspace", + "columnsFrom": [ + "source_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "mothership_benchmarks_version_check": { + "name": "mothership_benchmarks_version_check", + "value": "\"mothership_benchmarks\".\"version\" > 0" + }, + "mothership_benchmarks_attempt_check": { + "name": "mothership_benchmarks_attempt_check", + "value": "(\"mothership_benchmarks\".\"running_stage\" IS NULL AND \"mothership_benchmarks\".\"attempt_id\" IS NULL AND \"mothership_benchmarks\".\"lease_expires_at\" IS NULL) OR (\"mothership_benchmarks\".\"running_stage\" IS NOT NULL AND \"mothership_benchmarks\".\"running_stage\" IN ('distill', 'redact', 'plan', 'reconstruct', 'grade') AND \"mothership_benchmarks\".\"attempt_id\" IS NOT NULL AND \"mothership_benchmarks\".\"lease_expires_at\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.mothership_inbox_allowed_sender": { + "name": "mothership_inbox_allowed_sender", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "added_by": { + "name": "added_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "inbox_sender_ws_email_idx": { + "name": "inbox_sender_ws_email_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mothership_inbox_allowed_sender_workspace_id_workspace_id_fk": { + "name": "mothership_inbox_allowed_sender_workspace_id_workspace_id_fk", + "tableFrom": "mothership_inbox_allowed_sender", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_inbox_allowed_sender_added_by_user_id_fk": { + "name": "mothership_inbox_allowed_sender_added_by_user_id_fk", + "tableFrom": "mothership_inbox_allowed_sender", + "tableTo": "user", + "columnsFrom": [ + "added_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mothership_inbox_task": { + "name": "mothership_inbox_task", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "from_email": { + "name": "from_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "from_name": { + "name": "from_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "body_preview": { + "name": "body_preview", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body_text": { + "name": "body_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body_html": { + "name": "body_html", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email_message_id": { + "name": "email_message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "in_reply_to": { + "name": "in_reply_to", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "response_message_id": { + "name": "response_message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agentmail_message_id": { + "name": "agentmail_message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'received'" + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "trigger_job_id": { + "name": "trigger_job_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "result_summary": { + "name": "result_summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rejection_reason": { + "name": "rejection_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "has_attachments": { + "name": "has_attachments", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "cc_recipients": { + "name": "cc_recipients", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "inbox_task_ws_created_at_idx": { + "name": "inbox_task_ws_created_at_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "inbox_task_ws_status_idx": { + "name": "inbox_task_ws_status_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "inbox_task_response_msg_id_idx": { + "name": "inbox_task_response_msg_id_idx", + "columns": [ + { + "expression": "response_message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "inbox_task_email_msg_id_idx": { + "name": "inbox_task_email_msg_id_idx", + "columns": [ + { + "expression": "email_message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mothership_inbox_task_workspace_id_workspace_id_fk": { + "name": "mothership_inbox_task_workspace_id_workspace_id_fk", + "tableFrom": "mothership_inbox_task", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_inbox_task_chat_id_copilot_chats_id_fk": { + "name": "mothership_inbox_task_chat_id_copilot_chats_id_fk", + "tableFrom": "mothership_inbox_task", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mothership_inbox_webhook": { + "name": "mothership_inbox_webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "webhook_id": { + "name": "webhook_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "mothership_inbox_webhook_workspace_id_workspace_id_fk": { + "name": "mothership_inbox_webhook_workspace_id_workspace_id_fk", + "tableFrom": "mothership_inbox_webhook", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mothership_inbox_webhook_workspace_id_unique": { + "name": "mothership_inbox_webhook_workspace_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workspace_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mothership_memory_selections": { + "name": "mothership_memory_selections", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "space_id": { + "name": "space_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mothership_memory_selections_user_id_user_id_fk": { + "name": "mothership_memory_selections_user_id_user_id_fk", + "tableFrom": "mothership_memory_selections", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_memory_selections_organization_id_organization_id_fk": { + "name": "mothership_memory_selections_organization_id_organization_id_fk", + "tableFrom": "mothership_memory_selections", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_memory_selections_space_id_mothership_memory_spaces_id_fk": { + "name": "mothership_memory_selections_space_id_mothership_memory_spaces_id_fk", + "tableFrom": "mothership_memory_selections", + "tableTo": "mothership_memory_spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "mothership_memory_selections_user_id_organization_id_pk": { + "name": "mothership_memory_selections_user_id_organization_id_pk", + "columns": [ + "user_id", + "organization_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mothership_memory_spaces": { + "name": "mothership_memory_spaces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mothership_memory_spaces_owner_idx": { + "name": "mothership_memory_spaces_owner_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mothership_memory_spaces_user_id_user_id_fk": { + "name": "mothership_memory_spaces_user_id_user_id_fk", + "tableFrom": "mothership_memory_spaces", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mothership_memory_spaces_organization_id_organization_id_fk": { + "name": "mothership_memory_spaces_organization_id_organization_id_fk", + "tableFrom": "mothership_memory_spaces", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mothership_resource_effects": { + "name": "mothership_resource_effects", + "schema": "", + "columns": { + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "effect_id": { + "name": "effect_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "mothership_resource_effects_chat_id_copilot_chats_id_fk": { + "name": "mothership_resource_effects_chat_id_copilot_chats_id_fk", + "tableFrom": "mothership_resource_effects", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "mothership_resource_effects_chat_id_effect_id_pk": { + "name": "mothership_resource_effects_chat_id_effect_id_pk", + "columns": [ + "chat_id", + "effect_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.oauth_access_token": { + "name": "oauth_access_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_id": { + "name": "refresh_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "resource": { + "name": "resource", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "oauth_access_token_client_id_idx": { + "name": "oauth_access_token_client_id_idx", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_access_token_session_id_idx": { + "name": "oauth_access_token_session_id_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_access_token_refresh_id_idx": { + "name": "oauth_access_token_refresh_id_idx", + "columns": [ + { + "expression": "refresh_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_access_token_user_client_idx": { + "name": "oauth_access_token_user_client_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_access_token_expires_at_idx": { + "name": "oauth_access_token_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "oauth_access_token_client_id_oauth_client_client_id_fk": { + "name": "oauth_access_token_client_id_oauth_client_client_id_fk", + "tableFrom": "oauth_access_token", + "tableTo": "oauth_client", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_access_token_session_id_session_id_fk": { + "name": "oauth_access_token_session_id_session_id_fk", + "tableFrom": "oauth_access_token", + "tableTo": "session", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "oauth_access_token_user_id_user_id_fk": { + "name": "oauth_access_token_user_id_user_id_fk", + "tableFrom": "oauth_access_token", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_access_token_refresh_id_oauth_refresh_token_id_fk": { + "name": "oauth_access_token_refresh_id_oauth_refresh_token_id_fk", + "tableFrom": "oauth_access_token", + "tableTo": "oauth_refresh_token", + "columnsFrom": [ + "refresh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_access_token_token_unique": { + "name": "oauth_access_token_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": { + "oauth_access_token_search_resource_check": { + "name": "oauth_access_token_search_resource_check", + "value": "NOT ('search:read' = ANY(\"oauth_access_token\".\"scopes\")) OR \"oauth_access_token\".\"resource\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.oauth_client": { + "name": "oauth_client", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "skip_consent": { + "name": "skip_consent", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "enable_end_session": { + "name": "enable_end_session", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "subject_type": { + "name": "subject_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contacts": { + "name": "contacts", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "tos": { + "name": "tos", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "policy": { + "name": "policy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_id": { + "name": "software_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_version": { + "name": "software_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_statement": { + "name": "software_statement", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redirect_uris": { + "name": "redirect_uris", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "post_logout_redirect_uris": { + "name": "post_logout_redirect_uris", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "token_endpoint_auth_method": { + "name": "token_endpoint_auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "grant_types": { + "name": "grant_types", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "response_types": { + "name": "response_types", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "public": { + "name": "public", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "require_pkce": { + "name": "require_pkce", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "oauth_client_user_id_idx": { + "name": "oauth_client_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "oauth_client_user_id_user_id_fk": { + "name": "oauth_client_user_id_user_id_fk", + "tableFrom": "oauth_client", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_client_client_id_unique": { + "name": "oauth_client_client_id_unique", + "nullsNotDistinct": false, + "columns": [ + "client_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.oauth_consent": { + "name": "oauth_consent", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "oauth_consent_client_id_idx": { + "name": "oauth_consent_client_id_idx", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "oauth_consent_client_id_oauth_client_client_id_fk": { + "name": "oauth_consent_client_id_oauth_client_client_id_fk", + "tableFrom": "oauth_consent", + "tableTo": "oauth_client", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_consent_user_id_user_id_fk": { + "name": "oauth_consent_user_id_user_id_fk", + "tableFrom": "oauth_consent", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_consent_user_client_reference_unique": { + "name": "oauth_consent_user_client_reference_unique", + "nullsNotDistinct": true, + "columns": [ + "user_id", + "client_id", + "reference_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.oauth_refresh_token": { + "name": "oauth_refresh_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "revoked": { + "name": "revoked", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "auth_time": { + "name": "auth_time", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "resource": { + "name": "resource", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "family_id": { + "name": "family_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "generation": { + "name": "generation", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "oauth_refresh_token_client_id_idx": { + "name": "oauth_refresh_token_client_id_idx", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_refresh_token_session_id_idx": { + "name": "oauth_refresh_token_session_id_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_refresh_token_user_client_idx": { + "name": "oauth_refresh_token_user_client_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_refresh_token_expires_at_idx": { + "name": "oauth_refresh_token_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "oauth_refresh_token_client_id_oauth_client_client_id_fk": { + "name": "oauth_refresh_token_client_id_oauth_client_client_id_fk", + "tableFrom": "oauth_refresh_token", + "tableTo": "oauth_client", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_refresh_token_session_id_session_id_fk": { + "name": "oauth_refresh_token_session_id_session_id_fk", + "tableFrom": "oauth_refresh_token", + "tableTo": "session", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "oauth_refresh_token_user_id_user_id_fk": { + "name": "oauth_refresh_token_user_id_user_id_fk", + "tableFrom": "oauth_refresh_token", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_refresh_token_family_id_oauth_token_family_id_fk": { + "name": "oauth_refresh_token_family_id_oauth_token_family_id_fk", + "tableFrom": "oauth_refresh_token", + "tableTo": "oauth_token_family", + "columnsFrom": [ + "family_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_refresh_token_token_unique": { + "name": "oauth_refresh_token_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + }, + "oauth_refresh_token_family_generation_unique": { + "name": "oauth_refresh_token_family_generation_unique", + "nullsNotDistinct": false, + "columns": [ + "family_id", + "generation" + ] + } + }, + "policies": {}, + "checkConstraints": { + "oauth_refresh_token_generation_check": { + "name": "oauth_refresh_token_generation_check", + "value": "\"oauth_refresh_token\".\"generation\" BETWEEN 0 AND 1000" + }, + "oauth_refresh_token_search_resource_check": { + "name": "oauth_refresh_token_search_resource_check", + "value": "NOT ('search:read' = ANY(\"oauth_refresh_token\".\"scopes\")) OR \"oauth_refresh_token\".\"resource\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.oauth_token_family": { + "name": "oauth_token_family", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "consent_id": { + "name": "consent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "current_generation": { + "name": "current_generation", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "oauth_token_family_client_id_idx": { + "name": "oauth_token_family_client_id_idx", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_token_family_session_id_idx": { + "name": "oauth_token_family_session_id_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_token_family_user_client_idx": { + "name": "oauth_token_family_user_client_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_token_family_consent_id_idx": { + "name": "oauth_token_family_consent_id_idx", + "columns": [ + { + "expression": "consent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "oauth_token_family_expires_at_idx": { + "name": "oauth_token_family_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "oauth_token_family_client_id_oauth_client_client_id_fk": { + "name": "oauth_token_family_client_id_oauth_client_client_id_fk", + "tableFrom": "oauth_token_family", + "tableTo": "oauth_client", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_token_family_session_id_session_id_fk": { + "name": "oauth_token_family_session_id_session_id_fk", + "tableFrom": "oauth_token_family", + "tableTo": "session", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "oauth_token_family_user_id_user_id_fk": { + "name": "oauth_token_family_user_id_user_id_fk", + "tableFrom": "oauth_token_family", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_token_family_consent_id_oauth_consent_id_fk": { + "name": "oauth_token_family_consent_id_oauth_consent_id_fk", + "tableFrom": "oauth_token_family", + "tableTo": "oauth_consent", + "columnsFrom": [ + "consent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "oauth_token_family_generation_check": { + "name": "oauth_token_family_generation_check", + "value": "\"oauth_token_family\".\"current_generation\" BETWEEN 0 AND 1000" + } + }, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "session_policy_settings": { + "name": "session_policy_settings", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "security_policy_version": { + "name": "security_policy_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "require_sso": { + "name": "require_sso", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "whitelabel_settings": { + "name": "whitelabel_settings", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "data_retention_settings": { + "name": "data_retention_settings", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "org_usage_limit": { + "name": "org_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "limit_notifications": { + "name": "limit_notifications", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_access_request_settings": { + "name": "organization_access_request_settings", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "allow_requests": { + "name": "allow_requests", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "organization_access_request_settings_organization_id_organization_id_fk": { + "name": "organization_access_request_settings_organization_id_organization_id_fk", + "tableFrom": "organization_access_request_settings", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_access_request_settings_updated_by_user_id_fk": { + "name": "organization_access_request_settings_updated_by_user_id_fk", + "tableFrom": "organization_access_request_settings", + "tableTo": "user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_byok_keys": { + "name": "organization_byok_keys", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encrypted_api_key": { + "name": "encrypted_api_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_byok_organization_provider_idx": { + "name": "organization_byok_organization_provider_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_byok_keys_organization_id_organization_id_fk": { + "name": "organization_byok_keys_organization_id_organization_id_fk", + "tableFrom": "organization_byok_keys", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_byok_keys_created_by_user_id_fk": { + "name": "organization_byok_keys_created_by_user_id_fk", + "tableFrom": "organization_byok_keys", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_member_usage_limit": { + "name": "organization_member_usage_limit", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "usage_limit": { + "name": "usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "set_by": { + "name": "set_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "org_member_usage_limit_org_user_unique": { + "name": "org_member_usage_limit_org_user_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "org_member_usage_limit_organization_id_idx": { + "name": "org_member_usage_limit_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_member_usage_limit_organization_id_organization_id_fk": { + "name": "organization_member_usage_limit_organization_id_organization_id_fk", + "tableFrom": "organization_member_usage_limit", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_member_usage_limit_user_id_user_id_fk": { + "name": "organization_member_usage_limit_user_id_user_id_fk", + "tableFrom": "organization_member_usage_limit", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_member_usage_limit_set_by_user_id_fk": { + "name": "organization_member_usage_limit_set_by_user_id_fk", + "tableFrom": "organization_member_usage_limit", + "tableTo": "user", + "columnsFrom": [ + "set_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_search_history": { + "name": "organization_search_history", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sources": { + "name": "sources", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "queries": { + "name": "queries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": { + "organization_search_history_user_idx": { + "name": "organization_search_history_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_search_history_organization_id_organization_id_fk": { + "name": "organization_search_history_organization_id_organization_id_fk", + "tableFrom": "organization_search_history", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_search_history_user_id_user_id_fk": { + "name": "organization_search_history_user_id_user_id_fk", + "tableFrom": "organization_search_history", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "organization_search_history_organization_id_user_id_pk": { + "name": "organization_search_history_organization_id_user_id_pk", + "columns": [ + "organization_id", + "user_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_search_integration": { + "name": "organization_search_integration", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connector_type": { + "name": "connector_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "approved": { + "name": "approved", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "organization_search_integration_organization_id_organization_id_fk": { + "name": "organization_search_integration_organization_id_organization_id_fk", + "tableFrom": "organization_search_integration", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "organization_search_integration_organization_id_connector_type_pk": { + "name": "organization_search_integration_organization_id_connector_type_pk", + "columns": [ + "organization_id", + "connector_type" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_search_mcp_invocation": { + "name": "organization_search_mcp_invocation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_kind": { + "name": "auth_kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oauth_client_id": { + "name": "oauth_client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_name": { + "name": "client_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "outcome": { + "name": "outcome", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_search_mcp_invocation_org_created_idx": { + "name": "organization_search_mcp_invocation_org_created_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_search_mcp_invocation_user_idx": { + "name": "organization_search_mcp_invocation_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "org_search_mcp_invocation_org_fk": { + "name": "org_search_mcp_invocation_org_fk", + "tableFrom": "organization_search_mcp_invocation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "org_search_mcp_invocation_user_fk": { + "name": "org_search_mcp_invocation_user_fk", + "tableFrom": "organization_search_mcp_invocation", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "organization_search_mcp_invocation_tool_check": { + "name": "organization_search_mcp_invocation_tool_check", + "value": "\"organization_search_mcp_invocation\".\"tool_name\" IN ('search', 'read_document', 'chat')" + }, + "organization_search_mcp_invocation_outcome_check": { + "name": "organization_search_mcp_invocation_outcome_check", + "value": "\"organization_search_mcp_invocation\".\"outcome\" IN ('success', 'error', 'cancelled', 'rate_limited')" + }, + "organization_search_mcp_invocation_duration_check": { + "name": "organization_search_mcp_invocation_duration_check", + "value": "\"organization_search_mcp_invocation\".\"duration_ms\" >= 0" + }, + "organization_search_mcp_invocation_client_name_check": { + "name": "organization_search_mcp_invocation_client_name_check", + "value": "length(\"organization_search_mcp_invocation\".\"client_name\") <= 256" + }, + "organization_search_mcp_invocation_auth_check": { + "name": "organization_search_mcp_invocation_auth_check", + "value": "(\"organization_search_mcp_invocation\".\"auth_kind\" = 'oauth_access_token' AND \"organization_search_mcp_invocation\".\"oauth_client_id\" IS NOT NULL)\n OR (\"organization_search_mcp_invocation\".\"auth_kind\" IN ('personal_api_key', 'workspace_api_key') AND \"organization_search_mcp_invocation\".\"oauth_client_id\" IS NULL AND \"organization_search_mcp_invocation\".\"client_name\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.organization_secret": { + "name": "organization_secret", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "source_id": { + "name": "source_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encrypted_value": { + "name": "encrypted_value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_secret_shared_unique": { + "name": "organization_secret_shared_unique", + "columns": [ + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"organization_secret\".\"owner_user_id\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_secret_member_unique": { + "name": "organization_secret_member_unique", + "columns": [ + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"organization_secret\".\"owner_user_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_secret_owner_idx": { + "name": "organization_secret_owner_idx", + "columns": [ + { + "expression": "owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_secret_source_id_organization_secret_source_id_fk": { + "name": "organization_secret_source_id_organization_secret_source_id_fk", + "tableFrom": "organization_secret", + "tableTo": "organization_secret_source", + "columnsFrom": [ + "source_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_secret_owner_user_id_user_id_fk": { + "name": "organization_secret_owner_user_id_user_id_fk", + "tableFrom": "organization_secret", + "tableTo": "user", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_secret_source": { + "name": "organization_secret_source", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mode": { + "name": "mode", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_secret_source_org_unique": { + "name": "organization_secret_source_org_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_secret_source_organization_id_organization_id_fk": { + "name": "organization_secret_source_organization_id_organization_id_fk", + "tableFrom": "organization_secret_source", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "organization_secret_source_mode_check": { + "name": "organization_secret_source_mode_check", + "value": "\"organization_secret_source\".\"mode\" IN ('organization', 'member')" + } + }, + "isRLSEnabled": false + }, + "public.outbox_event": { + "name": "outbox_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "max_attempts": { + "name": "max_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 10 + }, + "available_at": { + "name": "available_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "locked_at": { + "name": "locked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "processed_at": { + "name": "processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "outbox_event_status_available_idx": { + "name": "outbox_event_status_available_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "available_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "outbox_event_pending_type_available_idx": { + "name": "outbox_event_pending_type_available_idx", + "columns": [ + { + "expression": "event_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "available_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"outbox_event\".\"status\" = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "outbox_event_locked_at_idx": { + "name": "outbox_event_locked_at_idx", + "columns": [ + { + "expression": "locked_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "outbox_event_type_created_idx": { + "name": "outbox_event_type_created_idx", + "columns": [ + { + "expression": "event_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.paused_executions": { + "name": "paused_executions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_snapshot": { + "name": "execution_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "pause_points": { + "name": "pause_points", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "total_pause_count": { + "name": "total_pause_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "resumed_count": { + "name": "resumed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "automatic_resume_retry_count": { + "name": "automatic_resume_retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'paused'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_resume_at": { + "name": "next_resume_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "paused_executions_workflow_id_idx": { + "name": "paused_executions_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_status_idx": { + "name": "paused_executions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_execution_id_unique": { + "name": "paused_executions_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_next_resume_at_idx": { + "name": "paused_executions_next_resume_at_idx", + "columns": [ + { + "expression": "next_resume_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "status = 'paused' AND next_resume_at IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "paused_executions_workflow_id_workflow_id_fk": { + "name": "paused_executions_workflow_id_workflow_id_fk", + "tableFrom": "paused_executions", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pending_credential_draft": { + "name": "pending_credential_draft", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oauth_config": { + "name": "oauth_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pending_draft_organization_id_idx": { + "name": "pending_draft_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_draft_user_provider_org": { + "name": "pending_draft_user_provider_org", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pending_draft_user_provider_ws": { + "name": "pending_draft_user_provider_ws", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pending_credential_draft_user_id_user_id_fk": { + "name": "pending_credential_draft_user_id_user_id_fk", + "tableFrom": "pending_credential_draft", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pending_credential_draft_workspace_id_workspace_id_fk": { + "name": "pending_credential_draft_workspace_id_workspace_id_fk", + "tableFrom": "pending_credential_draft", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pending_credential_draft_organization_id_organization_id_fk": { + "name": "pending_credential_draft_organization_id_organization_id_fk", + "tableFrom": "pending_credential_draft", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pending_credential_draft_credential_id_credential_id_fk": { + "name": "pending_credential_draft_credential_id_credential_id_fk", + "tableFrom": "pending_credential_draft", + "tableTo": "credential", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "pending_draft_owner_check": { + "name": "pending_draft_owner_check", + "value": "num_nonnulls(\"pending_credential_draft\".\"workspace_id\", \"pending_credential_draft\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.people_directory_entry": { + "name": "people_directory_entry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "department": { + "name": "department", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "manager_external_id": { + "name": "manager_external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "people_directory_entry_source_id_idx": { + "name": "people_directory_entry_source_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "people_directory_entry_email_idx": { + "name": "people_directory_entry_email_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "people_directory_entry_manager_idx": { + "name": "people_directory_entry_manager_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "manager_external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "people_directory_entry_organization_id_people_directory_sync_organization_id_fk": { + "name": "people_directory_entry_organization_id_people_directory_sync_organization_id_fk", + "tableFrom": "people_directory_entry", + "tableTo": "people_directory_sync", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.people_directory_page": { + "name": "people_directory_page", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "page_hash": { + "name": "page_hash", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "people_directory_page_organization_id_people_directory_sync_organization_id_fk": { + "name": "people_directory_page_organization_id_people_directory_sync_organization_id_fk", + "tableFrom": "people_directory_page", + "tableTo": "people_directory_sync", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "people_directory_page_organization_id_run_id_page_hash_pk": { + "name": "people_directory_page_organization_id_run_id_page_hash_pk", + "columns": [ + "organization_id", + "run_id", + "page_hash" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.people_directory_scim_change": { + "name": "people_directory_scim_change", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "changed_at": { + "name": "changed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "people_directory_scim_change_due_idx": { + "name": "people_directory_scim_change_due_idx", + "columns": [ + { + "expression": "changed_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "people_directory_scim_change_organization_id_organization_id_fk": { + "name": "people_directory_scim_change_organization_id_organization_id_fk", + "tableFrom": "people_directory_scim_change", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.people_directory_stage": { + "name": "people_directory_stage", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "proposed_id": { + "name": "proposed_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "department": { + "name": "department", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "manager_external_id": { + "name": "manager_external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reports_cursor": { + "name": "reports_cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reports_complete": { + "name": "reports_complete", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "people_directory_stage_email_idx": { + "name": "people_directory_stage_email_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "people_directory_stage_pending_idx": { + "name": "people_directory_stage_pending_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "NOT \"people_directory_stage\".\"reports_complete\"", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "people_directory_stage_organization_id_people_directory_sync_organization_id_fk": { + "name": "people_directory_stage_organization_id_people_directory_sync_organization_id_fk", + "tableFrom": "people_directory_stage", + "tableTo": "people_directory_sync", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "people_directory_stage_organization_id_run_id_external_id_pk": { + "name": "people_directory_stage_organization_id_run_id_external_id_pk", + "columns": [ + "organization_id", + "run_id", + "external_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.people_directory_sync": { + "name": "people_directory_sync", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_target": { + "name": "source_target", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_credential": { + "name": "encrypted_credential", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "configured_by": { + "name": "configured_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lease_token": { + "name": "lease_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_id": { + "name": "run_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "run_started_at": { + "name": "run_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "phase": { + "name": "phase", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cursor": { + "name": "cursor", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "users_read": { + "name": "users_read", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "next_sync_at": { + "name": "next_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_success_at": { + "name": "last_success_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "people_directory_sync_due_idx": { + "name": "people_directory_sync_due_idx", + "columns": [ + { + "expression": "next_sync_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "people_directory_sync_organization_id_organization_id_fk": { + "name": "people_directory_sync_organization_id_organization_id_fk", + "tableFrom": "people_directory_sync", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "people_directory_sync_configured_by_user_id_fk": { + "name": "people_directory_sync_configured_by_user_id_fk", + "tableFrom": "people_directory_sync", + "tableTo": "user", + "columnsFrom": [ + "configured_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permission_access_request": { + "name": "permission_access_request", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requester_id": { + "name": "requester_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope_key": { + "name": "scope_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_key": { + "name": "target_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target": { + "name": "target", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "target_label": { + "name": "target_label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "membership_id": { + "name": "membership_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "group_name": { + "name": "group_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "decision_reason": { + "name": "decision_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "decided_by": { + "name": "decided_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "decision": { + "name": "decision", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "decided_at": { + "name": "decided_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "permission_access_request_pending_unique": { + "name": "permission_access_request_pending_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "requester_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"permission_access_request\".\"status\" = 'pending'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_access_request_org_queue_idx": { + "name": "permission_access_request_org_queue_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_access_request_requester_idx": { + "name": "permission_access_request_requester_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "requester_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permission_access_request_organization_id_organization_id_fk": { + "name": "permission_access_request_organization_id_organization_id_fk", + "tableFrom": "permission_access_request", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_access_request_requester_id_user_id_fk": { + "name": "permission_access_request_requester_id_user_id_fk", + "tableFrom": "permission_access_request", + "tableTo": "user", + "columnsFrom": [ + "requester_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_access_request_decided_by_user_id_fk": { + "name": "permission_access_request_decided_by_user_id_fk", + "tableFrom": "permission_access_request", + "tableTo": "user", + "columnsFrom": [ + "decided_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "permission_access_request_status_check": { + "name": "permission_access_request_status_check", + "value": "\"permission_access_request\".\"status\" in ('pending', 'fulfilled', 'declined', 'cancelled', 'closed')" + } + }, + "isRLSEnabled": false + }, + "public.permission_group": { + "name": "permission_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "membership_mode": { + "name": "membership_mode", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'inherit'" + } + }, + "indexes": { + "permission_group_created_by_idx": { + "name": "permission_group_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_group_organization_name_unique": { + "name": "permission_group_organization_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_group_organization_default_unique": { + "name": "permission_group_organization_default_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "is_default = true", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permission_group_organization_id_organization_id_fk": { + "name": "permission_group_organization_id_organization_id_fk", + "tableFrom": "permission_group", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_created_by_user_id_fk": { + "name": "permission_group_created_by_user_id_fk", + "tableFrom": "permission_group", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permission_group_member": { + "name": "permission_group_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "permission_group_id": { + "name": "permission_group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permission_group_member_group_user_unique": { + "name": "permission_group_member_group_user_unique", + "columns": [ + { + "expression": "permission_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_group_member_organization_user_idx": { + "name": "permission_group_member_organization_user_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permission_group_member_permission_group_id_permission_group_id_fk": { + "name": "permission_group_member_permission_group_id_permission_group_id_fk", + "tableFrom": "permission_group_member", + "tableTo": "permission_group", + "columnsFrom": [ + "permission_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_member_organization_id_organization_id_fk": { + "name": "permission_group_member_organization_id_organization_id_fk", + "tableFrom": "permission_group_member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_member_user_id_user_id_fk": { + "name": "permission_group_member_user_id_user_id_fk", + "tableFrom": "permission_group_member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_member_assigned_by_user_id_fk": { + "name": "permission_group_member_assigned_by_user_id_fk", + "tableFrom": "permission_group_member", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permission_group_workspace": { + "name": "permission_group_workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "permission_group_id": { + "name": "permission_group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permission_group_workspace_workspace_id_idx": { + "name": "permission_group_workspace_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permission_group_workspace_group_workspace_unique": { + "name": "permission_group_workspace_group_workspace_unique", + "columns": [ + { + "expression": "permission_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permission_group_workspace_permission_group_id_permission_group_id_fk": { + "name": "permission_group_workspace_permission_group_id_permission_group_id_fk", + "tableFrom": "permission_group_workspace", + "tableTo": "permission_group", + "columnsFrom": [ + "permission_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_workspace_workspace_id_workspace_id_fk": { + "name": "permission_group_workspace_workspace_id_workspace_id_fk", + "tableFrom": "permission_group_workspace", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "permission_group_workspace_organization_id_organization_id_fk": { + "name": "permission_group_workspace_organization_id_organization_id_fk", + "tableFrom": "permission_group_workspace", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_entity_idx": { + "name": "permissions_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_permission_idx": { + "name": "permissions_user_entity_permission_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_unique_constraint": { + "name": "permissions_unique_constraint", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_user_id_user_id_fk": { + "name": "permissions_user_id_user_id_fk", + "tableFrom": "permissions", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pinned_item": { + "name": "pinned_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pinned_at": { + "name": "pinned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pinned_item_user_workspace_idx": { + "name": "pinned_item_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pinned_item_resource_idx": { + "name": "pinned_item_resource_idx", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pinned_item_user_resource_unique": { + "name": "pinned_item_user_resource_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pinned_item_user_id_user_id_fk": { + "name": "pinned_item_user_id_user_id_fk", + "tableFrom": "pinned_item", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pinned_item_workspace_id_workspace_id_fk": { + "name": "pinned_item_workspace_id_workspace_id_fk", + "tableFrom": "pinned_item", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_scope_key": { + "name": "organization_scope_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "CASE WHEN organization_id IS NULL THEN 'personal' ELSE 'organization:' || organization_id END", + "type": "stored" + } + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "project_organization_archive_id_idx": { + "name": "project_organization_archive_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "project_owner_archive_id_idx": { + "name": "project_owner_archive_id_idx", + "columns": [ + { + "expression": "owner_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "project_organization_id_organization_id_fk": { + "name": "project_organization_id_organization_id_fk", + "tableFrom": "project", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "project_owner_id_user_id_fk": { + "name": "project_owner_id_user_id_fk", + "tableFrom": "project", + "tableTo": "user", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "project_id_organization_scope_unique": { + "name": "project_id_organization_scope_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_scope_key" + ] + } + }, + "policies": {}, + "checkConstraints": { + "project_name_length": { + "name": "project_name_length", + "value": "char_length(btrim(\"project\".\"name\")) BETWEEN 1 AND 100" + } + }, + "isRLSEnabled": false + }, + "public.public_share": { + "name": "public_share", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "public_share_entity_id_idx": { + "name": "public_share_entity_id_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_share_token_unique": { + "name": "public_share_token_unique", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_share_resource_unique": { + "name": "public_share_resource_unique", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_share_resource_id_idx": { + "name": "public_share_resource_id_idx", + "columns": [ + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_share_workspace_id_idx": { + "name": "public_share_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "public_share_workspace_id_workspace_id_fk": { + "name": "public_share_workspace_id_workspace_id_fk", + "tableFrom": "public_share", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "public_share_created_by_user_id_fk": { + "name": "public_share_created_by_user_id_fk", + "tableFrom": "public_share", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "public_share_entity_binding_check": { + "name": "public_share_entity_binding_check", + "value": "\n (\"public_share\".\"entity_type\" IS NULL AND \"public_share\".\"entity_id\" IS NULL AND \"public_share\".\"workspace_id\" IS NOT NULL)\n OR (\"public_share\".\"entity_type\" IS NOT NULL AND \"public_share\".\"entity_id\" IS NOT NULL AND char_length(\"public_share\".\"entity_id\") > 0\n AND ((\"public_share\".\"entity_type\" = 'workspace' AND \"public_share\".\"workspace_id\" IS NOT NULL AND \"public_share\".\"entity_id\" = \"public_share\".\"workspace_id\")\n OR (\"public_share\".\"entity_type\" = 'project' AND \"public_share\".\"workspace_id\" IS NULL AND \"public_share\".\"resource_type\" = 'file')))\n " + } + }, + "isRLSEnabled": false + }, + "public.rate_limit_bucket": { + "name": "rate_limit_bucket", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokens": { + "name": "tokens", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "blocked_until": { + "name": "blocked_until", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "capacity_state": { + "name": "capacity_state", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_policy": { + "name": "resource_policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "document": { + "name": "document", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "resource_policy_organization_id_idx": { + "name": "resource_policy_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resource_policy_resource_unique": { + "name": "resource_policy_resource_unique", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resource_policy_workspace_id_idx": { + "name": "resource_policy_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_policy_workspace_id_workspace_id_fk": { + "name": "resource_policy_workspace_id_workspace_id_fk", + "tableFrom": "resource_policy", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "resource_policy_organization_id_organization_id_fk": { + "name": "resource_policy_organization_id_organization_id_fk", + "tableFrom": "resource_policy", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "resource_policy_created_by_user_id_fk": { + "name": "resource_policy_created_by_user_id_fk", + "tableFrom": "resource_policy", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "resource_policy_updated_by_user_id_fk": { + "name": "resource_policy_updated_by_user_id_fk", + "tableFrom": "resource_policy", + "tableTo": "user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "resource_policy_owner_check": { + "name": "resource_policy_owner_check", + "value": "num_nonnulls(\"resource_policy\".\"workspace_id\", \"resource_policy\".\"organization_id\") = 1" + } + }, + "isRLSEnabled": false + }, + "public.resume_queue": { + "name": "resume_queue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "paused_execution_id": { + "name": "paused_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_execution_id": { + "name": "parent_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "new_execution_id": { + "name": "new_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resume_input": { + "name": "resume_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "queued_at": { + "name": "queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resume_queue_parent_status_idx": { + "name": "resume_queue_parent_status_idx", + "columns": [ + { + "expression": "parent_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resume_queue_new_execution_idx": { + "name": "resume_queue_new_execution_idx", + "columns": [ + { + "expression": "new_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resume_queue_paused_execution_id_paused_executions_id_fk": { + "name": "resume_queue_paused_execution_id_paused_executions_id_fk", + "tableFrom": "resume_queue", + "tableTo": "paused_executions", + "columnsFrom": [ + "paused_execution_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sandbox_image": { + "name": "sandbox_image", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "spec_hash": { + "name": "spec_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "spec": { + "name": "spec", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "sandbox_image_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "image_ref": { + "name": "image_ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_image_id": { + "name": "provider_image_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "build_id": { + "name": "build_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "materialization_generation": { + "name": "materialization_generation", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_detail": { + "name": "error_detail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sandbox_image_provider_spec_unique": { + "name": "sandbox_image_provider_spec_unique", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "spec_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sandbox_image_status_idx": { + "name": "sandbox_image_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sandbox_image_last_used_idx": { + "name": "sandbox_image_last_used_idx", + "columns": [ + { + "expression": "last_used_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_connection": { + "name": "scim_connection", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "last_request_at": { + "name": "last_request_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "reconcile_lock_token": { + "name": "reconcile_lock_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reconcile_lease_at": { + "name": "reconcile_lease_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "reconciled_at": { + "name": "reconciled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_connection_organization_unique": { + "name": "scim_connection_organization_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_connection_reconcile_due_idx": { + "name": "scim_connection_reconcile_due_idx", + "columns": [ + { + "expression": "reconciled_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_connection_organization_id_organization_id_fk": { + "name": "scim_connection_organization_id_organization_id_fk", + "tableFrom": "scim_connection", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_connection_created_by_user_id_fk": { + "name": "scim_connection_created_by_user_id_fk", + "tableFrom": "scim_connection", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_credential": { + "name": "scim_credential", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scopes": { + "name": "scopes", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked_by": { + "name": "revoked_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_credential_token_hash_unique": { + "name": "scim_credential_token_hash_unique", + "columns": [ + { + "expression": "token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_credential_connection_idx": { + "name": "scim_credential_connection_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_credential_connection_id_scim_connection_id_fk": { + "name": "scim_credential_connection_id_scim_connection_id_fk", + "tableFrom": "scim_credential", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_credential_revoked_by_user_id_fk": { + "name": "scim_credential_revoked_by_user_id_fk", + "tableFrom": "scim_credential", + "tableTo": "user", + "columnsFrom": [ + "revoked_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "scim_credential_created_by_user_id_fk": { + "name": "scim_credential_created_by_user_id_fk", + "tableFrom": "scim_credential", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_group": { + "name": "scim_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name_key": { + "name": "display_name_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "order_key": { + "name": "order_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_group_connection_display_name_unique": { + "name": "scim_group_connection_display_name_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_group_connection_external_id_unique": { + "name": "scim_group_connection_external_id_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "external_id is not null", + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_group_connection_order_idx": { + "name": "scim_group_connection_order_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "order_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_group_connection_id_scim_connection_id_fk": { + "name": "scim_group_connection_id_scim_connection_id_fk", + "tableFrom": "scim_group", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_group_mapping": { + "name": "scim_group_mapping", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_kind": { + "name": "target_kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_group_id": { + "name": "permission_group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_group_mapping_permission_group_idx": { + "name": "scim_group_mapping_permission_group_idx", + "columns": [ + { + "expression": "permission_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_group_mapping_workspace_idx": { + "name": "scim_group_mapping_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_group_mapping_group_target_unique": { + "name": "scim_group_mapping_group_target_unique", + "columns": [ + { + "expression": "group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"permission_group_id\", \"workspace_id\", \"role\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_group_mapping_group_id_scim_group_id_fk": { + "name": "scim_group_mapping_group_id_scim_group_id_fk", + "tableFrom": "scim_group_mapping", + "tableTo": "scim_group", + "columnsFrom": [ + "group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_group_mapping_permission_group_id_permission_group_id_fk": { + "name": "scim_group_mapping_permission_group_id_permission_group_id_fk", + "tableFrom": "scim_group_mapping", + "tableTo": "permission_group", + "columnsFrom": [ + "permission_group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_group_mapping_workspace_id_workspace_id_fk": { + "name": "scim_group_mapping_workspace_id_workspace_id_fk", + "tableFrom": "scim_group_mapping", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_group_mapping_created_by_user_id_fk": { + "name": "scim_group_mapping_created_by_user_id_fk", + "tableFrom": "scim_group_mapping", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "scim_group_mapping_target_shape": { + "name": "scim_group_mapping_target_shape", + "value": "(\n (\"scim_group_mapping\".\"target_kind\" = 'permission_group' AND \"scim_group_mapping\".\"permission_group_id\" IS NOT NULL AND \"scim_group_mapping\".\"workspace_id\" IS NULL AND \"scim_group_mapping\".\"permission_type\" IS NULL AND \"scim_group_mapping\".\"role\" IS NULL)\n OR (\"scim_group_mapping\".\"target_kind\" = 'workspace' AND \"scim_group_mapping\".\"workspace_id\" IS NOT NULL AND \"scim_group_mapping\".\"permission_type\" IS NOT NULL AND \"scim_group_mapping\".\"permission_group_id\" IS NULL AND \"scim_group_mapping\".\"role\" IS NULL)\n OR (\"scim_group_mapping\".\"target_kind\" = 'org_role' AND \"scim_group_mapping\".\"role\" IS NOT NULL AND \"scim_group_mapping\".\"permission_group_id\" IS NULL AND \"scim_group_mapping\".\"workspace_id\" IS NULL AND \"scim_group_mapping\".\"permission_type\" IS NULL)\n )" + } + }, + "isRLSEnabled": false + }, + "public.scim_group_member": { + "name": "scim_group_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scim_user_id": { + "name": "scim_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_group_member_group_user_unique": { + "name": "scim_group_member_group_user_unique", + "columns": [ + { + "expression": "group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scim_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_group_member_scim_user_idx": { + "name": "scim_group_member_scim_user_idx", + "columns": [ + { + "expression": "scim_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_group_member_group_id_scim_group_id_fk": { + "name": "scim_group_member_group_id_scim_group_id_fk", + "tableFrom": "scim_group_member", + "tableTo": "scim_group", + "columnsFrom": [ + "group_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_group_member_scim_user_id_scim_user_id_fk": { + "name": "scim_group_member_scim_user_id_scim_user_id_fk", + "tableFrom": "scim_group_member", + "tableTo": "scim_user", + "columnsFrom": [ + "scim_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_projection_grant": { + "name": "scim_projection_grant", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scim_user_id": { + "name": "scim_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_kind": { + "name": "target_kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "baseline_permission": { + "name": "baseline_permission", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "origin": { + "name": "origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'directory'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_projection_grant_user_target_unique": { + "name": "scim_projection_grant_user_target_unique", + "columns": [ + { + "expression": "scim_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_projection_grant_connection_idx": { + "name": "scim_projection_grant_connection_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_projection_grant_connection_id_scim_connection_id_fk": { + "name": "scim_projection_grant_connection_id_scim_connection_id_fk", + "tableFrom": "scim_projection_grant", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_projection_grant_scim_user_id_scim_user_id_fk": { + "name": "scim_projection_grant_scim_user_id_scim_user_id_fk", + "tableFrom": "scim_projection_grant", + "tableTo": "scim_user", + "columnsFrom": [ + "scim_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_request_log": { + "name": "scim_request_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "scim_type": { + "name": "scim_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "detail": { + "name": "detail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_request_log_connection_created_idx": { + "name": "scim_request_log_connection_created_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_request_log_connection_id_scim_connection_id_fk": { + "name": "scim_request_log_connection_id_scim_connection_id_fk", + "tableFrom": "scim_request_log", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_user": { + "name": "scim_user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_name": { + "name": "user_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "attributes": { + "name": "attributes", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "order_key": { + "name": "order_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_user_connection_user_unique": { + "name": "scim_user_connection_user_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_user_connection_user_name_unique": { + "name": "scim_user_connection_user_name_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_user_connection_external_id_unique": { + "name": "scim_user_connection_external_id_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "external_id is not null", + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_user_connection_order_idx": { + "name": "scim_user_connection_order_idx", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "order_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_user_user_idx": { + "name": "scim_user_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_user_connection_id_scim_connection_id_fk": { + "name": "scim_user_connection_id_scim_connection_id_fk", + "tableFrom": "scim_user", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_user_user_id_user_id_fk": { + "name": "scim_user_user_id_user_id_fk", + "tableFrom": "scim_user", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.scim_user_tombstone": { + "name": "scim_user_tombstone", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "scim_user_tombstone_connection_external_id_unique": { + "name": "scim_user_tombstone_connection_external_id_unique", + "columns": [ + { + "expression": "connection_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "scim_user_tombstone_user_idx": { + "name": "scim_user_tombstone_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "scim_user_tombstone_connection_id_scim_connection_id_fk": { + "name": "scim_user_tombstone_connection_id_scim_connection_id_fk", + "tableFrom": "scim_user_tombstone", + "tableTo": "scim_connection", + "columnsFrom": [ + "connection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "scim_user_tombstone_user_id_user_id_fk": { + "name": "scim_user_tombstone_user_id_user_id_fk", + "tableFrom": "scim_user_tombstone", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.secret_usage": { + "name": "secret_usage", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret_name": { + "name": "secret_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret_scope": { + "name": "secret_scope", + "type": "secret_usage_scope", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "secret_owner_user_id": { + "name": "secret_owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "source": { + "name": "source", + "type": "secret_usage_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "actor_user_id": { + "name": "actor_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "usage_date": { + "name": "usage_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "use_count": { + "name": "use_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "last_execution_id": { + "name": "last_execution_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_trigger": { + "name": "last_trigger", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "secret_usage_bucket_unique": { + "name": "secret_usage_bucket_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_scope", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "actor_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "usage_date", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "secret_usage_secret_recent_idx": { + "name": "secret_usage_secret_recent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_scope", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "secret_owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_used_at", + "isExpression": false, + "asc": false, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "secret_usage_workspace_id_workspace_id_fk": { + "name": "secret_usage_workspace_id_workspace_id_fk", + "tableFrom": "secret_usage", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "session_active_organization_id_organization_id_fk": { + "name": "session_active_organization_id_organization_id_fk", + "tableFrom": "session", + "tableTo": "organization", + "columnsFrom": [ + "active_organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'system'" + }, + "auto_connect": { + "name": "auto_connect", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "telemetry_enabled": { + "name": "telemetry_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "email_preferences": { + "name": "email_preferences", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "billing_usage_notifications_enabled": { + "name": "billing_usage_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "super_user_mode_enabled": { + "name": "super_user_mode_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "mothership_environment": { + "name": "mothership_environment", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "error_notifications_enabled": { + "name": "error_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "snap_to_grid_size": { + "name": "snap_to_grid_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "show_action_bar": { + "name": "show_action_bar", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "auto_focus_on_click": { + "name": "auto_focus_on_click", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "copilot_auto_allowed_tools": { + "name": "copilot_auto_allowed_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "last_active_workspace_id": { + "name": "last_active_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "settings_user_id_user_id_fk": { + "name": "settings_user_id_user_id_fk", + "tableFrom": "settings", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "settings_user_id_unique": { + "name": "settings_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sim_link": { + "name": "sim_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "normalized_name": { + "name": "normalized_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "default_url": { + "name": "default_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "unlisted": { + "name": "unlisted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "restrict_edit": { + "name": "restrict_edit", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "visit_count": { + "name": "visit_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_visited_at": { + "name": "last_visited_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sim_link_organization_name_unique": { + "name": "sim_link_organization_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "normalized_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sim_link_created_by_idx": { + "name": "sim_link_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sim_link_organization_id_organization_id_fk": { + "name": "sim_link_organization_id_organization_id_fk", + "tableFrom": "sim_link", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sim_link_created_by_user_id_fk": { + "name": "sim_link_created_by_user_id_fk", + "tableFrom": "sim_link", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sim_trigger_state": { + "name": "sim_trigger_state", + "schema": "", + "columns": { + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_key": { + "name": "scope_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "last_fired_at": { + "name": "last_fired_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "sim_trigger_state_workflow_id_workflow_id_fk": { + "name": "sim_trigger_state_workflow_id_workflow_id_fk", + "tableFrom": "sim_trigger_state", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sim_trigger_state_workflow_id_block_id_scope_key_pk": { + "name": "sim_trigger_state_workflow_id_block_id_scope_key_pk", + "columns": [ + "workflow_id", + "block_id", + "scope_key" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.skill": { + "name": "skill", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "skill_workspace_name_unique": { + "name": "skill_workspace_name_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "skill_workspace_id_workspace_id_fk": { + "name": "skill_workspace_id_workspace_id_fk", + "tableFrom": "skill", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "skill_user_id_user_id_fk": { + "name": "skill_user_id_user_id_fk", + "tableFrom": "skill", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.skill_member": { + "name": "skill_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "skill_id": { + "name": "skill_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "skill_member_user_id_idx": { + "name": "skill_member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "skill_member_unique": { + "name": "skill_member_unique", + "columns": [ + { + "expression": "skill_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "skill_member_skill_id_skill_id_fk": { + "name": "skill_member_skill_id_skill_id_fk", + "tableFrom": "skill_member", + "tableTo": "skill", + "columnsFrom": [ + "skill_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "skill_member_user_id_user_id_fk": { + "name": "skill_member_user_id_user_id_fk", + "tableFrom": "skill_member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "skill_member_invited_by_user_id_fk": { + "name": "skill_member_invited_by_user_id_fk", + "tableFrom": "skill_member", + "tableTo": "user", + "columnsFrom": [ + "invited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.slack_app": { + "name": "slack_app", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_client_secret": { + "name": "encrypted_client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_signing_secret": { + "name": "encrypted_signing_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "slack_app_organization_id_organization_id_fk": { + "name": "slack_app_organization_id_organization_id_fk", + "tableFrom": "slack_app", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "slack_app_owner_check": { + "name": "slack_app_owner_check", + "value": "(\"slack_app\".\"kind\" = 'custom' AND \"slack_app\".\"organization_id\" IS NOT NULL) OR (\"slack_app\".\"kind\" = 'shared' AND \"slack_app\".\"organization_id\" IS NULL)" + }, + "slack_app_custom_credentials_check": { + "name": "slack_app_custom_credentials_check", + "value": "\"slack_app\".\"kind\" = 'shared' OR (\"slack_app\".\"client_id\" IS NOT NULL AND \"slack_app\".\"encrypted_client_secret\" IS NOT NULL AND \"slack_app\".\"encrypted_signing_secret\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.slack_search_installation": { + "name": "slack_search_installation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "app_id": { + "name": "app_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slack_app_id": { + "name": "slack_app_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "team_id": { + "name": "team_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "team_name": { + "name": "team_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bot_user_id": { + "name": "bot_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enterprise_id": { + "name": "enterprise_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "credential_version": { + "name": "credential_version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_outcome": { + "name": "last_outcome", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_event_at": { + "name": "last_event_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "slack_search_installation_organization_idx": { + "name": "slack_search_installation_organization_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_installation_credential_unique": { + "name": "slack_search_installation_credential_unique", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_installation_app_team_unique": { + "name": "slack_search_installation_app_team_unique", + "columns": [ + { + "expression": "app_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_installation_active_team_unique": { + "name": "slack_search_installation_active_team_unique", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"slack_search_installation\".\"enabled\" = true", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "slack_search_installation_organization_id_organization_id_fk": { + "name": "slack_search_installation_organization_id_organization_id_fk", + "tableFrom": "slack_search_installation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "slack_search_installation_credential_id_credential_id_fk": { + "name": "slack_search_installation_credential_id_credential_id_fk", + "tableFrom": "slack_search_installation", + "tableTo": "credential", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "slack_search_installation_slack_app_id_slack_app_id_fk": { + "name": "slack_search_installation_slack_app_id_slack_app_id_fk", + "tableFrom": "slack_search_installation", + "tableTo": "slack_app", + "columnsFrom": [ + "slack_app_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.slack_search_turn": { + "name": "slack_search_turn", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ordinal": { + "name": "ordinal", + "type": "integer", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "slack_search_turn_ordinal_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "installation_id": { + "name": "installation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conversation_key": { + "name": "conversation_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "lease_id": { + "name": "lease_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "outcome": { + "name": "outcome", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "slack_search_turn_event_unique": { + "name": "slack_search_turn_event_unique", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_turn_pending_idx": { + "name": "slack_search_turn_pending_idx", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_turn_thread_idx": { + "name": "slack_search_turn_thread_idx", + "columns": [ + { + "expression": "conversation_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "slack_search_turn_active_thread_unique": { + "name": "slack_search_turn_active_thread_unique", + "columns": [ + { + "expression": "conversation_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"slack_search_turn\".\"status\" = 'running'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "slack_search_turn_installation_id_slack_search_installation_id_fk": { + "name": "slack_search_turn_installation_id_slack_search_installation_id_fk", + "tableFrom": "slack_search_turn", + "tableTo": "slack_search_installation", + "columnsFrom": [ + "installation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_domain": { + "name": "sso_domain", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "verification_token": { + "name": "verification_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verified_at": { + "name": "verified_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "primary_provider_id": { + "name": "primary_provider_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sso_domain_domain_idx": { + "name": "sso_domain_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_domain_org_domain_unique": { + "name": "sso_domain_org_domain_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_domain_verified_unique": { + "name": "sso_domain_verified_unique", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "status = 'verified'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_domain_organization_id_organization_id_fk": { + "name": "sso_domain_organization_id_organization_id_fk", + "tableFrom": "sso_domain", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_domain_created_by_user_id_fk": { + "name": "sso_domain_created_by_user_id_fk", + "tableFrom": "sso_domain", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "domain_verified": { + "name": "domain_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "jit_provisioning_enabled": { + "name": "jit_provisioning_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "sso_provider_provider_id_unique": { + "name": "sso_provider_provider_id_unique", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_domain_idx": { + "name": "sso_provider_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_organization_id_idx": { + "name": "sso_provider_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "last_closed_period_start": { + "name": "last_closed_period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "subscription_reference_status_idx": { + "name": "subscription_reference_status_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "subscription_cycle_close_lagging_idx": { + "name": "subscription_cycle_close_lagging_idx", + "columns": [ + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"subscription\".\"status\" in ('active', 'past_due') and \"subscription\".\"period_start\" is not null and (\"subscription\".\"last_closed_period_start\" is null or \"subscription\".\"last_closed_period_start\" < \"subscription\".\"period_start\")", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "check_enterprise_metadata": { + "name": "check_enterprise_metadata", + "value": "plan != 'enterprise' OR metadata IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.table_jobs": { + "name": "table_jobs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "rows_processed": { + "name": "rows_processed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "table_jobs_one_active_per_table": { + "name": "table_jobs_one_active_per_table", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"table_jobs\".\"status\" = 'running' AND \"table_jobs\".\"type\" <> 'export'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_jobs_watchdog_idx": { + "name": "table_jobs_watchdog_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_jobs_table_started_idx": { + "name": "table_jobs_table_started_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "table_jobs_table_id_user_table_definitions_id_fk": { + "name": "table_jobs_table_id_user_table_definitions_id_fk", + "tableFrom": "table_jobs", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_jobs_workspace_id_workspace_id_fk": { + "name": "table_jobs_workspace_id_workspace_id_fk", + "tableFrom": "table_jobs", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.table_row_executions": { + "name": "table_row_executions", + "schema": "", + "columns": { + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "row_id": { + "name": "row_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "job_id": { + "name": "job_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "running_block_ids": { + "name": "running_block_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "block_errors": { + "name": "block_errors", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "cancelled_at": { + "name": "cancelled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "capability_governed_user_id": { + "name": "capability_governed_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enrichment_details": { + "name": "enrichment_details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "table_row_executions_table_status_idx": { + "name": "table_row_executions_table_status_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"table_row_executions\".\"status\" IN ('queued', 'running', 'pending')", + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_row_executions_execution_id_idx": { + "name": "table_row_executions_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"table_row_executions\".\"execution_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_row_executions_table_group_idx": { + "name": "table_row_executions_table_group_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "table_row_executions_table_id_user_table_definitions_id_fk": { + "name": "table_row_executions_table_id_user_table_definitions_id_fk", + "tableFrom": "table_row_executions", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_row_executions_row_id_user_table_rows_id_fk": { + "name": "table_row_executions_row_id_user_table_rows_id_fk", + "tableFrom": "table_row_executions", + "tableTo": "user_table_rows", + "columnsFrom": [ + "row_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_row_executions_capability_governed_user_id_user_id_fk": { + "name": "table_row_executions_capability_governed_user_id_user_id_fk", + "tableFrom": "table_row_executions", + "tableTo": "user", + "columnsFrom": [ + "capability_governed_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "table_row_executions_row_id_group_id_pk": { + "name": "table_row_executions_row_id_group_id_pk", + "columns": [ + "row_id", + "group_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.table_run_dispatches": { + "name": "table_run_dispatches", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mode": { + "name": "mode", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope": { + "name": "scope", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "cursor": { + "name": "cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "limit": { + "name": "limit", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "processed_count": { + "name": "processed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "is_manual_run": { + "name": "is_manual_run", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "triggered_by_user_id": { + "name": "triggered_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "capability_governed_user_id": { + "name": "capability_governed_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "requested_at": { + "name": "requested_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "heartbeat_at": { + "name": "heartbeat_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_at": { + "name": "cancelled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "table_run_dispatches_active_idx": { + "name": "table_run_dispatches_active_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_run_dispatches_watchdog_idx": { + "name": "table_run_dispatches_watchdog_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "requested_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_run_dispatches_governed_active_idx": { + "name": "table_run_dispatches_governed_active_idx", + "columns": [ + { + "expression": "capability_governed_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"table_run_dispatches\".\"status\" IN ('pending', 'dispatching')", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "table_run_dispatches_table_id_user_table_definitions_id_fk": { + "name": "table_run_dispatches_table_id_user_table_definitions_id_fk", + "tableFrom": "table_run_dispatches", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_run_dispatches_workspace_id_workspace_id_fk": { + "name": "table_run_dispatches_workspace_id_workspace_id_fk", + "tableFrom": "table_run_dispatches", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_run_dispatches_triggered_by_user_id_user_id_fk": { + "name": "table_run_dispatches_triggered_by_user_id_user_id_fk", + "tableFrom": "table_run_dispatches", + "tableTo": "user", + "columnsFrom": [ + "triggered_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "table_run_dispatches_capability_governed_user_id_user_id_fk": { + "name": "table_run_dispatches_capability_governed_user_id_user_id_fk", + "tableFrom": "table_run_dispatches", + "tableTo": "user", + "columnsFrom": [ + "capability_governed_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.table_views": { + "name": "table_views", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "table_views_table_created_idx": { + "name": "table_views_table_created_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_views_workspace_created_idx": { + "name": "table_views_workspace_created_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "table_views_table_default_unique": { + "name": "table_views_table_default_unique", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "is_default = true", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "table_views_table_id_user_table_definitions_id_fk": { + "name": "table_views_table_id_user_table_definitions_id_fk", + "tableFrom": "table_views", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_views_workspace_id_workspace_id_fk": { + "name": "table_views_workspace_id_workspace_id_fk", + "tableFrom": "table_views", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "table_views_created_by_user_id_fk": { + "name": "table_views_created_by_user_id_fk", + "tableFrom": "table_views", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.upload_session": { + "name": "upload_session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "purpose": { + "name": "purpose", + "type": "upload_session_purpose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "method": { + "name": "method", + "type": "upload_session_method", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "storage_context": { + "name": "storage_context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "final_key": { + "name": "final_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "storage_provider": { + "name": "storage_provider", + "type": "upload_session_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "provider_upload_id": { + "name": "provider_upload_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_object_version": { + "name": "provider_object_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_name": { + "name": "file_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_size": { + "name": "file_size", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "part_size": { + "name": "part_size", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "part_count": { + "name": "part_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "upload_session_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'uploading'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "processing_lease_id": { + "name": "processing_lease_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "processing_lease_expires_at": { + "name": "processing_lease_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_file_id": { + "name": "completed_file_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "upload_session_token_hash_unique": { + "name": "upload_session_token_hash_unique", + "columns": [ + { + "expression": "token_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "upload_session_final_key_unique": { + "name": "upload_session_final_key_unique", + "columns": [ + { + "expression": "final_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "upload_session_status_expires_at_idx": { + "name": "upload_session_status_expires_at_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.usage_log": { + "name": "usage_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "usage_log_category", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "usage_log_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "cost": { + "name": "cost", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "event_key": { + "name": "event_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_entity_type": { + "name": "billing_entity_type", + "type": "billing_entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "billing_entity_id": { + "name": "billing_entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_period_start": { + "name": "billing_period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "billing_period_end": { + "name": "billing_period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "usage_log_user_created_at_idx": { + "name": "usage_log_user_created_at_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_source_idx": { + "name": "usage_log_source_idx", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_workflow_id_idx": { + "name": "usage_log_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_event_key_unique": { + "name": "usage_log_event_key_unique", + "columns": [ + { + "expression": "event_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"usage_log\".\"event_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_billing_entity_period_cost_idx": { + "name": "usage_log_billing_entity_period_cost_idx", + "columns": [ + { + "expression": "billing_entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_period_start", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_period_end", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cost", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"usage_log\".\"billing_entity_type\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_billing_entity_created_at_cost_idx": { + "name": "usage_log_billing_entity_created_at_cost_idx", + "columns": [ + { + "expression": "billing_entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cost", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"usage_log\".\"billing_entity_type\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_workspace_created_at_cost_idx": { + "name": "usage_log_workspace_created_at_cost_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cost", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_execution_id_idx": { + "name": "usage_log_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "usage_log_user_id_user_id_fk": { + "name": "usage_log_user_id_user_id_fk", + "tableFrom": "usage_log", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "usage_log_workspace_id_workspace_id_fk": { + "name": "usage_log_workspace_id_workspace_id_fk", + "tableFrom": "usage_log", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "usage_log_workflow_id_workflow_id_fk": { + "name": "usage_log_workflow_id_workflow_id_fk", + "tableFrom": "usage_log", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "usage_log_billing_scope_all_or_none": { + "name": "usage_log_billing_scope_all_or_none", + "value": "(\n (\"usage_log\".\"billing_entity_type\" IS NULL AND \"usage_log\".\"billing_entity_id\" IS NULL AND \"usage_log\".\"billing_period_start\" IS NULL AND \"usage_log\".\"billing_period_end\" IS NULL)\n OR\n (\"usage_log\".\"billing_entity_type\" IS NOT NULL AND \"usage_log\".\"billing_entity_id\" IS NOT NULL AND \"usage_log\".\"billing_period_start\" IS NOT NULL AND \"usage_log\".\"billing_period_end\" IS NOT NULL AND \"usage_log\".\"billing_period_start\" < \"usage_log\".\"billing_period_end\")\n )" + } + }, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "normalized_email": { + "name": "normalized_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'user'" + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "suspension_source": { + "name": "suspension_source", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_email_lower_idx": { + "name": "user_email_lower_idx", + "columns": [ + { + "expression": "lower(btrim(\"email\"))", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_gmail_mailbox_idx": { + "name": "user_gmail_mailbox_idx", + "columns": [ + { + "expression": "(CASE WHEN split_part(lower(btrim(\"email\")), '@', 2) IN ('gmail.com', 'googlemail.com') THEN replace(split_part(split_part(lower(btrim(\"email\")), '@', 1), '+', 1), '.', '') || '@gmail.com' END)", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "(CASE WHEN split_part(lower(btrim(\"user\".\"email\")), '@', 2) IN ('gmail.com', 'googlemail.com') THEN replace(split_part(split_part(lower(btrim(\"user\".\"email\")), '@', 1), '+', 1), '.', '') || '@gmail.com' END) IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_normalized_email_unique": { + "name": "user_normalized_email_unique", + "nullsNotDistinct": false, + "columns": [ + "normalized_email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_stats": { + "name": "user_stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "current_usage_limit": { + "name": "current_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'5'" + }, + "usage_limit_updated_at": { + "name": "usage_limit_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "last_period_cost": { + "name": "last_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "billed_overage_this_period": { + "name": "billed_overage_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "credit_balance": { + "name": "credit_balance", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_copilot_cost": { + "name": "last_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "free_tier_eligible": { + "name": "free_tier_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "billing_blocked": { + "name": "billing_blocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "billing_blocked_reason": { + "name": "billing_blocked_reason", + "type": "billing_blocked_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "limit_notifications": { + "name": "limit_notifications", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "user_stats_user_id_user_id_fk": { + "name": "user_stats_user_id_user_id_fk", + "tableFrom": "user_stats", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_stats_user_id_unique": { + "name": "user_stats_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_table_definitions": { + "name": "user_table_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "max_rows": { + "name": "max_rows", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 10000 + }, + "row_count": { + "name": "row_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "rows_version": { + "name": "rows_version", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "schema_locked": { + "name": "schema_locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "insert_locked": { + "name": "insert_locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "update_locked": { + "name": "update_locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "delete_locked": { + "name": "delete_locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_table_def_workspace_id_idx": { + "name": "user_table_def_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_def_folder_id_idx": { + "name": "user_table_def_folder_id_idx", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_def_created_by_idx": { + "name": "user_table_def_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "user_table_def_workspace_name_unique": { + "name": "user_table_def_workspace_name_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"user_table_definitions\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_def_archived_at_idx": { + "name": "user_table_def_archived_at_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_def_workspace_archived_partial_idx": { + "name": "user_table_def_workspace_archived_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"user_table_definitions\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_table_definitions_workspace_id_workspace_id_fk": { + "name": "user_table_definitions_workspace_id_workspace_id_fk", + "tableFrom": "user_table_definitions", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_table_definitions_folder_id_folder_id_fk": { + "name": "user_table_definitions_folder_id_folder_id_fk", + "tableFrom": "user_table_definitions", + "tableTo": "folder", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "user_table_definitions_created_by_user_id_fk": { + "name": "user_table_definitions_created_by_user_id_fk", + "tableFrom": "user_table_definitions", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_table_row_changes": { + "name": "user_table_row_changes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigint", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "user_table_row_changes_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "row_delta": { + "name": "row_delta", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "user_table_row_changes_table_id_idx": { + "name": "user_table_row_changes_table_id_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_table_row_changes_table_id_user_table_definitions_id_fk": { + "name": "user_table_row_changes_table_id_user_table_definitions_id_fk", + "tableFrom": "user_table_row_changes", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_table_row_secret_provenance": { + "name": "user_table_row_secret_provenance", + "schema": "", + "columns": { + "row_id": { + "name": "row_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content_updated_at": { + "name": "content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entries": { + "name": "entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_table_row_secret_provenance_row_id_user_table_rows_id_fk": { + "name": "user_table_row_secret_provenance_row_id_user_table_rows_id_fk", + "tableFrom": "user_table_row_secret_provenance", + "tableTo": "user_table_rows", + "columnsFrom": [ + "row_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "user_table_row_secret_provenance_status_check": { + "name": "user_table_row_secret_provenance_status_check", + "value": "\"user_table_row_secret_provenance\".\"status\" IN ('exact', 'unknown')" + } + }, + "isRLSEnabled": false + }, + "public.user_table_rows": { + "name": "user_table_rows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "order_key": { + "name": "order_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_provenance_version": { + "name": "secret_provenance_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_table_rows_created_by_idx": { + "name": "user_table_rows_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"user_table_rows\".\"created_by\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "user_table_rows_tenant_data_gin_idx": { + "name": "user_table_rows_tenant_data_gin_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"data\" jsonb_path_ops", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": { + "fastupdate": "off" + } + }, + "user_table_rows_workspace_table_idx": { + "name": "user_table_rows_workspace_table_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_rows_table_position_idx": { + "name": "user_table_rows_table_position_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_rows_table_order_key_idx": { + "name": "user_table_rows_table_order_key_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "order_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_rows_table_created_id_idx": { + "name": "user_table_rows_table_created_id_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_table_rows_table_id_id_idx": { + "name": "user_table_rows_table_id_id_idx", + "columns": [ + { + "expression": "table_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_table_rows_table_id_user_table_definitions_id_fk": { + "name": "user_table_rows_table_id_user_table_definitions_id_fk", + "tableFrom": "user_table_rows", + "tableTo": "user_table_definitions", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_table_rows_workspace_id_workspace_id_fk": { + "name": "user_table_rows_workspace_id_workspace_id_fk", + "tableFrom": "user_table_rows", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_table_rows_created_by_user_id_fk": { + "name": "user_table_rows_created_by_user_id_fk", + "tableFrom": "user_table_rows", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "verification_expires_at_idx": { + "name": "verification_expires_at_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.waitlist": { + "name": "waitlist", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "waitlist_email_unique": { + "name": "waitlist_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhook": { + "name": "webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "registration_status": { + "name": "registration_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "registration_generation": { + "name": "registration_generation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "config_fingerprint": { + "name": "config_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prepared_at": { + "name": "prepared_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "routing_key": { + "name": "routing_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "path_deployment_unique": { + "name": "path_deployment_unique", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"webhook\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_workflow_deployment_idx": { + "name": "webhook_workflow_deployment_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_routing_key_active_idx": { + "name": "webhook_routing_key_active_idx", + "columns": [ + { + "expression": "routing_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"webhook\".\"archived_at\" IS NULL AND \"webhook\".\"routing_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_archived_at_partial_idx": { + "name": "webhook_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"webhook\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_provider_is_active_workflow_id_deploym_bdeed5468": { + "name": "idx_webhook_on_provider_is_active_workflow_id_deploym_bdeed5468", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_workflow_id_block_id_updated_at_desc": { + "name": "idx_webhook_on_workflow_id_block_id_updated_at_desc", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": false, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_active_registration_unique": { + "name": "webhook_active_registration_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"webhook\".\"registration_status\" = 'active' AND \"webhook\".\"block_id\" IS NOT NULL AND \"webhook\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_candidate_registration_unique": { + "name": "webhook_candidate_registration_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"webhook\".\"registration_status\" = 'candidate' AND \"webhook\".\"block_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_registration_status_generation_idx": { + "name": "webhook_registration_status_generation_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "registration_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "registration_generation", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_workflow_id_workflow_id_fk": { + "name": "webhook_workflow_id_workflow_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "webhook_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "webhook_registration_status_check": { + "name": "webhook_registration_status_check", + "value": "\"webhook\".\"registration_status\" IS NULL OR \"webhook\".\"registration_status\" IN ('active', 'candidate', 'retired', 'orphaned')" + }, + "webhook_registration_generation_check": { + "name": "webhook_registration_generation_check", + "value": "\"webhook\".\"registration_generation\" IS NULL OR \"webhook\".\"registration_generation\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.webhook_path_claim": { + "name": "webhook_path_claim", + "schema": "", + "columns": { + "path": { + "name": "path", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "generation": { + "name": "generation", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "webhook_path_claim_workflow_idx": { + "name": "webhook_path_claim_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_path_claim_workflow_id_workflow_id_fk": { + "name": "webhook_path_claim_workflow_id_workflow_id_fk", + "tableFrom": "webhook_path_claim", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "webhook_path_claim_generation_check": { + "name": "webhook_path_claim_generation_check", + "value": "\"webhook_path_claim\".\"generation\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_synced": { + "name": "last_synced", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_deployed": { + "name": "is_deployed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deployed_at": { + "name": "deployed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "is_public_api": { + "name": "is_public_api", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "locked": { + "name": "locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "fork_sync_excluded": { + "name": "fork_sync_excluded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_workspace_id_idx": { + "name": "workflow_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_user_workspace_idx": { + "name": "workflow_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_folder_name_active_unique": { + "name": "workflow_workspace_folder_name_active_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"folder_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_sort_idx": { + "name": "workflow_folder_sort_idx", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_active_workspace_sort_idx": { + "name": "workflow_active_workspace_sort_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_archived_at_idx": { + "name": "workflow_archived_at_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_archived_partial_idx": { + "name": "workflow_workspace_archived_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_user_id_user_id_fk": { + "name": "workflow_user_id_user_id_fk", + "tableFrom": "workflow", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_id_folder_id_fk": { + "name": "workflow_folder_id_folder_id_fk", + "tableFrom": "workflow", + "tableTo": "folder", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_blocks": { + "name": "workflow_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position_x": { + "name": "position_x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "position_y": { + "name": "position_y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "horizontal_handles": { + "name": "horizontal_handles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_wide": { + "name": "is_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "advanced_mode": { + "name": "advanced_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trigger_mode": { + "name": "trigger_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "error_enabled": { + "name": "error_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "retry": { + "name": "retry", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "locked": { + "name": "locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sub_blocks": { + "name": "sub_blocks", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "outputs": { + "name": "outputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_blocks_workflow_id_idx": { + "name": "workflow_blocks_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_blocks_type_idx": { + "name": "workflow_blocks_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_blocks_workflow_id_workflow_id_fk": { + "name": "workflow_blocks_workflow_id_workflow_id_fk", + "tableFrom": "workflow_blocks", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_checkpoints": { + "name": "workflow_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_state": { + "name": "workflow_state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_checkpoints_chat_id_idx": { + "name": "workflow_checkpoints_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_message_id_idx": { + "name": "workflow_checkpoints_message_id_idx", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_user_workflow_idx": { + "name": "workflow_checkpoints_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_chat_idx": { + "name": "workflow_checkpoints_workflow_chat_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_created_at_idx": { + "name": "workflow_checkpoints_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_created_at_idx": { + "name": "workflow_checkpoints_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_checkpoints_user_id_user_id_fk": { + "name": "workflow_checkpoints_user_id_user_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_workflow_id_workflow_id_fk": { + "name": "workflow_checkpoints_workflow_id_workflow_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_chat_id_copilot_chats_id_fk": { + "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_deployment_operation": { + "name": "workflow_deployment_operation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "previous_active_version_id": { + "name": "previous_active_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "protocol_version": { + "name": "protocol_version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "generation": { + "name": "generation", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'preparing'" + }, + "component_readiness": { + "name": "component_readiness", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "request_hash": { + "name": "request_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_deployment_operation_workflow_generation_unique": { + "name": "workflow_deployment_operation_workflow_generation_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "generation", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_operation_workflow_idempotency_unique": { + "name": "workflow_deployment_operation_workflow_idempotency_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "idempotency_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_deployment_operation\".\"idempotency_key\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_operation_workflow_in_flight_unique": { + "name": "workflow_deployment_operation_workflow_in_flight_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_deployment_operation\".\"status\" IN ('preparing', 'activating')", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_operation_workflow_status_idx": { + "name": "workflow_deployment_operation_workflow_status_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_operation_deployment_version_idx": { + "name": "workflow_deployment_operation_deployment_version_idx", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_operation_workflow_version_generation_idx": { + "name": "workflow_deployment_operation_workflow_version_generation_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "generation", + "isExpression": false, + "asc": false, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_operation_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_operation_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_operation", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_deployment_operation_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_deployment_operation_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_deployment_operation", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_deployment_operation_previous_active_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_deployment_operation_previous_active_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_deployment_operation", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "previous_active_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "workflow_deployment_operation_action_check": { + "name": "workflow_deployment_operation_action_check", + "value": "\"workflow_deployment_operation\".\"action\" IN ('deploy', 'activate')" + }, + "workflow_deployment_operation_status_check": { + "name": "workflow_deployment_operation_status_check", + "value": "\"workflow_deployment_operation\".\"status\" IN ('preparing', 'activating', 'active', 'failed', 'superseded')" + }, + "workflow_deployment_operation_generation_check": { + "name": "workflow_deployment_operation_generation_check", + "value": "\"workflow_deployment_operation\".\"generation\" > 0" + }, + "workflow_deployment_operation_protocol_version_check": { + "name": "workflow_deployment_operation_protocol_version_check", + "value": "\"workflow_deployment_operation\".\"protocol_version\" > 0" + } + }, + "isRLSEnabled": false + }, + "public.workflow_deployment_version": { + "name": "workflow_deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_deployment_version_workflow_version_unique": { + "name": "workflow_deployment_version_workflow_version_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_workflow_active_idx": { + "name": "workflow_deployment_version_workflow_active_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_created_at_idx": { + "name": "workflow_deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_version_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_version_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_version", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_edges": { + "name": "workflow_edges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_block_id": { + "name": "source_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_handle": { + "name": "source_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_edges_workflow_source_idx": { + "name": "workflow_edges_workflow_source_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_target_idx": { + "name": "workflow_edges_workflow_target_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_edges_workflow_id_workflow_id_fk": { + "name": "workflow_edges_workflow_id_workflow_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_source_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "source_block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_target_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": [ + "target_block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_logs": { + "name": "workflow_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_snapshot_id": { + "name": "state_snapshot_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "execution_deadline_at": { + "name": "execution_deadline_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost_total": { + "name": "cost_total", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "models_used": { + "name": "models_used", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "files": { + "name": "files", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_execution_logs_state_snapshot_id_idx": { + "name": "workflow_execution_logs_state_snapshot_id_idx", + "columns": [ + { + "expression": "state_snapshot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_deployment_version_id_idx": { + "name": "workflow_execution_logs_deployment_version_id_idx", + "columns": [ + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_trigger_idx": { + "name": "workflow_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_level_idx": { + "name": "workflow_execution_logs_level_idx", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_started_at_idx": { + "name": "workflow_execution_logs_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_execution_id_unique": { + "name": "workflow_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workflow_started_at_idx": { + "name": "workflow_execution_logs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workspace_activity_level_idx": { + "name": "workflow_execution_logs_workspace_activity_level_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "total_duration_ms", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workspace_started_at_id_desc_idx": { + "name": "workflow_execution_logs_workspace_started_at_id_desc_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"started_at\" DESC NULLS LAST", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "\"id\" DESC", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workspace_cost_total_idx": { + "name": "workflow_execution_logs_workspace_cost_total_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cost_total", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_models_used_idx": { + "name": "workflow_execution_logs_models_used_idx", + "columns": [ + { + "expression": "models_used", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "workflow_execution_logs_workspace_ended_at_id_idx": { + "name": "workflow_execution_logs_workspace_ended_at_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "date_trunc('milliseconds', \"ended_at\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_running_started_at_idx": { + "name": "workflow_execution_logs_running_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "status = 'running'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_running_deadline_idx": { + "name": "workflow_execution_logs_running_deadline_idx", + "columns": [ + { + "expression": "execution_deadline_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_execution_logs\".\"status\" = 'running' AND \"workflow_execution_logs\".\"execution_deadline_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_redacting_started_at_idx": { + "name": "workflow_execution_logs_redacting_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "status = 'redacting'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_redacting_deadline_idx": { + "name": "workflow_execution_logs_redacting_deadline_idx", + "columns": [ + { + "expression": "execution_deadline_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_execution_logs\".\"status\" = 'redacting' AND \"workflow_execution_logs\".\"execution_deadline_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_completed_ended_at_idx": { + "name": "workflow_execution_logs_completed_ended_at_idx", + "columns": [ + { + "expression": "ended_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_execution_logs\".\"status\" = 'completed' AND \"workflow_execution_logs\".\"level\" = 'info' AND \"workflow_execution_logs\".\"ended_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_logs_workflow_id_workflow_id_fk": { + "name": "workflow_execution_logs_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_execution_logs_workspace_id_workspace_id_fk": { + "name": "workflow_execution_logs_workspace_id_workspace_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { + "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_execution_snapshots", + "columnsFrom": [ + "state_snapshot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_snapshots": { + "name": "workflow_execution_snapshots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state_hash": { + "name": "state_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_data": { + "name": "state_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_snapshots_hash_idx": { + "name": "workflow_snapshots_hash_idx", + "columns": [ + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_workflow_hash_idx": { + "name": "workflow_snapshots_workflow_hash_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_created_at_idx": { + "name": "workflow_snapshots_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_snapshots_workflow_id_workflow_id_fk": { + "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_snapshots", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_server": { + "name": "workflow_mcp_server", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_server_workspace_id_idx": { + "name": "workflow_mcp_server_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_created_by_idx": { + "name": "workflow_mcp_server_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_deleted_at_idx": { + "name": "workflow_mcp_server_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_server_workspace_deleted_partial_idx": { + "name": "workflow_mcp_server_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_mcp_server\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_server_workspace_id_workspace_id_fk": { + "name": "workflow_mcp_server_workspace_id_workspace_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_server_created_by_user_id_fk": { + "name": "workflow_mcp_server_created_by_user_id_fk", + "tableFrom": "workflow_mcp_server", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_mcp_tool": { + "name": "workflow_mcp_tool", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "server_id": { + "name": "server_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_name": { + "name": "tool_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tool_description": { + "name": "tool_description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parameter_schema": { + "name": "parameter_schema", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "parameter_description_overrides": { + "name": "parameter_description_overrides", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'::json" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_mcp_tool_server_id_idx": { + "name": "workflow_mcp_tool_server_id_idx", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_workflow_id_idx": { + "name": "workflow_mcp_tool_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_server_workflow_unique": { + "name": "workflow_mcp_tool_server_workflow_unique", + "columns": [ + { + "expression": "server_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_mcp_tool\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_mcp_tool_archived_at_partial_idx": { + "name": "workflow_mcp_tool_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_mcp_tool\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk": { + "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow_mcp_server", + "columnsFrom": [ + "server_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_mcp_tool_workflow_id_workflow_id_fk": { + "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", + "tableFrom": "workflow_mcp_tool", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_schedule": { + "name": "workflow_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deployment_version_id": { + "name": "deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deployment_operation_id": { + "name": "deployment_operation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cron_expression": { + "name": "cron_expression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_ran_at": { + "name": "last_ran_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_queued_at": { + "name": "last_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trigger_type": { + "name": "trigger_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "infra_retry_count": { + "name": "infra_retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "source_type": { + "name": "source_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'workflow'" + }, + "job_title": { + "name": "job_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "lifecycle": { + "name": "lifecycle", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'persistent'" + }, + "success_condition": { + "name": "success_condition", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "max_runs": { + "name": "max_runs", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "source_chat_id": { + "name": "source_chat_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_task_name": { + "name": "source_task_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_user_id": { + "name": "source_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_workspace_id": { + "name": "source_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_scope": { + "name": "secret_scope", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "mounted_secrets": { + "name": "mounted_secrets", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "job_history": { + "name": "job_history", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "contexts": { + "name": "contexts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "excluded_dates": { + "name": "excluded_dates", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_budget_usd": { + "name": "run_budget_usd", + "type": "numeric(12, 4)", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_schedule_workflow_block_deployment_unique": { + "name": "workflow_schedule_workflow_block_deployment_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_schedule\".\"archived_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_schedule_workflow_deployment_idx": { + "name": "workflow_schedule_workflow_deployment_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_schedule_archived_at_partial_idx": { + "name": "workflow_schedule_archived_at_partial_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_schedule\".\"archived_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_workflow_schedule_on_source_workspace_id_source_t_c07f3bba6": { + "name": "idx_workflow_schedule_on_source_workspace_id_source_t_c07f3bba6", + "columns": [ + { + "expression": "source_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_schedule_due_workflow_idx": { + "name": "workflow_schedule_due_workflow_idx", + "columns": [ + { + "expression": "next_run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_schedule\".\"archived_at\" IS NULL AND \"workflow_schedule\".\"status\" NOT IN ('disabled', 'completed') AND (\"workflow_schedule\".\"source_type\" = 'workflow' OR \"workflow_schedule\".\"source_type\" IS NULL)", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_schedule_due_job_idx": { + "name": "workflow_schedule_due_job_idx", + "columns": [ + { + "expression": "next_run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workflow_schedule\".\"archived_at\" IS NULL AND \"workflow_schedule\".\"status\" NOT IN ('disabled', 'completed') AND \"workflow_schedule\".\"source_type\" = 'job'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_schedule_workflow_id_workflow_id_fk": { + "name": "workflow_schedule_workflow_id_workflow_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_deployment_version_id_workflow_deployment_version_id_fk": { + "name": "workflow_schedule_deployment_version_id_workflow_deployment_version_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_deployment_version", + "columnsFrom": [ + "deployment_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_deployment_operation_id_workflow_deployment_operation_id_fk": { + "name": "workflow_schedule_deployment_operation_id_workflow_deployment_operation_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_deployment_operation", + "columnsFrom": [ + "deployment_operation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workflow_schedule_source_user_id_user_id_fk": { + "name": "workflow_schedule_source_user_id_user_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "user", + "columnsFrom": [ + "source_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_source_workspace_id_workspace_id_fk": { + "name": "workflow_schedule_source_workspace_id_workspace_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workspace", + "columnsFrom": [ + "source_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_subflows": { + "name": "workflow_subflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_subflows_workflow_type_idx": { + "name": "workflow_subflows_workflow_type_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_subflows_workflow_id_workflow_id_fk": { + "name": "workflow_subflows_workflow_id_workflow_id_fk", + "tableFrom": "workflow_subflows", + "tableTo": "workflow", + "columnsFrom": [ + "workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_test": { + "name": "workflow_test", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body_file_id": { + "name": "body_file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cases": { + "name": "cases", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "source_hash": { + "name": "source_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_test_workspace_name_unique": { + "name": "workflow_test_workspace_name_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workflow_test\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_test_body_file_unique": { + "name": "workflow_test_body_file_unique", + "columns": [ + { + "expression": "body_file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_test_workspace_id_workspace_id_fk": { + "name": "workflow_test_workspace_id_workspace_id_fk", + "tableFrom": "workflow_test", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_test_body_file_id_workspace_files_id_fk": { + "name": "workflow_test_body_file_id_workspace_files_id_fk", + "tableFrom": "workflow_test", + "tableTo": "workspace_files", + "columnsFrom": [ + "body_file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workflow_test_created_by_user_id_user_id_fk": { + "name": "workflow_test_created_by_user_id_user_id_fk", + "tableFrom": "workflow_test", + "tableTo": "user", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_test_run": { + "name": "workflow_test_run", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "test_id": { + "name": "test_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "passed": { + "name": "passed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "failed": { + "name": "failed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "skipped": { + "name": "skipped", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "report": { + "name": "report", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_hash": { + "name": "source_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ran_against": { + "name": "ran_against", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "progress": { + "name": "progress", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "triggered_by_actor": { + "name": "triggered_by_actor", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "triggered_by_user_id": { + "name": "triggered_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_test_run_test_version_started_idx": { + "name": "workflow_test_run_test_version_started_idx", + "columns": [ + { + "expression": "test_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_test_run_test_id_workflow_test_id_fk": { + "name": "workflow_test_run_test_id_workflow_test_id_fk", + "tableFrom": "workflow_test_run", + "tableTo": "workflow_test", + "columnsFrom": [ + "test_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_test_run_workspace_id_workspace_id_fk": { + "name": "workflow_test_run_workspace_id_workspace_id_fk", + "tableFrom": "workflow_test_run", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_test_run_triggered_by_user_id_user_id_fk": { + "name": "workflow_test_run_triggered_by_user_id_user_id_fk", + "tableFrom": "workflow_test_run", + "tableTo": "user", + "columnsFrom": [ + "triggered_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "workflow_test_run_version_check": { + "name": "workflow_test_run_version_check", + "value": "\"workflow_test_run\".\"version\" IN ('draft', 'deployed')" + }, + "workflow_test_run_status_check": { + "name": "workflow_test_run_status_check", + "value": "\"workflow_test_run\".\"status\" IN ('running', 'passed', 'failed', 'error')" + }, + "workflow_test_run_completed_check": { + "name": "workflow_test_run_completed_check", + "value": "(\"workflow_test_run\".\"status\" = 'running') = (\"workflow_test_run\".\"completed_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#33C482'" + }, + "logo_url": { + "name": "logo_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_scope_key": { + "name": "organization_scope_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "CASE WHEN organization_id IS NULL THEN 'personal' ELSE 'organization:' || organization_id END", + "type": "stored" + } + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_mode": { + "name": "workspace_mode", + "type": "workspace_mode", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'grandfathered_shared'" + }, + "billed_account_user_id": { + "name": "billed_account_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "allow_personal_api_keys": { + "name": "allow_personal_api_keys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "inbox_enabled": { + "name": "inbox_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "inbox_address": { + "name": "inbox_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "inbox_provider_id": { + "name": "inbox_provider_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "inbox_secret_scope": { + "name": "inbox_secret_scope", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "inbox_mounted_secrets": { + "name": "inbox_mounted_secrets", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "organization_assigned_at": { + "name": "organization_assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "forked_from_workspace_id": { + "name": "forked_from_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fork_sync_new_workflows_excluded": { + "name": "fork_sync_new_workflows_excluded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_owner_id_idx": { + "name": "workspace_owner_id_idx", + "columns": [ + { + "expression": "owner_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_organization_id_idx": { + "name": "workspace_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_billed_account_user_id_idx": { + "name": "workspace_billed_account_user_id_idx", + "columns": [ + { + "expression": "billed_account_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_project_id_id_idx": { + "name": "workspace_project_id_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_mode_idx": { + "name": "workspace_mode_idx", + "columns": [ + { + "expression": "workspace_mode", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_forked_from_workspace_id_idx": { + "name": "workspace_forked_from_workspace_id_idx", + "columns": [ + { + "expression": "forked_from_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_inbox_provider_id_idx": { + "name": "workspace_inbox_provider_id_idx", + "columns": [ + { + "expression": "inbox_provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workspace\".\"inbox_provider_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_owner_id_user_id_fk": { + "name": "workspace_owner_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_organization_id_organization_id_fk": { + "name": "workspace_organization_id_organization_id_fk", + "tableFrom": "workspace", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workspace_project_id_project_id_fk": { + "name": "workspace_project_id_project_id_fk", + "tableFrom": "workspace", + "tableTo": "project", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "workspace_billed_account_user_id_user_id_fk": { + "name": "workspace_billed_account_user_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": [ + "billed_account_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workspace_forked_from_workspace_id_workspace_id_fk": { + "name": "workspace_forked_from_workspace_id_workspace_id_fk", + "tableFrom": "workspace", + "tableTo": "workspace", + "columnsFrom": [ + "forked_from_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workspace_project_organization_fk": { + "name": "workspace_project_organization_fk", + "tableFrom": "workspace", + "tableTo": "project", + "columnsFrom": [ + "project_id", + "organization_scope_key" + ], + "columnsTo": [ + "id", + "organization_scope_key" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "workspace_fork_project_fk": { + "name": "workspace_fork_project_fk", + "tableFrom": "workspace", + "tableTo": "workspace", + "columnsFrom": [ + "forked_from_workspace_id", + "project_id" + ], + "columnsTo": [ + "id", + "project_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_id_project_unique": { + "name": "workspace_id_project_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "project_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_storage_used_bytes_non_negative": { + "name": "workspace_storage_used_bytes_non_negative", + "value": "\"workspace\".\"storage_used_bytes\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.workspace_byok_keys": { + "name": "workspace_byok_keys", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encrypted_api_key": { + "name": "encrypted_api_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_byok_workspace_provider_idx": { + "name": "workspace_byok_workspace_provider_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_byok_keys_workspace_id_workspace_id_fk": { + "name": "workspace_byok_keys_workspace_id_workspace_id_fk", + "tableFrom": "workspace_byok_keys", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_byok_keys_created_by_user_id_fk": { + "name": "workspace_byok_keys_created_by_user_id_fk", + "tableFrom": "workspace_byok_keys", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_environment": { + "name": "workspace_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_environment_workspace_unique": { + "name": "workspace_environment_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_environment_workspace_id_workspace_id_fk": { + "name": "workspace_environment_workspace_id_workspace_id_fk", + "tableFrom": "workspace_environment", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file": { + "name": "workspace_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_workspace_id_idx": { + "name": "workspace_file_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_deleted_at_idx": { + "name": "workspace_file_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_workspace_deleted_partial_idx": { + "name": "workspace_file_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_uploaded_by_idx": { + "name": "workspace_file_uploaded_by_idx", + "columns": [ + { + "expression": "uploaded_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_workspace_id_workspace_id_fk": { + "name": "workspace_file_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_uploaded_by_user_id_fk": { + "name": "workspace_file_uploaded_by_user_id_fk", + "tableFrom": "workspace_file", + "tableTo": "user", + "columnsFrom": [ + "uploaded_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_file_key_unique": { + "name": "workspace_file_key_unique", + "nullsNotDistinct": false, + "columns": [ + "key" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_collab_state": { + "name": "workspace_file_collab_state", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "doc_state": { + "name": "doc_state", + "type": "bytea", + "primaryKey": false, + "notNull": true + }, + "source_hash": { + "name": "source_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_file_collab_state_file_id_workspace_files_id_fk": { + "name": "workspace_file_collab_state_file_id_workspace_files_id_fk", + "tableFrom": "workspace_file_collab_state", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_search_backfill": { + "name": "workspace_file_search_backfill", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "after_workspace_id": { + "name": "after_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "after_entity_type": { + "name": "after_entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "after_entity_id": { + "name": "after_entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "after_file_id": { + "name": "after_file_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_search_build": { + "name": "workspace_file_search_build", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "artifact_key": { + "name": "artifact_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_content_updated_at": { + "name": "source_content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workspace_file_search_build_file_idx": { + "name": "workspace_file_search_build_file_idx", + "columns": [ + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_build_cleanup_idx": { + "name": "workspace_file_search_build_cleanup_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_build\".\"expires_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "file_search_build_owner_check": { + "name": "file_search_build_owner_check", + "value": "(\"workspace_file_search_build\".\"entity_type\" IS NULL AND \"workspace_file_search_build\".\"entity_id\" IS NULL AND \"workspace_file_search_build\".\"workspace_id\" IS NOT NULL) OR (\"workspace_file_search_build\".\"entity_type\" = 'workspace' AND \"workspace_file_search_build\".\"entity_id\" = \"workspace_file_search_build\".\"workspace_id\") OR (\"workspace_file_search_build\".\"entity_type\" = 'project' AND length(\"workspace_file_search_build\".\"entity_id\") > 0 AND \"workspace_file_search_build\".\"workspace_id\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.workspace_file_search_chunk": { + "name": "workspace_file_search_chunk", + "schema": "", + "columns": { + "build_id": { + "name": "build_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ordinal": { + "name": "ordinal", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "line_start": { + "name": "line_start", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "fragment": { + "name": "fragment", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "overlap": { + "name": "overlap", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "file_search_chunk_owner_content_idx": { + "name": "file_search_chunk_owner_content_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "text_ops" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "text_ops" + }, + { + "expression": "content", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "gin_trgm_ops" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_chunk\".\"entity_type\" = 'project'", + "concurrently": true, + "method": "gin", + "with": { + "fastupdate": "off" + } + }, + "workspace_file_search_chunk_line_idx": { + "name": "workspace_file_search_chunk_line_idx", + "columns": [ + { + "expression": "build_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "line_start", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "ordinal", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_chunk_content_idx": { + "name": "workspace_file_search_chunk_content_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "text_ops" + }, + { + "expression": "content", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "gin_trgm_ops" + } + ], + "isUnique": false, + "concurrently": true, + "method": "gin", + "with": { + "fastupdate": "off" + } + } + }, + "foreignKeys": { + "workspace_file_search_chunk_build_id_workspace_file_search_build_id_fk": { + "name": "workspace_file_search_chunk_build_id_workspace_file_search_build_id_fk", + "tableFrom": "workspace_file_search_chunk", + "tableTo": "workspace_file_search_build", + "columnsFrom": [ + "build_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "workspace_file_search_chunk_pk": { + "name": "workspace_file_search_chunk_pk", + "columns": [ + "build_id", + "ordinal" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "file_search_chunk_owner_check": { + "name": "file_search_chunk_owner_check", + "value": "(\"workspace_file_search_chunk\".\"entity_type\" IS NULL AND \"workspace_file_search_chunk\".\"entity_id\" IS NULL AND \"workspace_file_search_chunk\".\"workspace_id\" IS NOT NULL) OR (\"workspace_file_search_chunk\".\"entity_type\" = 'workspace' AND \"workspace_file_search_chunk\".\"entity_id\" = \"workspace_file_search_chunk\".\"workspace_id\") OR (\"workspace_file_search_chunk\".\"entity_type\" = 'project' AND length(\"workspace_file_search_chunk\".\"entity_id\") > 0 AND \"workspace_file_search_chunk\".\"workspace_id\" IS NULL)" + }, + "workspace_file_search_chunk_content_size": { + "name": "workspace_file_search_chunk_content_size", + "value": "octet_length(\"workspace_file_search_chunk\".\"content\") <= 8192" + }, + "workspace_file_search_chunk_position": { + "name": "workspace_file_search_chunk_position", + "value": "\"workspace_file_search_chunk\".\"ordinal\" >= 0 AND \"workspace_file_search_chunk\".\"line_start\" > 0 AND \"workspace_file_search_chunk\".\"overlap\" BETWEEN 0 AND 2" + } + }, + "isRLSEnabled": false + }, + "public.workspace_file_search_dispatch_queue": { + "name": "workspace_file_search_dispatch_queue", + "schema": "", + "columns": { + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "enqueued_at": { + "name": "enqueued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_dispatched_at": { + "name": "last_dispatched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_search_dispatch_queue_schedule_idx": { + "name": "workspace_file_search_dispatch_queue_schedule_idx", + "columns": [ + { + "expression": "last_dispatched_at", + "isExpression": false, + "asc": true, + "nulls": "first" + }, + { + "expression": "enqueued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_search_queue_workspace_fk": { + "name": "workspace_file_search_queue_workspace_fk", + "tableFrom": "workspace_file_search_dispatch_queue", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_search_index": { + "name": "workspace_file_search_index", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_content_updated_at": { + "name": "source_content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "workspace_file_search_index_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "partial": { + "name": "partial", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "line_count": { + "name": "line_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "indexed_bytes": { + "name": "indexed_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "dispatched_at": { + "name": "dispatched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_search_index_workspace_status_idx": { + "name": "workspace_file_search_index_workspace_status_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_content_updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_index_pending_dispatch_idx": { + "name": "workspace_file_search_index_pending_dispatch_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_content_updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_index\".\"status\" = 'pending' AND \"workspace_file_search_index\".\"dispatched_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_index_active_dispatch_idx": { + "name": "workspace_file_search_index_active_dispatch_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "dispatched_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_index\".\"status\" = 'pending' AND \"workspace_file_search_index\".\"dispatched_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_search_index_file_fk": { + "name": "workspace_file_search_index_file_fk", + "tableFrom": "workspace_file_search_index", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_search_index_workspace_fk": { + "name": "workspace_file_search_index_workspace_fk", + "tableFrom": "workspace_file_search_index", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "workspace_file_search_index_pk": { + "name": "workspace_file_search_index_pk", + "columns": [ + "file_id", + "source_content_updated_at" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_search_revision": { + "name": "workspace_file_search_revision", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_content_updated_at": { + "name": "source_content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "workspace_file_search_index_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "build_id": { + "name": "build_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "line_count": { + "name": "line_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "indexed_bytes": { + "name": "indexed_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "dispatched_at": { + "name": "dispatched_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "handoff_expires_at": { + "name": "handoff_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "file_search_revision_owner_pending_idx": { + "name": "file_search_revision_owner_pending_idx", + "columns": [ + { + "expression": "coalesce(\"entity_type\", 'workspace')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"entity_id\", \"workspace_id\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_content_updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_revision\".\"status\" = 'pending' AND \"workspace_file_search_revision\".\"dispatched_at\" IS NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "file_search_revision_owner_status_idx": { + "name": "file_search_revision_owner_status_idx", + "columns": [ + { + "expression": "coalesce(\"entity_type\", 'workspace')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"entity_id\", \"workspace_id\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "dispatched_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_file_search_revision_workspace_status_idx": { + "name": "workspace_file_search_revision_workspace_status_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_revision_build_idx": { + "name": "workspace_file_search_revision_build_idx", + "columns": [ + { + "expression": "build_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_revision_pending_idx": { + "name": "workspace_file_search_revision_pending_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_content_updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_revision\".\"status\" = 'pending' AND \"workspace_file_search_revision\".\"dispatched_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_revision_active_idx": { + "name": "workspace_file_search_revision_active_idx", + "columns": [ + { + "expression": "dispatched_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_search_revision\".\"status\" = 'pending' AND \"workspace_file_search_revision\".\"dispatched_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_search_revision_file_id_workspace_files_id_fk": { + "name": "workspace_file_search_revision_file_id_workspace_files_id_fk", + "tableFrom": "workspace_file_search_revision", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_search_revision_build_id_workspace_file_search_build_id_fk": { + "name": "workspace_file_search_revision_build_id_workspace_file_search_build_id_fk", + "tableFrom": "workspace_file_search_revision", + "tableTo": "workspace_file_search_build", + "columnsFrom": [ + "build_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "file_search_revision_owner_check": { + "name": "file_search_revision_owner_check", + "value": "(\"workspace_file_search_revision\".\"entity_type\" IS NULL AND \"workspace_file_search_revision\".\"entity_id\" IS NULL AND \"workspace_file_search_revision\".\"workspace_id\" IS NOT NULL) OR (\"workspace_file_search_revision\".\"entity_type\" = 'workspace' AND \"workspace_file_search_revision\".\"entity_id\" = \"workspace_file_search_revision\".\"workspace_id\") OR (\"workspace_file_search_revision\".\"entity_type\" = 'project' AND length(\"workspace_file_search_revision\".\"entity_id\") > 0 AND \"workspace_file_search_revision\".\"workspace_id\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.workspace_file_search_segment": { + "name": "workspace_file_search_segment", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_content_updated_at": { + "name": "source_content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "line_number": { + "name": "line_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "segment_number": { + "name": "segment_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "segment_start": { + "name": "segment_start", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "line_length": { + "name": "line_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "workspace_file_search_segment_workspace_revision_idx": { + "name": "workspace_file_search_segment_workspace_revision_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_content_updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_search_segment_workspace_content_trgm_idx": { + "name": "workspace_file_search_segment_workspace_content_trgm_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "text_ops" + }, + { + "expression": "content", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "gin_trgm_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_search_segment_file_fk": { + "name": "workspace_file_search_segment_file_fk", + "tableFrom": "workspace_file_search_segment", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_search_segment_workspace_fk": { + "name": "workspace_file_search_segment_workspace_fk", + "tableFrom": "workspace_file_search_segment", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "workspace_file_search_segment_pk": { + "name": "workspace_file_search_segment_pk", + "columns": [ + "file_id", + "source_content_updated_at", + "line_number", + "segment_number" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file_secret_provenance": { + "name": "workspace_file_secret_provenance", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content_updated_at": { + "name": "content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entries": { + "name": "entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_file_secret_provenance_file_id_workspace_files_id_fk": { + "name": "workspace_file_secret_provenance_file_id_workspace_files_id_fk", + "tableFrom": "workspace_file_secret_provenance", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "workspace_file_secret_provenance_status_check": { + "name": "workspace_file_secret_provenance_status_check", + "value": "\"workspace_file_secret_provenance\".\"status\" IN ('exact', 'unknown', 'unrecorded')" + } + }, + "isRLSEnabled": false + }, + "public.workspace_file_version": { + "name": "workspace_file_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size_bytes": { + "name": "size_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "superseded_at": { + "name": "superseded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "workspace_file_version_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "author_user_ids": { + "name": "author_user_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "restored_from_version": { + "name": "restored_from_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "secret_provenance_status": { + "name": "secret_provenance_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_provenance_entries": { + "name": "secret_provenance_entries", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_version_file_version_unique": { + "name": "workspace_file_version_file_version_unique", + "columns": [ + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_version_key_unique": { + "name": "workspace_file_version_key_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_version_workspace_id_idx": { + "name": "workspace_file_version_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_version_workspace_superseded_idx": { + "name": "workspace_file_version_workspace_superseded_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "superseded_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_file_version\".\"superseded_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_version_file_id_workspace_files_id_fk": { + "name": "workspace_file_version_file_id_workspace_files_id_fk", + "tableFrom": "workspace_file_version", + "tableTo": "workspace_files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_version_workspace_id_workspace_id_fk": { + "name": "workspace_file_version_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file_version", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "workspace_file_version_provenance_status_check": { + "name": "workspace_file_version_provenance_status_check", + "value": "\"workspace_file_version\".\"secret_provenance_status\" IS NULL OR \"workspace_file_version\".\"secret_provenance_status\" IN ('exact', 'unknown', 'unrecorded')" + } + }, + "isRLSEnabled": false + }, + "public.workspace_files": { + "name": "workspace_files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size_bytes": { + "name": "size_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "width": { + "name": "width", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "height": { + "name": "height", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "content_updated_at": { + "name": "content_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "date_trunc('milliseconds', now())" + }, + "secret_provenance_version": { + "name": "secret_provenance_version", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workspace_files_project_id_idx": { + "name": "workspace_files_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_project_folder_name_active_unique": { + "name": "workspace_files_project_folder_name_active_unique", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"folder_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "original_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"project_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_key_active_unique": { + "name": "workspace_files_key_active_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workspace_files\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_folder_name_active_unique": { + "name": "workspace_files_workspace_folder_name_active_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"folder_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "original_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_search_owner_keyset_idx": { + "name": "workspace_files_search_owner_keyset_idx", + "columns": [ + { + "expression": "(CASE WHEN \"project_id\" IS NOT NULL THEN 'project' ELSE 'workspace' END)", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"project_id\", \"workspace_id\")", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND ((\"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL) OR (\"workspace_files\".\"context\" = 'project' AND \"workspace_files\".\"project_id\" IS NOT NULL))", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_active_keyset_idx": { + "name": "workspace_files_workspace_active_keyset_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_active_uploaded_idx": { + "name": "workspace_files_workspace_active_uploaded_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "uploaded_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_folder_uploaded_idx": { + "name": "workspace_files_workspace_folder_uploaded_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "coalesce(\"folder_id\", '')", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "uploaded_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_name_trgm_idx": { + "name": "workspace_files_workspace_name_trgm_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "text_ops" + }, + { + "expression": "original_name", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "gin_trgm_ops" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": true, + "method": "gin", + "with": { + "fastupdate": "off" + } + }, + "workspace_files_workspace_display_name_idx": { + "name": "workspace_files_workspace_display_name_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "regexp_replace(regexp_replace(regexp_replace(normalize(\"original_name\", NFC), '^[ \\t\\n\\v\\f\\r\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]+|[ \\t\\n\\v\\f\\r\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]+$', '', 'g'), '[\\x01-\\x1f\\x7f]', '', 'g'), '[ \\t\\n\\v\\f\\r\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]+', ' ', 'g')", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NULL AND \"workspace_files\".\"context\" = 'workspace' AND \"workspace_files\".\"workspace_id\" IS NOT NULL", + "concurrently": true, + "method": "btree", + "with": {} + }, + "workspace_files_chat_display_name_unique": { + "name": "workspace_files_chat_display_name_unique", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"workspace_files\".\"context\" = 'mothership' AND \"workspace_files\".\"chat_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_organization_id_idx": { + "name": "workspace_files_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_key_idx": { + "name": "workspace_files_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_user_id_idx": { + "name": "workspace_files_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_id_idx": { + "name": "workspace_files_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_folder_id_idx": { + "name": "workspace_files_folder_id_idx", + "columns": [ + { + "expression": "folder_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_context_idx": { + "name": "workspace_files_context_idx", + "columns": [ + { + "expression": "context", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_chat_id_idx": { + "name": "workspace_files_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_deleted_at_idx": { + "name": "workspace_files_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_deleted_partial_idx": { + "name": "workspace_files_workspace_deleted_partial_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_files\".\"deleted_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_files_project_id_project_id_fk": { + "name": "workspace_files_project_id_project_id_fk", + "tableFrom": "workspace_files", + "tableTo": "project", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "workspace_files_user_id_user_id_fk": { + "name": "workspace_files_user_id_user_id_fk", + "tableFrom": "workspace_files", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_workspace_id_workspace_id_fk": { + "name": "workspace_files_workspace_id_workspace_id_fk", + "tableFrom": "workspace_files", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_organization_id_organization_id_fk": { + "name": "workspace_files_organization_id_organization_id_fk", + "tableFrom": "workspace_files", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_folder_id_folder_id_fk": { + "name": "workspace_files_folder_id_folder_id_fk", + "tableFrom": "workspace_files", + "tableTo": "folder", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "workspace_files_chat_id_copilot_chats_id_fk": { + "name": "workspace_files_chat_id_copilot_chats_id_fk", + "tableFrom": "workspace_files", + "tableTo": "copilot_chats", + "columnsFrom": [ + "chat_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "workspace_files_owner_check": { + "name": "workspace_files_owner_check", + "value": "num_nonnulls(\"workspace_files\".\"workspace_id\", \"workspace_files\".\"project_id\", \"workspace_files\".\"organization_id\") <= 1" + }, + "workspace_files_workspace_binding_check": { + "name": "workspace_files_workspace_binding_check", + "value": "\"workspace_files\".\"context\" NOT IN ('workspace', 'chat', 'mothership', 'execution', 'workspace-logos') OR \"workspace_files\".\"workspace_id\" IS NOT NULL" + }, + "workspace_files_project_binding_check": { + "name": "workspace_files_project_binding_check", + "value": "(\"workspace_files\".\"project_id\" IS NOT NULL) = (\"workspace_files\".\"context\" = 'project') AND (\"workspace_files\".\"project_id\" IS NULL OR \"workspace_files\".\"chat_id\" IS NULL)" + }, + "workspace_files_organization_binding_check": { + "name": "workspace_files_organization_binding_check", + "value": "\"workspace_files\".\"organization_id\" IS NULL OR (\"workspace_files\".\"workspace_id\" IS NULL AND \"workspace_files\".\"context\" = 'knowledge-base' AND \"workspace_files\".\"folder_id\" IS NULL AND \"workspace_files\".\"chat_id\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.workspace_fork_block_map": { + "name": "workspace_fork_block_map", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "child_workspace_id": { + "name": "child_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_workflow_id": { + "name": "parent_workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_block_id": { + "name": "parent_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "child_workflow_id": { + "name": "child_workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "child_block_id": { + "name": "child_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_fork_block_map_child_ws_parent_unique": { + "name": "workspace_fork_block_map_child_ws_parent_unique", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_block_map_child_ws_child_unique": { + "name": "workspace_fork_block_map_child_ws_child_unique", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "child_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_block_map_child_ws_parent_wf_idx": { + "name": "workspace_fork_block_map_child_ws_parent_wf_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_block_map_child_ws_child_wf_idx": { + "name": "workspace_fork_block_map_child_ws_child_wf_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "child_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_fork_block_map_child_workspace_id_workspace_id_fk": { + "name": "workspace_fork_block_map_child_workspace_id_workspace_id_fk", + "tableFrom": "workspace_fork_block_map", + "tableTo": "workspace", + "columnsFrom": [ + "child_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_fork_dependent_value": { + "name": "workspace_fork_dependent_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "child_workspace_id": { + "name": "child_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_workflow_id": { + "name": "target_workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sub_block_key": { + "name": "sub_block_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_fork_dependent_value_field_unique": { + "name": "workspace_fork_dependent_value_field_unique", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sub_block_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_fork_dependent_value_child_workspace_id_workspace_id_fk": { + "name": "workspace_fork_dependent_value_child_workspace_id_workspace_id_fk", + "tableFrom": "workspace_fork_dependent_value", + "tableTo": "workspace", + "columnsFrom": [ + "child_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_fork_promote_run": { + "name": "workspace_fork_promote_run", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "child_workspace_id": { + "name": "child_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_workspace_id": { + "name": "source_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_workspace_id": { + "name": "target_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "direction": { + "name": "direction", + "type": "workspace_fork_promote_direction", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "snapshot": { + "name": "snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_fork_promote_run_child_ws_target_unique": { + "name": "workspace_fork_promote_run_child_ws_target_unique", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_promote_run_target_ws_idx": { + "name": "workspace_fork_promote_run_target_ws_idx", + "columns": [ + { + "expression": "target_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_fork_promote_run_child_workspace_id_workspace_id_fk": { + "name": "workspace_fork_promote_run_child_workspace_id_workspace_id_fk", + "tableFrom": "workspace_fork_promote_run", + "tableTo": "workspace", + "columnsFrom": [ + "child_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_fork_promote_run_created_by_user_id_fk": { + "name": "workspace_fork_promote_run_created_by_user_id_fk", + "tableFrom": "workspace_fork_promote_run", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_fork_resource_map": { + "name": "workspace_fork_resource_map", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "child_workspace_id": { + "name": "child_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "workspace_fork_resource_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "parent_resource_id": { + "name": "parent_resource_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "child_resource_id": { + "name": "child_resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_fork_resource_map_child_type_parent_unique": { + "name": "workspace_fork_resource_map_child_type_parent_unique", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_fork_resource_map_child_workspace_id_workspace_id_fk": { + "name": "workspace_fork_resource_map_child_workspace_id_workspace_id_fk", + "tableFrom": "workspace_fork_resource_map", + "tableTo": "workspace", + "columnsFrom": [ + "child_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_fork_resource_map_created_by_user_id_fk": { + "name": "workspace_fork_resource_map_created_by_user_id_fk", + "tableFrom": "workspace_fork_resource_map", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_fork_workflow_sync": { + "name": "workspace_fork_workflow_sync", + "schema": "", + "columns": { + "deployment_operation_id": { + "name": "deployment_operation_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "child_workspace_id": { + "name": "child_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_workflow_id": { + "name": "source_workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_workflow_id": { + "name": "target_workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_deployment_version_id": { + "name": "source_deployment_version_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sequence": { + "name": "sequence", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "workspace_fork_workflow_sync_sequence_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "promote_run_id": { + "name": "promote_run_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "activated_at": { + "name": "activated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "rollback_operation_id": { + "name": "rollback_operation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rolled_back_at": { + "name": "rolled_back_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workspace_fork_workflow_sync_baseline_idx": { + "name": "workspace_fork_workflow_sync_baseline_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sequence", + "isExpression": false, + "asc": false, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_fork_workflow_sync\".\"activated_at\" IS NOT NULL AND \"workspace_fork_workflow_sync\".\"rolled_back_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_workflow_sync_run_idx": { + "name": "workspace_fork_workflow_sync_run_idx", + "columns": [ + { + "expression": "promote_run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_workflow_sync_rollback_idx": { + "name": "workspace_fork_workflow_sync_rollback_idx", + "columns": [ + { + "expression": "rollback_operation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"workspace_fork_workflow_sync\".\"rollback_operation_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_workflow_sync_source_idx": { + "name": "workspace_fork_workflow_sync_source_idx", + "columns": [ + { + "expression": "source_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_workflow_sync_target_idx": { + "name": "workspace_fork_workflow_sync_target_idx", + "columns": [ + { + "expression": "target_workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_workflow_sync_child_workspace_idx": { + "name": "workspace_fork_workflow_sync_child_workspace_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_fork_workflow_sync_child_workspace_id_workspace_id_fk": { + "name": "workspace_fork_workflow_sync_child_workspace_id_workspace_id_fk", + "tableFrom": "workspace_fork_workflow_sync", + "tableTo": "workspace", + "columnsFrom": [ + "child_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_fork_workflow_sync_source_workflow_id_workflow_id_fk": { + "name": "workspace_fork_workflow_sync_source_workflow_id_workflow_id_fk", + "tableFrom": "workspace_fork_workflow_sync", + "tableTo": "workflow", + "columnsFrom": [ + "source_workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_fork_workflow_sync_target_workflow_id_workflow_id_fk": { + "name": "workspace_fork_workflow_sync_target_workflow_id_workflow_id_fk", + "tableFrom": "workspace_fork_workflow_sync", + "tableTo": "workflow", + "columnsFrom": [ + "target_workflow_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_operation_receipt": { + "name": "workspace_operation_receipt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "request_hash": { + "name": "request_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "report": { + "name": "report", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_operation_receipt_request_unique": { + "name": "workspace_operation_receipt_request_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_operation_receipt_workspace_created_idx": { + "name": "workspace_operation_receipt_workspace_created_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_operation_receipt_workspace_id_workspace_id_fk": { + "name": "workspace_operation_receipt_workspace_id_workspace_id_fk", + "tableFrom": "workspace_operation_receipt", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_sandbox": { + "name": "workspace_sandbox", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "language": { + "name": "language", + "type": "sandbox_language", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "dependencies": { + "name": "dependencies", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "cli_tools": { + "name": "cli_tools", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "system_packages": { + "name": "system_packages", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "spec_hash": { + "name": "spec_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_sandbox_workspace_name_unique": { + "name": "workspace_sandbox_workspace_name_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_sandbox_spec_hash_idx": { + "name": "workspace_sandbox_spec_hash_idx", + "columns": [ + { + "expression": "spec_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_sandbox_workspace_id_workspace_id_fk": { + "name": "workspace_sandbox_workspace_id_workspace_id_fk", + "tableFrom": "workspace_sandbox", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_sandbox_created_by_user_id_fk": { + "name": "workspace_sandbox_created_by_user_id_fk", + "tableFrom": "workspace_sandbox", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_visit": { + "name": "workspace_visit", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "visited_at": { + "name": "visited_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_visit_workspace_idx": { + "name": "workspace_visit_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_visit_user_id_user_id_fk": { + "name": "workspace_visit_user_id_user_id_fk", + "tableFrom": "workspace_visit", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_visit_workspace_id_workspace_id_fk": { + "name": "workspace_visit_workspace_id_workspace_id_fk", + "tableFrom": "workspace_visit", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "workspace_visit_user_id_workspace_id_pk": { + "name": "workspace_visit_user_id_workspace_id_pk", + "columns": [ + "user_id", + "workspace_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.api_key_access": { + "name": "api_key_access", + "schema": "public", + "values": [ + "read", + "write" + ] + }, + "public.aws_marketplace_license_status": { + "name": "aws_marketplace_license_status", + "schema": "public", + "values": [ + "pending", + "active", + "inactive" + ] + }, + "public.background_work_kind": { + "name": "background_work_kind", + "schema": "public", + "values": [ + "deployment_side_effects", + "fork_content_copy", + "fork_sync", + "fork_rollback" + ] + }, + "public.background_work_status_value": { + "name": "background_work_status_value", + "schema": "public", + "values": [ + "pending", + "processing", + "completed", + "completed_with_warnings", + "failed" + ] + }, + "public.billing_blocked_reason": { + "name": "billing_blocked_reason", + "schema": "public", + "values": [ + "payment_failed", + "dispute" + ] + }, + "public.billing_entity_type": { + "name": "billing_entity_type", + "schema": "public", + "values": [ + "user", + "organization" + ] + }, + "public.chat_type": { + "name": "chat_type", + "schema": "public", + "values": [ + "mothership", + "copilot" + ] + }, + "public.copilot_async_tool_status": { + "name": "copilot_async_tool_status", + "schema": "public", + "values": [ + "pending", + "running", + "completed", + "failed", + "cancelled", + "delivered" + ] + }, + "public.copilot_run_status": { + "name": "copilot_run_status", + "schema": "public", + "values": [ + "active", + "paused_waiting_for_tool", + "resuming", + "complete", + "error", + "cancelled" + ] + }, + "public.copilot_tool_permission_decision": { + "name": "copilot_tool_permission_decision", + "schema": "public", + "values": [ + "allow", + "allow_chat", + "always_allow", + "skip" + ] + }, + "public.credential_group_enrollment_status": { + "name": "credential_group_enrollment_status", + "schema": "public", + "values": [ + "invited", + "delivery_failed", + "in_progress", + "completed", + "revoked" + ] + }, + "public.credential_group_status": { + "name": "credential_group_status", + "schema": "public", + "values": [ + "active", + "disabled" + ] + }, + "public.credential_member_role": { + "name": "credential_member_role", + "schema": "public", + "values": [ + "admin", + "member" + ] + }, + "public.credential_member_status": { + "name": "credential_member_status", + "schema": "public", + "values": [ + "active", + "pending", + "revoked" + ] + }, + "public.credential_type": { + "name": "credential_type", + "schema": "public", + "values": [ + "oauth", + "managed_oauth", + "managed_mcp", + "env_workspace", + "env_personal", + "service_account", + "personal_token" + ] + }, + "public.data_drain_cadence": { + "name": "data_drain_cadence", + "schema": "public", + "values": [ + "hourly", + "daily" + ] + }, + "public.data_drain_destination": { + "name": "data_drain_destination", + "schema": "public", + "values": [ + "s3", + "gcs", + "azure_blob", + "sentinel", + "datadog", + "bigquery", + "snowflake", + "webhook" + ] + }, + "public.data_drain_run_status": { + "name": "data_drain_run_status", + "schema": "public", + "values": [ + "running", + "success", + "failed" + ] + }, + "public.data_drain_run_trigger": { + "name": "data_drain_run_trigger", + "schema": "public", + "values": [ + "cron", + "manual" + ] + }, + "public.data_drain_source": { + "name": "data_drain_source", + "schema": "public", + "values": [ + "workflow_logs", + "job_logs", + "audit_logs", + "copilot_chats", + "copilot_runs" + ] + }, + "public.execution_large_value_reference_source": { + "name": "execution_large_value_reference_source", + "schema": "public", + "values": [ + "execution_log", + "paused_snapshot" + ] + }, + "public.folder_resource_type": { + "name": "folder_resource_type", + "schema": "public", + "values": [ + "workflow", + "file", + "knowledge_base", + "table" + ] + }, + "public.invitation_kind": { + "name": "invitation_kind", + "schema": "public", + "values": [ + "organization", + "workspace" + ] + }, + "public.invitation_membership_intent": { + "name": "invitation_membership_intent", + "schema": "public", + "values": [ + "internal", + "external" + ] + }, + "public.invitation_status": { + "name": "invitation_status", + "schema": "public", + "values": [ + "pending", + "accepted", + "rejected", + "cancelled", + "expired" + ] + }, + "public.managed_oauth_credential_status": { + "name": "managed_oauth_credential_status", + "schema": "public", + "values": [ + "active", + "needs_reauth", + "revoked" + ] + }, + "public.permission_type": { + "name": "permission_type", + "schema": "public", + "values": [ + "admin", + "write", + "read" + ] + }, + "public.sandbox_image_status": { + "name": "sandbox_image_status", + "schema": "public", + "values": [ + "pending", + "building", + "ready", + "failed" + ] + }, + "public.sandbox_language": { + "name": "sandbox_language", + "schema": "public", + "values": [ + "javascript", + "python" + ] + }, + "public.secret_usage_scope": { + "name": "secret_usage_scope", + "schema": "public", + "values": [ + "workspace", + "personal" + ] + }, + "public.secret_usage_source": { + "name": "secret_usage_source", + "schema": "public", + "values": [ + "workflow", + "copilot", + "mcp" + ] + }, + "public.upload_session_method": { + "name": "upload_session_method", + "schema": "public", + "values": [ + "put", + "multipart" + ] + }, + "public.upload_session_provider": { + "name": "upload_session_provider", + "schema": "public", + "values": [ + "local", + "s3", + "blob", + "gcs" + ] + }, + "public.upload_session_purpose": { + "name": "upload_session_purpose", + "schema": "public", + "values": [ + "workspace_file", + "project_file", + "table_import", + "knowledge_import", + "knowledge_document", + "profile_picture", + "workspace_logo", + "organization_logo", + "mothership_attachment", + "execution_attachment" + ] + }, + "public.upload_session_status": { + "name": "upload_session_status", + "schema": "public", + "values": [ + "uploading", + "completing", + "finalizing", + "completed", + "aborting", + "aborted", + "failed", + "expired" + ] + }, + "public.usage_log_category": { + "name": "usage_log_category", + "schema": "public", + "values": [ + "model", + "fixed", + "tool", + "model_unbilled" + ] + }, + "public.usage_log_source": { + "name": "usage_log_source", + "schema": "public", + "values": [ + "workflow", + "wand", + "copilot", + "workspace-chat", + "mcp_copilot", + "mothership_block", + "knowledge-base", + "voice-input", + "enrichment", + "voice-output", + "api-tool", + "workflow-test" + ] + }, + "public.workspace_file_search_index_status": { + "name": "workspace_file_search_index_status", + "schema": "public", + "values": [ + "pending", + "ready", + "skipped", + "failed" + ] + }, + "public.workspace_file_version_source": { + "name": "workspace_file_version_source", + "schema": "public", + "values": [ + "upload", + "user", + "api", + "copilot", + "workflow", + "collab", + "revert", + "unknown" + ] + }, + "public.workspace_fork_promote_direction": { + "name": "workspace_fork_promote_direction", + "schema": "public", + "values": [ + "push", + "pull" + ] + }, + "public.workspace_fork_resource_type": { + "name": "workspace_fork_resource_type", + "schema": "public", + "values": [ + "workflow", + "oauth_credential", + "service_account_credential", + "env_var", + "table", + "knowledge_base", + "knowledge_document", + "file", + "file_folder", + "mcp_server", + "workflow_mcp_server", + "custom_block", + "custom_tool", + "skill", + "sandbox" + ] + }, + "public.workspace_mode": { + "name": "workspace_mode", + "schema": "public", + "values": [ + "personal", + "organization", + "grandfathered_shared" + ] + } + }, + "schemas": {}, + "sequences": { + "public.copilot_async_tool_calls_persist_seq": { + "name": "copilot_async_tool_calls_persist_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 1489fe74be8..4db8b65115a 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -3179,6 +3179,13 @@ "when": 1793937981518, "tag": "0454_aws_marketplace_license", "breakpoints": true + }, + { + "idx": 455, + "version": "7", + "when": 1794342674732, + "tag": "0455_api_key_access", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/packages/db/schema.ts b/packages/db/schema.ts index f820b423751..92cb73299ca 100644 --- a/packages/db/schema.ts +++ b/packages/db/schema.ts @@ -1446,6 +1446,9 @@ export const simTriggerState = pgTable( }) ) +/** What an API key may do: `read` keys are refused every operation that changes state. */ +export const apiKeyAccessEnum = pgEnum('api_key_access', ['read', 'write']) + export const apiKey = pgTable( 'api_key', { @@ -1460,6 +1463,7 @@ export const apiKey = pgTable( key: text('key').notNull().unique(), keyHash: text('key_hash'), type: text('type').notNull().default('personal'), + access: apiKeyAccessEnum('access').notNull().default('write'), lastUsed: timestamp('last_used'), createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), diff --git a/packages/sim-cli/src/generated/v2-api.ts b/packages/sim-cli/src/generated/v2-api.ts index 992fa1a7246..af4f489039c 100644 --- a/packages/sim-cli/src/generated/v2-api.ts +++ b/packages/sim-cli/src/generated/v2-api.ts @@ -6629,6 +6629,7 @@ type GetMetaResponseRef0 = { v2Enabled: boolean keyType: 'personal' | 'workspace' | 'oauth_access_token' expiresAt: string | null + scopes: Array<'api:read' | 'api:write' | 'search:read'> } export type GetMetaResponse = { diff --git a/packages/testing/src/factories/principal.factory.ts b/packages/testing/src/factories/principal.factory.ts index 98b90edef4e..a7933e14171 100644 --- a/packages/testing/src/factories/principal.factory.ts +++ b/packages/testing/src/factories/principal.factory.ts @@ -29,18 +29,30 @@ export function createSessionPrincipal( return { kind: 'session', userId: 'user-1', sessionId: 'session-1', ...overrides } } -/** A personal-API-key principal. Defaults: `user-1` / `key-1`. */ +/** A personal-API-key principal. Defaults: `user-1` / `key-1`, write access. */ export function createPersonalApiKeyPrincipal( overrides: Partial = {} ): PersonalApiKeyPrincipal { - return { kind: 'personal_api_key', userId: 'user-1', keyId: 'key-1', ...overrides } + return { + kind: 'personal_api_key', + userId: 'user-1', + keyId: 'key-1', + access: 'write', + ...overrides, + } } -/** A workspace-API-key principal. Defaults: `workspace-1` / `key-1`. */ +/** A workspace-API-key principal. Defaults: `workspace-1` / `key-1`, write access. */ export function createWorkspaceApiKeyPrincipal( overrides: Partial = {} ): WorkspaceApiKeyPrincipal { - return { kind: 'workspace_api_key', workspaceId: 'workspace-1', keyId: 'key-1', ...overrides } + return { + kind: 'workspace_api_key', + workspaceId: 'workspace-1', + keyId: 'key-1', + access: 'write', + ...overrides, + } } /** diff --git a/packages/testing/src/mocks/schema-tables.generated.ts b/packages/testing/src/mocks/schema-tables.generated.ts index 24e91762785..40b184134bc 100644 --- a/packages/testing/src/mocks/schema-tables.generated.ts +++ b/packages/testing/src/mocks/schema-tables.generated.ts @@ -357,6 +357,7 @@ export const GENERATED_SCHEMA_TABLES = { 'key', 'keyHash', 'type', + 'access', 'lastUsed', 'createdAt', 'updatedAt', @@ -2272,6 +2273,7 @@ export const GENERATED_SCHEMA_ENUMS = { executionLargeValueReferenceSourceEnum: ['execution_log', 'paused_snapshot'], secretUsageScopeEnum: ['workspace', 'personal'], secretUsageSourceEnum: ['workflow', 'copilot', 'mcp'], + apiKeyAccessEnum: ['read', 'write'], billingBlockedReasonEnum: ['payment_failed', 'dispute'], billingEntityTypeEnum: ['user', 'organization'], awsMarketplaceLicenseStatusEnum: ['pending', 'active', 'inactive'], diff --git a/packages/testing/src/mocks/v1-route.mock.ts b/packages/testing/src/mocks/v1-route.mock.ts index bd6dc09cab8..99aeabd214e 100644 --- a/packages/testing/src/mocks/v1-route.mock.ts +++ b/packages/testing/src/mocks/v1-route.mock.ts @@ -41,7 +41,7 @@ export function v1PersonalKeyCredential(userId: string, keyId = 'key-1') { authenticated: true, userId, keyType: 'personal' as const, - principal: { kind: 'personal_api_key' as const, userId, keyId }, + principal: { kind: 'personal_api_key' as const, userId, keyId, access: 'write' as const }, } } @@ -68,6 +68,6 @@ export function v1WorkspaceKeyCredential( userId: creatorUserId, workspaceId, keyType: 'workspace' as const, - principal: { kind: 'workspace_api_key' as const, workspaceId, keyId }, + principal: { kind: 'workspace_api_key' as const, workspaceId, keyId, access: 'write' as const }, } } diff --git a/scripts/check-unused-exports.baseline.json b/scripts/check-unused-exports.baseline.json index dff09edea85..1c876935125 100644 --- a/scripts/check-unused-exports.baseline.json +++ b/scripts/check-unused-exports.baseline.json @@ -1153,7 +1153,6 @@ "apps/sim/lib/api-key/auth.ts#formatApiKeyForDisplay", "apps/sim/lib/api-key/auth.ts#getApiKeyLast4", "apps/sim/lib/api-key/byok-entitlement.ts#ORGANIZATION_BYOK_ENTITLEMENT_TTL_MS", - "apps/sim/lib/api-key/orchestration/index.ts#ApiKeyOrchestrationErrorCode", "apps/sim/lib/api-key/orchestration/index.ts#CreatedApiKey", "apps/sim/lib/api/contracts/access-requests.ts#ACCESS_REQUEST_MAX_PAGE_SIZE", "apps/sim/lib/api/contracts/access-requests.ts#AccessRequestDecision", From 75be4e30f3b2650e7def01953a7853e2f1cb56a6 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:05:38 -0800 Subject: [PATCH 2/8] fix(api-keys): default expiry to never, tolerate older list responses, share key principal builder - Create modal defaults Expires to Never; docs say so and note read-only keys keep search chat - Client key list defaults a missing access to write during deploy rollout - apiKeyPrincipal builds the key principal once for v1, hybrid, and workflow route auth - Auth result carries expired: true instead of callers matching the message text - Integration fixture uses valid table names; v2 create answers 201 - Serialized-principal test uses the wire shape; migration snapshot formatted --- .../docs/api-reference/authentication.mdx | 4 +- apps/docs/content/docs/mcp/authentication.mdx | 2 +- apps/sim/app/api/v1/auth.ts | 27 +- .../create-api-key-modal.tsx | 2 +- .../async-preprocessing-correlation.test.ts | 10 +- .../read-only-access.integration.ts | 15 +- apps/sim/lib/api-key/orchestration/index.ts | 5 +- apps/sim/lib/api-key/principal.ts | 29 + apps/sim/lib/api-key/service.ts | 4 +- apps/sim/lib/api/contracts/api-keys.ts | 3 +- apps/sim/lib/auth/hybrid.ts | 28 +- apps/sim/lib/workflows/api/route-policies.ts | 28 +- .../db/migrations/meta/0455_snapshot.json | 3444 ++++------------- packages/db/migrations/meta/_journal.json | 2 +- 14 files changed, 894 insertions(+), 2709 deletions(-) create mode 100644 apps/sim/lib/api-key/principal.ts diff --git a/apps/docs/content/docs/api-reference/authentication.mdx b/apps/docs/content/docs/api-reference/authentication.mdx index 6e8dc91c782..0a5d04db648 100644 --- a/apps/docs/content/docs/api-reference/authentication.mdx +++ b/apps/docs/content/docs/api-reference/authentication.mdx @@ -38,13 +38,13 @@ Delete a key from the same settings page to revoke it. Update applications that | Access | Allows | | --- | --- | | **Full access** | Everything the key's identity can do: reads, changes, deploys, and workflow runs | -| **Read only** | The operations the [`api:read` scope](#oauth-access-tokens) allows, including searches sent as POST requests | +| **Read only** | The operations the [`api:read` scope](#oauth-access-tokens) allows, including searches sent as POST requests and search chat, which `search:read` covers | A read-only key cannot run, resume, or cancel workflows, or create, change, or delete anything. Those requests fail with `403` and `error.details.code` `READ_ONLY_API_KEY`. Access narrows a key; it never grants more than the key's identity already has. Access is fixed at creation, so create a new key to change it. Keys created before access levels existed have full access. Keys created from the deploy modal or for a workflow MCP server always have full access, because they exist to run workflows. ### Expiration [#key-expiration] -A key expires 30 days, 90 days, or 1 year after creation, or never. The settings page defaults to 90 days. After it expires, every request with the key fails with `401` and the message `API key has expired`; create a replacement before then. The key list shows each key's expiration date. `GET /api/v2/meta` reports the calling key's `expiresAt` and `scopes`. +A key expires 30 days, 90 days, or 1 year after creation, or never. The settings page defaults to never. After it expires, every request with the key fails with `401` and the message `API key has expired`; create a replacement before then. The key list shows each key's expiration date. `GET /api/v2/meta` reports the calling key's `expiresAt` and `scopes`. ## Send an API key [#using-api-keys] diff --git a/apps/docs/content/docs/mcp/authentication.mdx b/apps/docs/content/docs/mcp/authentication.mdx index 28d7e22c01b..32af01718d3 100644 --- a/apps/docs/content/docs/mcp/authentication.mdx +++ b/apps/docs/content/docs/mcp/authentication.mdx @@ -58,7 +58,7 @@ The Cursor process must receive `SIM_API_KEY` for its environment interpolation For an agent that only reads, create a **Read only** key: it reaches the operations `api:read` allows, and a write tool call fails with `READ_ONLY_API_KEY`. See [key access](/api-reference/authentication#key-access). - Keys created in Sim settings expire after 90 days unless you choose otherwise. Revoke a key when it is no longer needed. Prefer OAuth for an app that + Keys created in Sim settings never expire unless you choose an expiration. Revoke a key when it is no longer needed. Prefer OAuth for an app that supports browser sign-in, and store keys in your app's secret or environment settings rather than in a shared config file. diff --git a/apps/sim/app/api/v1/auth.ts b/apps/sim/app/api/v1/auth.ts index d9d072d2109..f7ab808ded2 100644 --- a/apps/sim/app/api/v1/auth.ts +++ b/apps/sim/app/api/v1/auth.ts @@ -5,6 +5,7 @@ import { } from '@sim/auth/principal' import { createLogger } from '@sim/logger' import type { NextRequest } from 'next/server' +import { apiKeyPrincipal } from '@/lib/api-key/principal' import { authenticateApiKeyFromHeader, updateApiKeyLastUsed } from '@/lib/api-key/service' import { isAuthDisabled } from '@/lib/core/config/env-flags' @@ -54,30 +55,8 @@ export async function authenticateV1Request(request: NextRequest): Promise { it.each([ { name: 'workspace API key', - serializedPrincipal: { - version: 1 as const, - principal: createWorkspaceApiKeyPrincipal({ keyId: 'workspace-key-1' }), - }, + serializedPrincipal: serializePrincipal( + createWorkspaceApiKeyPrincipal({ keyId: 'workspace-key-1' }) + ), isPublicApiAccess: false, }, { @@ -262,7 +262,7 @@ describe('async preprocessing correlation threading', () => { const executionMetadata = mockExecutionSnapshot.mock.calls[0]?.[0] expect(executionMetadata.userId).toBe('actor-1') - expect(executionMetadata.principal).toEqual(serializedPrincipal.principal) + expect(executionMetadata.principal).toEqual(parsePrincipal(serializedPrincipal)) expect(executionMetadata.isPublicApiAccess).toBe(isPublicApiAccess) expect(executionMetadata.principal).not.toHaveProperty('userId') } diff --git a/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts b/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts index a304c07f201..beca21b0d74 100644 --- a/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts +++ b/apps/sim/lib/api-key/__integration__/read-only-access.integration.ts @@ -86,10 +86,11 @@ async function call(handler: unknown, path: string, options: CallOptions = {}) { return { status: response.status, body } } -function tableBody(name: string) { +/** Table names must match `NAME_PATTERN`, so the generated id's hyphens become underscores. */ +function tableBody(label: string) { return { workspaceId, - name, + name: `${label}_${generateId().replaceAll('-', '_')}`, schema: { columns: [{ name: 'title', type: 'string' }] }, } } @@ -276,7 +277,7 @@ describe('read-only and expiring API keys in PostgreSQL', () => { for (const key of [readPersonalKey, readWorkspaceKey]) { const v2 = await call(v2CreateTable, '/api/v2/tables', { key, - body: tableBody(`v2 ${generateId()}`), + body: tableBody('v2'), }) expect(v2.status).toBe(403) expect(v2.body).toMatchObject({ @@ -288,7 +289,7 @@ describe('read-only and expiring API keys in PostgreSQL', () => { headers: MCP_HEADERS, body: mcpToolCall('call_write_operation', { operation: 'createTable', - body: tableBody(`mcp ${generateId()}`), + body: tableBody('mcp'), }), }) expect(mcpWrite.status).toBe(403) @@ -296,7 +297,7 @@ describe('read-only and expiring API keys in PostgreSQL', () => { const v1 = await call(v1CreateTable, '/api/v1/tables', { key, - body: tableBody(`v1 ${generateId()}`), + body: tableBody('v1'), }) expect(v1.status).toBe(403) expect(v1.body).toEqual({ @@ -370,9 +371,9 @@ describe('read-only and expiring API keys in PostgreSQL', () => { const tablesBefore = await tableCount() const created = await call(v2CreateTable, '/api/v2/tables', { key: legacyKey, - body: tableBody(`legacy ${generateId()}`), + body: tableBody('legacy'), }) - expect(created.status).toBe(200) + expect(created.status, JSON.stringify(created.body)).toBe(201) expect(await tableCount()).toBe(tablesBefore + 1) }) diff --git a/apps/sim/lib/api-key/orchestration/index.ts b/apps/sim/lib/api-key/orchestration/index.ts index 5cd9233b9ce..9e060bbb25f 100644 --- a/apps/sim/lib/api-key/orchestration/index.ts +++ b/apps/sim/lib/api-key/orchestration/index.ts @@ -30,9 +30,8 @@ export function apiKeyCreationErrorStatus(code: ApiKeyOrchestrationErrorCode | u return 500 } +/** Also the shortest lifetime a key may be created with. */ const DAY_MS = 24 * 60 * 60 * 1000 -/** The shortest lifetime a key may be created with. */ -const MIN_API_KEY_LIFETIME_MS = DAY_MS /** The longest lifetime a key may be created with: a year, with a day of slack for time zones. */ const MAX_API_KEY_LIFETIME_MS = 366 * DAY_MS @@ -55,7 +54,7 @@ function resolveApiKeyExpiry(expiresAt: string | null | undefined): ResolvedExpi if (!Number.isFinite(lifetimeMs)) { return { ok: false, error: 'Expiration must be a valid date' } } - if (lifetimeMs < MIN_API_KEY_LIFETIME_MS) { + if (lifetimeMs < DAY_MS) { return { ok: false, error: 'Expiration must be at least one day from now' } } if (lifetimeMs > MAX_API_KEY_LIFETIME_MS) { diff --git a/apps/sim/lib/api-key/principal.ts b/apps/sim/lib/api-key/principal.ts new file mode 100644 index 00000000000..3964c75816a --- /dev/null +++ b/apps/sim/lib/api-key/principal.ts @@ -0,0 +1,29 @@ +import type { PersonalApiKeyPrincipal, WorkspaceApiKeyPrincipal } from '@sim/auth/principal' +import type { ApiKeyAuthResult } from '@/lib/api-key/service' + +/** The principal a successful `authenticateApiKeyFromHeader` result identifies. */ +export function apiKeyPrincipal( + result: ApiKeyAuthResult +): PersonalApiKeyPrincipal | WorkspaceApiKeyPrincipal { + if (!result.success || !result.keyId || !result.keyType || !result.access) { + throw new Error('API key authentication returned incomplete identity') + } + if (result.keyType === 'personal') { + if (!result.userId) throw new Error('Personal API key authentication returned no owner') + return { + kind: 'personal_api_key', + userId: result.userId, + keyId: result.keyId, + access: result.access, + } + } + if (!result.workspaceId) { + throw new Error('Workspace API key authentication returned no workspace scope') + } + return { + kind: 'workspace_api_key', + workspaceId: result.workspaceId, + keyId: result.keyId, + access: result.access, + } +} diff --git a/apps/sim/lib/api-key/service.ts b/apps/sim/lib/api-key/service.ts index 5b09f5dfb07..7d9a43ad7ab 100644 --- a/apps/sim/lib/api-key/service.ts +++ b/apps/sim/lib/api-key/service.ts @@ -26,6 +26,8 @@ export interface ApiKeyAuthResult { access?: ApiKeyAccess workspaceId?: string error?: string + /** The key matched but is past its expiry, so callers can say so rather than "invalid". */ + expired?: true } const INVALID = { success: false, error: 'Invalid API key' } as const @@ -101,7 +103,7 @@ export async function authenticateApiKeyFromHeader( if (options.userId && record.userId !== options.userId) return INVALID if (options.keyTypes?.length && !options.keyTypes.includes(keyType)) return INVALID if (record.expiresAt && record.expiresAt < new Date()) { - return { success: false, error: API_KEY_EXPIRED } + return { success: false, error: API_KEY_EXPIRED, expired: true } } if ( diff --git a/apps/sim/lib/api/contracts/api-keys.ts b/apps/sim/lib/api/contracts/api-keys.ts index 21608de3e40..7cde5bfac87 100644 --- a/apps/sim/lib/api/contracts/api-keys.ts +++ b/apps/sim/lib/api/contracts/api-keys.ts @@ -7,7 +7,8 @@ export type ApiKeyAccessLevel = z.output const apiKeyMetadataSchema = z.object({ id: z.string(), name: z.string(), - access: apiKeyAccessSchema, + /** Defaulted so a new client tolerates an old server's response during rollout. */ + access: apiKeyAccessSchema.default('write'), lastUsed: z.string().nullable().optional(), createdAt: z.string(), expiresAt: z.string().nullable().optional(), diff --git a/apps/sim/lib/auth/hybrid.ts b/apps/sim/lib/auth/hybrid.ts index a450850395e..c7aaeab337c 100644 --- a/apps/sim/lib/auth/hybrid.ts +++ b/apps/sim/lib/auth/hybrid.ts @@ -3,6 +3,7 @@ import { createLogger } from '@sim/logger' import type { NextRequest } from 'next/server' import { API_KEY_HEADER, BEARER_PREFIX } from '@/lib/api/server/credential-headers' import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' +import { apiKeyPrincipal } from '@/lib/api-key/principal' import { authenticateApiKeyFromHeader, updateApiKeyLastUsed } from '@/lib/api-key/service' import { getSession } from '@/lib/auth' import { type InternalSandboxProfile, verifyInternalToken } from '@/lib/auth/internal' @@ -215,29 +216,8 @@ export async function checkHybridAuth( const apiKeyHeader = request.headers.get(API_KEY_HEADER) ?? '' const result = await authenticateApiKeyFromHeader(apiKeyHeader) if (result.success) { - if (!result.keyId || !result.keyType || !result.userId || !result.access) { - throw new Error('API key authentication returned incomplete identity') - } - let principal: WorkflowExecutionPrincipal - if (result.keyType === 'personal') { - principal = { - kind: 'personal_api_key', - userId: result.userId, - keyId: result.keyId, - access: result.access, - } - } else { - if (!result.workspaceId) { - throw new Error('Workspace API key authentication returned no workspace scope') - } - principal = { - kind: 'workspace_api_key', - workspaceId: result.workspaceId, - keyId: result.keyId, - access: result.access, - } - } - updateApiKeyLastUsed(result.keyId) + const principal = apiKeyPrincipal(result) + updateApiKeyLastUsed(principal.keyId) return { success: true, userId: result.userId, @@ -250,7 +230,7 @@ export async function checkHybridAuth( return { success: false, - error: result.error === API_KEY_EXPIRED ? API_KEY_EXPIRED : 'Invalid API key', + error: result.expired ? API_KEY_EXPIRED : 'Invalid API key', } } diff --git a/apps/sim/lib/workflows/api/route-policies.ts b/apps/sim/lib/workflows/api/route-policies.ts index a81334592b1..391c884ae71 100644 --- a/apps/sim/lib/workflows/api/route-policies.ts +++ b/apps/sim/lib/workflows/api/route-policies.ts @@ -19,6 +19,7 @@ import { v2OrchestrationErrorPolicy, } from '@/lib/api/server/routes' import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' +import { apiKeyPrincipal } from '@/lib/api-key/principal' import { authenticateApiKeyFromHeader, updateApiKeyLastUsed } from '@/lib/api-key/service' import { asOrchestrationError, statusForOrchestrationError } from '@/lib/core/orchestration/types' import { WorkflowRunAlreadyTerminalError } from '@/lib/execution/workflow-run-already-terminal-error' @@ -101,29 +102,12 @@ type WorkflowApiKeyPrincipal = PersonalApiKeyPrincipal | WorkspaceApiKeyPrincipa async function authenticateWorkflowApiKey(rawApiKey: string): Promise { const result = await authenticateApiKeyFromHeader(rawApiKey) - if (!result.success || !result.keyId || !result.keyType || !result.access) { - throw new InternalUnauthenticatedError( - result.error === API_KEY_EXPIRED ? API_KEY_EXPIRED : 'Unauthorized' - ) - } - updateApiKeyLastUsed(result.keyId) - - if (result.keyType === 'workspace') { - if (!result.workspaceId) throw new Error('Workspace API key is missing its workspace scope') - return { - kind: 'workspace_api_key', - workspaceId: result.workspaceId, - keyId: result.keyId, - access: result.access, - } - } - if (!result.userId) throw new Error('Personal API key is missing its credential owner') - return { - kind: 'personal_api_key', - userId: result.userId, - keyId: result.keyId, - access: result.access, + if (!result.success) { + throw new InternalUnauthenticatedError(result.expired ? API_KEY_EXPIRED : 'Unauthorized') } + const principal = apiKeyPrincipal(result) + updateApiKeyLastUsed(principal.keyId) + return principal } export const internalWorkflowSessionOrApiKeyAuth: InternalAuthPolicy< diff --git a/packages/db/migrations/meta/0455_snapshot.json b/packages/db/migrations/meta/0455_snapshot.json index 775efe4979b..5684c162ac6 100644 --- a/packages/db/migrations/meta/0455_snapshot.json +++ b/packages/db/migrations/meta/0455_snapshot.json @@ -154,12 +154,8 @@ "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -311,12 +307,8 @@ "name": "agent_memory_turn_memory_id_memory_id_fk", "tableFrom": "agent_memory_turn", "tableTo": "memory", - "columnsFrom": [ - "memory_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["memory_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -324,12 +316,8 @@ "name": "agent_memory_turn_workflow_id_workflow_id_fk", "tableFrom": "agent_memory_turn", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -492,12 +480,8 @@ "name": "api_key_user_id_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -505,12 +489,8 @@ "name": "api_key_workspace_id_workspace_id_fk", "tableFrom": "api_key", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -518,12 +498,8 @@ "name": "api_key_created_by_user_id_fk", "tableFrom": "api_key", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -533,9 +509,7 @@ "api_key_key_unique": { "name": "api_key_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -642,12 +616,8 @@ "name": "assistant_tool_permission_organization_id_organization_id_fk", "tableFrom": "assistant_tool_permission", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -655,12 +625,8 @@ "name": "assistant_tool_permission_user_id_user_id_fk", "tableFrom": "assistant_tool_permission", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -668,12 +634,8 @@ "name": "assistant_tool_permission_credential_id_credential_id_fk", "tableFrom": "assistant_tool_permission", "tableTo": "credential", - "columnsFrom": [ - "credential_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -681,11 +643,7 @@ "compositePrimaryKeys": { "assistant_tool_permission_organization_id_user_id_credential_id_pk": { "name": "assistant_tool_permission_organization_id_user_id_credential_id_pk", - "columns": [ - "organization_id", - "user_id", - "credential_id" - ] + "columns": ["organization_id", "user_id", "credential_id"] } }, "uniqueConstraints": {}, @@ -1157,12 +1115,8 @@ "name": "audit_log_workspace_id_workspace_id_fk", "tableFrom": "audit_log", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -1170,12 +1124,8 @@ "name": "audit_log_actor_id_user_id_fk", "tableFrom": "audit_log", "tableTo": "user", - "columnsFrom": [ - "actor_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1460,12 +1410,8 @@ "name": "aws_marketplace_license_organization_id_organization_id_fk", "tableFrom": "aws_marketplace_license", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -1473,12 +1419,8 @@ "name": "aws_marketplace_license_linked_by_user_id_user_id_fk", "tableFrom": "aws_marketplace_license", "tableTo": "user", - "columnsFrom": [ - "linked_by_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["linked_by_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1643,12 +1585,8 @@ "name": "background_work_status_workspace_id_workspace_id_fk", "tableFrom": "background_work_status", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1656,12 +1594,8 @@ "name": "background_work_status_workflow_id_workflow_id_fk", "tableFrom": "background_work_status", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1747,12 +1681,8 @@ "name": "changelog_change_release_id_changelog_release_id_fk", "tableFrom": "changelog_change", "tableTo": "changelog_release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1760,12 +1690,8 @@ "name": "changelog_change_workflow_id_workflow_id_fk", "tableFrom": "changelog_change", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -1773,12 +1699,8 @@ "name": "changelog_change_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "changelog_change", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -1786,12 +1708,8 @@ "name": "changelog_change_chat_id_copilot_chats_id_fk", "tableFrom": "changelog_change", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1977,12 +1895,8 @@ "name": "changelog_release_workspace_id_workspace_id_fk", "tableFrom": "changelog_release", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1990,12 +1904,8 @@ "name": "changelog_release_body_file_id_workspace_files_id_fk", "tableFrom": "changelog_release", "tableTo": "workspace_files", - "columnsFrom": [ - "body_file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["body_file_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -2003,12 +1913,8 @@ "name": "changelog_release_created_by_user_id_fk", "tableFrom": "changelog_release", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -2016,12 +1922,8 @@ "name": "changelog_release_updated_by_user_id_fk", "tableFrom": "changelog_release", "tableTo": "user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -2228,12 +2130,8 @@ "name": "chat_workflow_id_workflow_id_fk", "tableFrom": "chat", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2241,12 +2139,8 @@ "name": "chat_user_id_user_id_fk", "tableFrom": "chat", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2627,12 +2521,8 @@ "name": "copilot_async_tool_calls_run_id_copilot_runs_id_fk", "tableFrom": "copilot_async_tool_calls", "tableTo": "copilot_runs", - "columnsFrom": [ - "run_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["run_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2640,12 +2530,8 @@ "name": "copilot_async_tool_calls_checkpoint_id_copilot_run_checkpoints_id_fk", "tableFrom": "copilot_async_tool_calls", "tableTo": "copilot_run_checkpoints", - "columnsFrom": [ - "checkpoint_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["checkpoint_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3003,12 +2889,8 @@ "name": "copilot_chats_user_id_user_id_fk", "tableFrom": "copilot_chats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3016,12 +2898,8 @@ "name": "copilot_chats_workflow_id_workflow_id_fk", "tableFrom": "copilot_chats", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3029,12 +2907,8 @@ "name": "copilot_chats_workspace_id_workspace_id_fk", "tableFrom": "copilot_chats", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3042,12 +2916,8 @@ "name": "copilot_chats_organization_id_organization_id_fk", "tableFrom": "copilot_chats", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3223,12 +3093,8 @@ "name": "copilot_feedback_user_id_user_id_fk", "tableFrom": "copilot_feedback", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3236,12 +3102,8 @@ "name": "copilot_feedback_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_feedback", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3460,12 +3322,8 @@ "name": "copilot_messages_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_messages", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3512,12 +3370,8 @@ "name": "copilot_organization_request_stops_user_id_user_id_fk", "tableFrom": "copilot_organization_request_stops", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3525,12 +3379,8 @@ "name": "copilot_organization_request_stops_organization_id_organization_id_fk", "tableFrom": "copilot_organization_request_stops", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3538,11 +3388,7 @@ "compositePrimaryKeys": { "copilot_organization_request_stops_user_id_organization_id_stream_id_pk": { "name": "copilot_organization_request_stops_user_id_organization_id_stream_id_pk", - "columns": [ - "user_id", - "organization_id", - "stream_id" - ] + "columns": ["user_id", "organization_id", "stream_id"] } }, "uniqueConstraints": {}, @@ -3586,12 +3432,8 @@ "name": "copilot_request_stops_user_id_user_id_fk", "tableFrom": "copilot_request_stops", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3599,12 +3441,8 @@ "name": "copilot_request_stops_workspace_id_workspace_id_fk", "tableFrom": "copilot_request_stops", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3612,11 +3450,7 @@ "compositePrimaryKeys": { "copilot_request_stops_user_id_workspace_id_stream_id_pk": { "name": "copilot_request_stops_user_id_workspace_id_stream_id_pk", - "columns": [ - "user_id", - "workspace_id", - "stream_id" - ] + "columns": ["user_id", "workspace_id", "stream_id"] } }, "uniqueConstraints": {}, @@ -3726,12 +3560,8 @@ "name": "copilot_run_checkpoints_run_id_copilot_runs_id_fk", "tableFrom": "copilot_run_checkpoints", "tableTo": "copilot_runs", - "columnsFrom": [ - "run_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["run_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4081,12 +3911,8 @@ "name": "copilot_runs_chat_id_copilot_chats_id_fk", "tableFrom": "copilot_runs", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4094,12 +3920,8 @@ "name": "copilot_runs_user_id_user_id_fk", "tableFrom": "copilot_runs", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4107,12 +3929,8 @@ "name": "copilot_runs_workflow_id_workflow_id_fk", "tableFrom": "copilot_runs", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4120,12 +3938,8 @@ "name": "copilot_runs_workspace_id_workspace_id_fk", "tableFrom": "copilot_runs", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4133,12 +3947,8 @@ "name": "copilot_runs_organization_id_organization_id_fk", "tableFrom": "copilot_runs", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4146,12 +3956,8 @@ "name": "copilot_runs_desktop_device_id_desktop_devices_id_fk", "tableFrom": "copilot_runs", "tableTo": "desktop_devices", - "columnsFrom": [ - "desktop_device_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["desktop_device_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -4868,12 +4674,8 @@ "name": "credential_workspace_id_workspace_id_fk", "tableFrom": "credential", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4881,12 +4683,8 @@ "name": "credential_organization_id_organization_id_fk", "tableFrom": "credential", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4894,12 +4692,8 @@ "name": "credential_slack_app_id_slack_app_id_fk", "tableFrom": "credential", "tableTo": "slack_app", - "columnsFrom": [ - "slack_app_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["slack_app_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -4907,12 +4701,8 @@ "name": "credential_account_id_account_id_fk", "tableFrom": "credential", "tableTo": "account", - "columnsFrom": [ - "account_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["account_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4920,12 +4710,8 @@ "name": "credential_env_owner_user_id_user_id_fk", "tableFrom": "credential", "tableTo": "user", - "columnsFrom": [ - "env_owner_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["env_owner_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4933,12 +4719,8 @@ "name": "credential_credential_group_enrollment_id_credential_group_enrollment_id_fk", "tableFrom": "credential", "tableTo": "credential_group_enrollment", - "columnsFrom": [ - "credential_group_enrollment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_group_enrollment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4946,12 +4728,8 @@ "name": "credential_mcp_server_id_mcp_servers_id_fk", "tableFrom": "credential", "tableTo": "mcp_servers", - "columnsFrom": [ - "mcp_server_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["mcp_server_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4959,12 +4737,8 @@ "name": "credential_created_by_user_id_fk", "tableFrom": "credential", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5149,12 +4923,8 @@ "name": "credential_group_workspace_id_workspace_id_fk", "tableFrom": "credential_group", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5162,12 +4932,8 @@ "name": "credential_group_organization_id_organization_id_fk", "tableFrom": "credential_group", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5175,12 +4941,8 @@ "name": "credential_group_created_by_user_id_fk", "tableFrom": "credential_group", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5423,12 +5185,8 @@ "name": "credential_group_enrollment_credential_group_id_credential_group_id_fk", "tableFrom": "credential_group_enrollment", "tableTo": "credential_group", - "columnsFrom": [ - "credential_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5436,12 +5194,8 @@ "name": "credential_group_enrollment_user_id_user_id_fk", "tableFrom": "credential_group_enrollment", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5449,12 +5203,8 @@ "name": "credential_group_enrollment_created_by_user_id_fk", "tableFrom": "credential_group_enrollment", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5612,12 +5362,8 @@ "name": "credential_member_credential_id_credential_id_fk", "tableFrom": "credential_member", "tableTo": "credential", - "columnsFrom": [ - "credential_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5625,12 +5371,8 @@ "name": "credential_member_user_id_user_id_fk", "tableFrom": "credential_member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5638,12 +5380,8 @@ "name": "credential_member_invited_by_user_id_fk", "tableFrom": "credential_member", "tableTo": "user", - "columnsFrom": [ - "invited_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["invited_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5791,12 +5529,8 @@ "name": "custom_block_organization_id_organization_id_fk", "tableFrom": "custom_block", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5804,12 +5538,8 @@ "name": "custom_block_workflow_id_workflow_id_fk", "tableFrom": "custom_block", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5817,12 +5547,8 @@ "name": "custom_block_created_by_user_id_fk", "tableFrom": "custom_block", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -5916,12 +5642,8 @@ "name": "custom_tools_workspace_id_workspace_id_fk", "tableFrom": "custom_tools", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -5929,12 +5651,8 @@ "name": "custom_tools_user_id_user_id_fk", "tableFrom": "custom_tools", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -6023,12 +5741,8 @@ "name": "dashboard_workspace_id_workspace_id_fk", "tableFrom": "dashboard", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6036,12 +5750,8 @@ "name": "dashboard_created_by_user_id_fk", "tableFrom": "dashboard", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -6049,12 +5759,8 @@ "name": "dashboard_updated_by_user_id_fk", "tableFrom": "dashboard", "tableTo": "user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -6176,12 +5882,8 @@ "name": "data_drain_runs_drain_id_data_drains_id_fk", "tableFrom": "data_drain_runs", "tableTo": "data_drains", - "columnsFrom": [ - "drain_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["drain_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -6342,12 +6044,8 @@ "name": "data_drains_organization_id_organization_id_fk", "tableFrom": "data_drains", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6355,12 +6053,8 @@ "name": "data_drains_created_by_user_id_fk", "tableFrom": "data_drains", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -6530,12 +6224,8 @@ "name": "desktop_devices_user_id_user_id_fk", "tableFrom": "desktop_devices", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -6543,12 +6233,8 @@ "name": "desktop_devices_session_id_session_id_fk", "tableFrom": "desktop_devices", "tableTo": "session", - "columnsFrom": [ - "session_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["session_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -7738,12 +7424,8 @@ "name": "document_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "document", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -7751,12 +7433,8 @@ "name": "document_connector_id_knowledge_connector_id_fk", "tableFrom": "document", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -7764,12 +7442,8 @@ "name": "document_uploaded_by_user_id_fk", "tableFrom": "document", "tableTo": "user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -7828,12 +7502,8 @@ "name": "document_secret_provenance_document_id_document_id_fk", "tableFrom": "document_secret_provenance", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8495,12 +8165,8 @@ "name": "embedding_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "embedding", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -8508,12 +8174,8 @@ "name": "embedding_document_id_document_id_fk", "tableFrom": "embedding", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8800,12 +8462,8 @@ "name": "embedding_search_id_embedding_id_fk", "tableFrom": "embedding_search", "tableTo": "embedding", - "columnsFrom": [ - "id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8864,12 +8522,8 @@ "name": "embedding_secret_provenance_embedding_id_embedding_id_fk", "tableFrom": "embedding_secret_provenance", "tableTo": "embedding", - "columnsFrom": [ - "embedding_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["embedding_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8921,12 +8575,8 @@ "name": "environment_user_id_user_id_fk", "tableFrom": "environment", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -8936,9 +8586,7 @@ "environment_user_id_unique": { "name": "environment_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -9024,12 +8672,8 @@ "name": "execution_large_value_dependencies_workspace_id_workspace_id_fk", "tableFrom": "execution_large_value_dependencies", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -9037,10 +8681,7 @@ "compositePrimaryKeys": { "execution_large_value_dependencies_parent_key_child_key_pk": { "name": "execution_large_value_dependencies_parent_key_child_key_pk", - "columns": [ - "parent_key", - "child_key" - ] + "columns": ["parent_key", "child_key"] } }, "uniqueConstraints": {}, @@ -9140,12 +8781,8 @@ "name": "execution_large_value_references_workspace_id_workspace_id_fk", "tableFrom": "execution_large_value_references", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -9153,12 +8790,8 @@ "name": "execution_large_value_references_workflow_id_workflow_id_fk", "tableFrom": "execution_large_value_references", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -9166,11 +8799,7 @@ "compositePrimaryKeys": { "execution_large_value_references_key_execution_id_source_pk": { "name": "execution_large_value_references_key_execution_id_source_pk", - "columns": [ - "key", - "execution_id", - "source" - ] + "columns": ["key", "execution_id", "source"] } }, "uniqueConstraints": {}, @@ -9334,12 +8963,8 @@ "name": "execution_large_values_workspace_id_workspace_id_fk", "tableFrom": "execution_large_values", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -9347,12 +8972,8 @@ "name": "execution_large_values_workflow_id_workflow_id_fk", "tableFrom": "execution_large_values", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -9459,12 +9080,8 @@ "name": "file_search_dependency_build_id_workspace_file_search_build_id_fk", "tableFrom": "file_search_dependency", "tableTo": "workspace_file_search_build", - "columnsFrom": [ - "build_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["build_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -9472,10 +9089,7 @@ "compositePrimaryKeys": { "file_search_dependency_build_id_file_id_pk": { "name": "file_search_dependency_build_id_file_id_pk", - "columns": [ - "build_id", - "file_id" - ] + "columns": ["build_id", "file_id"] } }, "uniqueConstraints": {}, @@ -9559,10 +9173,7 @@ "compositePrimaryKeys": { "file_search_dispatch_queue_entity_type_entity_id_pk": { "name": "file_search_dispatch_queue_entity_type_entity_id_pk", - "columns": [ - "entity_type", - "entity_id" - ] + "columns": ["entity_type", "entity_id"] } }, "uniqueConstraints": {}, @@ -9853,12 +9464,8 @@ "name": "folder_project_id_project_id_fk", "tableFrom": "folder", "tableTo": "project", - "columnsFrom": [ - "project_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["project_id"], + "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }, @@ -9866,12 +9473,8 @@ "name": "folder_user_id_user_id_fk", "tableFrom": "folder", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -9879,12 +9482,8 @@ "name": "folder_workspace_id_workspace_id_fk", "tableFrom": "folder", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -9892,12 +9491,8 @@ "name": "folder_parent_id_folder_id_fk", "tableFrom": "folder", "tableTo": "folder", - "columnsFrom": [ - "parent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -9905,16 +9500,8 @@ "name": "folder_workspace_parent_owner_fk", "tableFrom": "folder", "tableTo": "folder", - "columnsFrom": [ - "parent_id", - "workspace_id", - "resource_type" - ], - "columnsTo": [ - "id", - "workspace_id", - "resource_type" - ], + "columnsFrom": ["parent_id", "workspace_id", "resource_type"], + "columnsTo": ["id", "workspace_id", "resource_type"], "onDelete": "no action", "onUpdate": "no action" }, @@ -9922,16 +9509,8 @@ "name": "folder_project_parent_owner_fk", "tableFrom": "folder", "tableTo": "folder", - "columnsFrom": [ - "parent_id", - "project_id", - "resource_type" - ], - "columnsTo": [ - "id", - "project_id", - "resource_type" - ], + "columnsFrom": ["parent_id", "project_id", "resource_type"], + "columnsTo": ["id", "project_id", "resource_type"], "onDelete": "no action", "onUpdate": "no action" } @@ -9941,20 +9520,12 @@ "folder_workspace_owner_type_unique": { "name": "folder_workspace_owner_type_unique", "nullsNotDistinct": false, - "columns": [ - "id", - "workspace_id", - "resource_type" - ] + "columns": ["id", "workspace_id", "resource_type"] }, "folder_project_owner_type_unique": { "name": "folder_project_owner_type_unique", "nullsNotDistinct": false, - "columns": [ - "id", - "project_id", - "resource_type" - ] + "columns": ["id", "project_id", "resource_type"] } }, "policies": {}, @@ -10173,12 +9744,8 @@ "name": "invitation_inviter_id_user_id_fk", "tableFrom": "invitation", "tableTo": "user", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -10186,12 +9753,8 @@ "name": "invitation_organization_id_organization_id_fk", "tableFrom": "invitation", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -10201,9 +9764,7 @@ "invitation_token_unique": { "name": "invitation_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -10297,12 +9858,8 @@ "name": "invitation_workspace_grant_invitation_id_invitation_id_fk", "tableFrom": "invitation_workspace_grant", "tableTo": "invitation", - "columnsFrom": [ - "invitation_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["invitation_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -10310,12 +9867,8 @@ "name": "invitation_workspace_grant_workspace_id_workspace_id_fk", "tableFrom": "invitation_workspace_grant", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -10574,12 +10127,8 @@ "name": "job_execution_logs_schedule_id_workflow_schedule_id_fk", "tableFrom": "job_execution_logs", "tableTo": "workflow_schedule", - "columnsFrom": [ - "schedule_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["schedule_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -10587,12 +10136,8 @@ "name": "job_execution_logs_workspace_id_workspace_id_fk", "tableFrom": "job_execution_logs", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -10891,12 +10436,8 @@ "name": "knowledge_base_user_id_user_id_fk", "tableFrom": "knowledge_base", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -10904,12 +10445,8 @@ "name": "knowledge_base_workspace_id_workspace_id_fk", "tableFrom": "knowledge_base", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -10917,12 +10454,8 @@ "name": "knowledge_base_organization_id_organization_id_fk", "tableFrom": "knowledge_base", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -10930,12 +10463,8 @@ "name": "knowledge_base_folder_id_folder_id_fk", "tableFrom": "knowledge_base", "tableTo": "folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -11111,12 +10640,8 @@ "name": "knowledge_base_import_workspace_id_workspace_id_fk", "tableFrom": "knowledge_base_import", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -11124,12 +10649,8 @@ "name": "knowledge_base_import_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_base_import", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -11239,12 +10760,8 @@ "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_base_tag_definitions", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -11626,12 +11143,8 @@ "name": "knowledge_connector_knowledge_base_id_knowledge_base_id_fk", "tableFrom": "knowledge_connector", "tableTo": "knowledge_base", - "columnsFrom": [ - "knowledge_base_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -11639,12 +11152,8 @@ "name": "knowledge_connector_credential_group_id_credential_group_id_fk", "tableFrom": "knowledge_connector", "tableTo": "credential_group", - "columnsFrom": [ - "credential_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_group_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -11894,12 +11403,8 @@ "name": "knowledge_connector_member_workspace_id_workspace_id_fk", "tableFrom": "knowledge_connector_member", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -11907,12 +11412,8 @@ "name": "knowledge_connector_member_organization_id_organization_id_fk", "tableFrom": "knowledge_connector_member", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -11920,12 +11421,8 @@ "name": "knowledge_connector_member_connector_id_knowledge_connector_id_fk", "tableFrom": "knowledge_connector_member", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -11933,12 +11430,8 @@ "name": "knowledge_connector_member_credential_id_credential_id_fk", "tableFrom": "knowledge_connector_member", "tableTo": "credential", - "columnsFrom": [ - "credential_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12178,12 +11671,8 @@ "name": "knowledge_connector_member_sync_log_connector_id_knowledge_connector_id_fk", "tableFrom": "knowledge_connector_member_sync_log", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12387,12 +11876,8 @@ "name": "knowledge_connector_partition_connector_id_knowledge_connector_id_fk", "tableFrom": "knowledge_connector_partition", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12400,10 +11885,7 @@ "compositePrimaryKeys": { "kcp_pk": { "name": "kcp_pk", - "columns": [ - "connector_id", - "partition_key" - ] + "columns": ["connector_id", "partition_key"] } }, "uniqueConstraints": {}, @@ -12489,12 +11971,8 @@ "name": "kcpg_snapshot_fk", "tableFrom": "knowledge_connector_permission_grant", "tableTo": "knowledge_connector_permission_snapshot", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "connector_id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["connector_id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12502,11 +11980,7 @@ "compositePrimaryKeys": { "kcpg_pk": { "name": "kcpg_pk", - "columns": [ - "connector_id", - "group_key", - "subject_token" - ] + "columns": ["connector_id", "group_key", "subject_token"] } }, "uniqueConstraints": {}, @@ -12558,12 +12032,8 @@ "name": "kcps_connector_fk", "tableFrom": "knowledge_connector_permission_snapshot", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12735,12 +12205,8 @@ "name": "knowledge_connector_sync_log_connector_id_knowledge_connector_id_fk", "tableFrom": "knowledge_connector_sync_log", "tableTo": "knowledge_connector", - "columnsFrom": [ - "connector_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connector_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12808,12 +12274,8 @@ "name": "knowledge_document_observation_document_id_document_id_fk", "tableFrom": "knowledge_document_observation", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -12821,12 +12283,8 @@ "name": "knowledge_document_observation_member_id_knowledge_connector_member_id_fk", "tableFrom": "knowledge_document_observation", "tableTo": "knowledge_connector_member", - "columnsFrom": [ - "member_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["member_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -12834,10 +12292,7 @@ "compositePrimaryKeys": { "knowledge_document_observation_document_id_member_id_pk": { "name": "knowledge_document_observation_document_id_member_id_pk", - "columns": [ - "document_id", - "member_id" - ] + "columns": ["document_id", "member_id"] } }, "uniqueConstraints": {}, @@ -12959,12 +12414,8 @@ "name": "knowledge_external_directory_workspace_id_workspace_id_fk", "tableFrom": "knowledge_external_directory", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -12972,12 +12423,8 @@ "name": "knowledge_external_directory_organization_id_organization_id_fk", "tableFrom": "knowledge_external_directory", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -13169,12 +12616,8 @@ "name": "knowledge_external_group_organization_id_organization_id_fk", "tableFrom": "knowledge_external_group", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13182,12 +12625,8 @@ "name": "keg_workspace_fk", "tableFrom": "knowledge_external_group", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -13249,12 +12688,8 @@ "name": "kegm_group_fk", "tableFrom": "knowledge_external_group_member", "tableTo": "knowledge_external_group", - "columnsFrom": [ - "group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -13262,10 +12697,7 @@ "compositePrimaryKeys": { "knowledge_external_group_member_group_id_subject_token_pk": { "name": "knowledge_external_group_member_group_id_subject_token_pk", - "columns": [ - "group_id", - "subject_token" - ] + "columns": ["group_id", "subject_token"] } }, "uniqueConstraints": {}, @@ -13327,12 +12759,8 @@ "name": "knowledge_projection_dirty_document_id_document_id_fk", "tableFrom": "knowledge_projection_dirty", "tableTo": "document", - "columnsFrom": [ - "document_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["document_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -13465,12 +12893,8 @@ "name": "mcp_server_oauth_mcp_server_id_mcp_servers_id_fk", "tableFrom": "mcp_server_oauth", "tableTo": "mcp_servers", - "columnsFrom": [ - "mcp_server_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["mcp_server_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13478,12 +12902,8 @@ "name": "mcp_server_oauth_user_id_user_id_fk", "tableFrom": "mcp_server_oauth", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -13491,12 +12911,8 @@ "name": "mcp_server_oauth_workspace_id_workspace_id_fk", "tableFrom": "mcp_server_oauth", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13504,12 +12920,8 @@ "name": "mcp_server_oauth_organization_id_organization_id_fk", "tableFrom": "mcp_server_oauth", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -13818,12 +13230,8 @@ "name": "mcp_servers_workspace_id_workspace_id_fk", "tableFrom": "mcp_servers", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13831,12 +13239,8 @@ "name": "mcp_servers_organization_id_organization_id_fk", "tableFrom": "mcp_servers", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13844,12 +13248,8 @@ "name": "mcp_servers_credential_group_id_credential_group_id_fk", "tableFrom": "mcp_servers", "tableTo": "credential_group", - "columnsFrom": [ - "credential_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_group_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -13857,12 +13257,8 @@ "name": "mcp_servers_created_by_user_id_fk", "tableFrom": "mcp_servers", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -13963,12 +13359,8 @@ "name": "member_user_id_user_id_fk", "tableFrom": "member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -13976,12 +13368,8 @@ "name": "member_organization_id_organization_id_fk", "tableFrom": "member", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14083,12 +13471,8 @@ "name": "member_profile_member_id_member_id_fk", "tableFrom": "member_profile", "tableTo": "member", - "columnsFrom": [ - "member_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["member_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -14096,12 +13480,8 @@ "name": "member_profile_manager_member_id_member_id_fk", "tableFrom": "member_profile", "tableTo": "member", - "columnsFrom": [ - "manager_member_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["manager_member_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -14109,12 +13489,8 @@ "name": "member_profile_updated_by_user_id_fk", "tableFrom": "member_profile", "tableTo": "user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -14263,12 +13639,8 @@ "name": "memory_workspace_id_workspace_id_fk", "tableFrom": "memory", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14318,12 +13690,8 @@ "name": "memory_artifact_memory_id_memory_id_fk", "tableFrom": "memory_artifact", "tableTo": "memory", - "columnsFrom": [ - "memory_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["memory_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -14331,12 +13699,8 @@ "name": "memory_artifact_key_execution_large_values_key_fk", "tableFrom": "memory_artifact", "tableTo": "execution_large_values", - "columnsFrom": [ - "key" - ], - "columnsTo": [ - "key" - ], + "columnsFrom": ["key"], + "columnsTo": ["key"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14344,10 +13708,7 @@ "compositePrimaryKeys": { "memory_artifact_memory_id_key_pk": { "name": "memory_artifact_memory_id_key_pk", - "columns": [ - "memory_id", - "key" - ] + "columns": ["memory_id", "key"] } }, "uniqueConstraints": {}, @@ -14488,12 +13849,8 @@ "name": "memory_item_memory_id_memory_id_fk", "tableFrom": "memory_item", "tableTo": "memory", - "columnsFrom": [ - "memory_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["memory_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14556,12 +13913,8 @@ "name": "memory_secret_provenance_memory_id_memory_id_fk", "tableFrom": "memory_secret_provenance", "tableTo": "memory", - "columnsFrom": [ - "memory_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["memory_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14692,12 +14045,8 @@ "name": "mothership_benchmark_runs_benchmark_id_mothership_benchmarks_id_fk", "tableFrom": "mothership_benchmark_runs", "tableTo": "mothership_benchmarks", - "columnsFrom": [ - "benchmark_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["benchmark_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -14874,12 +14223,8 @@ "name": "mothership_benchmarks_organization_id_organization_id_fk", "tableFrom": "mothership_benchmarks", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -14887,12 +14232,8 @@ "name": "mothership_benchmarks_user_id_user_id_fk", "tableFrom": "mothership_benchmarks", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -14900,12 +14241,8 @@ "name": "mothership_benchmarks_run_as_user_id_user_id_fk", "tableFrom": "mothership_benchmarks", "tableTo": "user", - "columnsFrom": [ - "run_as_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["run_as_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -14913,12 +14250,8 @@ "name": "mothership_benchmarks_source_workspace_id_workspace_id_fk", "tableFrom": "mothership_benchmarks", "tableTo": "workspace", - "columnsFrom": [ - "source_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15008,12 +14341,8 @@ "name": "mothership_inbox_allowed_sender_workspace_id_workspace_id_fk", "tableFrom": "mothership_inbox_allowed_sender", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15021,12 +14350,8 @@ "name": "mothership_inbox_allowed_sender_added_by_user_id_fk", "tableFrom": "mothership_inbox_allowed_sender", "tableTo": "user", - "columnsFrom": [ - "added_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["added_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15262,12 +14587,8 @@ "name": "mothership_inbox_task_workspace_id_workspace_id_fk", "tableFrom": "mothership_inbox_task", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15275,12 +14596,8 @@ "name": "mothership_inbox_task_chat_id_copilot_chats_id_fk", "tableFrom": "mothership_inbox_task", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -15333,12 +14650,8 @@ "name": "mothership_inbox_webhook_workspace_id_workspace_id_fk", "tableFrom": "mothership_inbox_webhook", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15348,9 +14661,7 @@ "mothership_inbox_webhook_workspace_id_unique": { "name": "mothership_inbox_webhook_workspace_id_unique", "nullsNotDistinct": false, - "columns": [ - "workspace_id" - ] + "columns": ["workspace_id"] } }, "policies": {}, @@ -15386,12 +14697,8 @@ "name": "mothership_memory_selections_user_id_user_id_fk", "tableFrom": "mothership_memory_selections", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15399,12 +14706,8 @@ "name": "mothership_memory_selections_organization_id_organization_id_fk", "tableFrom": "mothership_memory_selections", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15412,12 +14715,8 @@ "name": "mothership_memory_selections_space_id_mothership_memory_spaces_id_fk", "tableFrom": "mothership_memory_selections", "tableTo": "mothership_memory_spaces", - "columnsFrom": [ - "space_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["space_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -15425,10 +14724,7 @@ "compositePrimaryKeys": { "mothership_memory_selections_user_id_organization_id_pk": { "name": "mothership_memory_selections_user_id_organization_id_pk", - "columns": [ - "user_id", - "organization_id" - ] + "columns": ["user_id", "organization_id"] } }, "uniqueConstraints": {}, @@ -15500,12 +14796,8 @@ "name": "mothership_memory_spaces_user_id_user_id_fk", "tableFrom": "mothership_memory_spaces", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15513,12 +14805,8 @@ "name": "mothership_memory_spaces_organization_id_organization_id_fk", "tableFrom": "mothership_memory_spaces", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15559,12 +14847,8 @@ "name": "mothership_resource_effects_chat_id_copilot_chats_id_fk", "tableFrom": "mothership_resource_effects", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15572,10 +14856,7 @@ "compositePrimaryKeys": { "mothership_resource_effects_chat_id_effect_id_pk": { "name": "mothership_resource_effects_chat_id_effect_id_pk", - "columns": [ - "chat_id", - "effect_id" - ] + "columns": ["chat_id", "effect_id"] } }, "uniqueConstraints": {}, @@ -15742,12 +15023,8 @@ "name": "oauth_access_token_client_id_oauth_client_client_id_fk", "tableFrom": "oauth_access_token", "tableTo": "oauth_client", - "columnsFrom": [ - "client_id" - ], - "columnsTo": [ - "client_id" - ], + "columnsFrom": ["client_id"], + "columnsTo": ["client_id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15755,12 +15032,8 @@ "name": "oauth_access_token_session_id_session_id_fk", "tableFrom": "oauth_access_token", "tableTo": "session", - "columnsFrom": [ - "session_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["session_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -15768,12 +15041,8 @@ "name": "oauth_access_token_user_id_user_id_fk", "tableFrom": "oauth_access_token", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -15781,12 +15050,8 @@ "name": "oauth_access_token_refresh_id_oauth_refresh_token_id_fk", "tableFrom": "oauth_access_token", "tableTo": "oauth_refresh_token", - "columnsFrom": [ - "refresh_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["refresh_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -15796,9 +15061,7 @@ "oauth_access_token_token_unique": { "name": "oauth_access_token_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -16018,12 +15281,8 @@ "name": "oauth_client_user_id_user_id_fk", "tableFrom": "oauth_client", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -16033,9 +15292,7 @@ "oauth_client_client_id_unique": { "name": "oauth_client_client_id_unique", "nullsNotDistinct": false, - "columns": [ - "client_id" - ] + "columns": ["client_id"] } }, "policies": {}, @@ -16111,12 +15368,8 @@ "name": "oauth_consent_client_id_oauth_client_client_id_fk", "tableFrom": "oauth_consent", "tableTo": "oauth_client", - "columnsFrom": [ - "client_id" - ], - "columnsTo": [ - "client_id" - ], + "columnsFrom": ["client_id"], + "columnsTo": ["client_id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16124,12 +15377,8 @@ "name": "oauth_consent_user_id_user_id_fk", "tableFrom": "oauth_consent", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -16139,11 +15388,7 @@ "oauth_consent_user_client_reference_unique": { "name": "oauth_consent_user_client_reference_unique", "nullsNotDistinct": true, - "columns": [ - "user_id", - "client_id", - "reference_id" - ] + "columns": ["user_id", "client_id", "reference_id"] } }, "policies": {}, @@ -16312,12 +15557,8 @@ "name": "oauth_refresh_token_client_id_oauth_client_client_id_fk", "tableFrom": "oauth_refresh_token", "tableTo": "oauth_client", - "columnsFrom": [ - "client_id" - ], - "columnsTo": [ - "client_id" - ], + "columnsFrom": ["client_id"], + "columnsTo": ["client_id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16325,12 +15566,8 @@ "name": "oauth_refresh_token_session_id_session_id_fk", "tableFrom": "oauth_refresh_token", "tableTo": "session", - "columnsFrom": [ - "session_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["session_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -16338,12 +15575,8 @@ "name": "oauth_refresh_token_user_id_user_id_fk", "tableFrom": "oauth_refresh_token", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16351,12 +15584,8 @@ "name": "oauth_refresh_token_family_id_oauth_token_family_id_fk", "tableFrom": "oauth_refresh_token", "tableTo": "oauth_token_family", - "columnsFrom": [ - "family_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["family_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -16366,17 +15595,12 @@ "oauth_refresh_token_token_unique": { "name": "oauth_refresh_token_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] }, "oauth_refresh_token_family_generation_unique": { "name": "oauth_refresh_token_family_generation_unique", "nullsNotDistinct": false, - "columns": [ - "family_id", - "generation" - ] + "columns": ["family_id", "generation"] } }, "policies": {}, @@ -16540,12 +15764,8 @@ "name": "oauth_token_family_client_id_oauth_client_client_id_fk", "tableFrom": "oauth_token_family", "tableTo": "oauth_client", - "columnsFrom": [ - "client_id" - ], - "columnsTo": [ - "client_id" - ], + "columnsFrom": ["client_id"], + "columnsTo": ["client_id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16553,12 +15773,8 @@ "name": "oauth_token_family_session_id_session_id_fk", "tableFrom": "oauth_token_family", "tableTo": "session", - "columnsFrom": [ - "session_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["session_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -16566,12 +15782,8 @@ "name": "oauth_token_family_user_id_user_id_fk", "tableFrom": "oauth_token_family", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16579,12 +15791,8 @@ "name": "oauth_token_family_consent_id_oauth_consent_id_fk", "tableFrom": "oauth_token_family", "tableTo": "oauth_consent", - "columnsFrom": [ - "consent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["consent_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -16753,12 +15961,8 @@ "name": "organization_access_request_settings_organization_id_organization_id_fk", "tableFrom": "organization_access_request_settings", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16766,12 +15970,8 @@ "name": "organization_access_request_settings_updated_by_user_id_fk", "tableFrom": "organization_access_request_settings", "tableTo": "user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -16865,12 +16065,8 @@ "name": "organization_byok_keys_organization_id_organization_id_fk", "tableFrom": "organization_byok_keys", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16878,12 +16074,8 @@ "name": "organization_byok_keys_created_by_user_id_fk", "tableFrom": "organization_byok_keys", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -16986,12 +16178,8 @@ "name": "organization_member_usage_limit_organization_id_organization_id_fk", "tableFrom": "organization_member_usage_limit", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -16999,12 +16187,8 @@ "name": "organization_member_usage_limit_user_id_user_id_fk", "tableFrom": "organization_member_usage_limit", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -17012,12 +16196,8 @@ "name": "organization_member_usage_limit_set_by_user_id_fk", "tableFrom": "organization_member_usage_limit", "tableTo": "user", - "columnsFrom": [ - "set_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["set_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -17081,12 +16261,8 @@ "name": "organization_search_history_organization_id_organization_id_fk", "tableFrom": "organization_search_history", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -17094,12 +16270,8 @@ "name": "organization_search_history_user_id_user_id_fk", "tableFrom": "organization_search_history", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -17107,10 +16279,7 @@ "compositePrimaryKeys": { "organization_search_history_organization_id_user_id_pk": { "name": "organization_search_history_organization_id_user_id_pk", - "columns": [ - "organization_id", - "user_id" - ] + "columns": ["organization_id", "user_id"] } }, "uniqueConstraints": {}, @@ -17154,12 +16323,8 @@ "name": "organization_search_integration_organization_id_organization_id_fk", "tableFrom": "organization_search_integration", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -17167,10 +16332,7 @@ "compositePrimaryKeys": { "organization_search_integration_organization_id_connector_type_pk": { "name": "organization_search_integration_organization_id_connector_type_pk", - "columns": [ - "organization_id", - "connector_type" - ] + "columns": ["organization_id", "connector_type"] } }, "uniqueConstraints": {}, @@ -17287,12 +16449,8 @@ "name": "org_search_mcp_invocation_org_fk", "tableFrom": "organization_search_mcp_invocation", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -17300,12 +16458,8 @@ "name": "org_search_mcp_invocation_user_fk", "tableFrom": "organization_search_mcp_invocation", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -17451,12 +16605,8 @@ "name": "organization_secret_source_id_organization_secret_source_id_fk", "tableFrom": "organization_secret", "tableTo": "organization_secret_source", - "columnsFrom": [ - "source_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -17464,12 +16614,8 @@ "name": "organization_secret_owner_user_id_user_id_fk", "tableFrom": "organization_secret", "tableTo": "user", - "columnsFrom": [ - "owner_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["owner_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -17539,12 +16685,8 @@ "name": "organization_secret_source_organization_id_organization_id_fk", "tableFrom": "organization_secret_source", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -17899,12 +17041,8 @@ "name": "paused_executions_workflow_id_workflow_id_fk", "tableFrom": "paused_executions", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18063,12 +17201,8 @@ "name": "pending_credential_draft_user_id_user_id_fk", "tableFrom": "pending_credential_draft", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18076,12 +17210,8 @@ "name": "pending_credential_draft_workspace_id_workspace_id_fk", "tableFrom": "pending_credential_draft", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18089,12 +17219,8 @@ "name": "pending_credential_draft_organization_id_organization_id_fk", "tableFrom": "pending_credential_draft", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18102,12 +17228,8 @@ "name": "pending_credential_draft_credential_id_credential_id_fk", "tableFrom": "pending_credential_draft", "tableTo": "credential", - "columnsFrom": [ - "credential_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18265,12 +17387,8 @@ "name": "people_directory_entry_organization_id_people_directory_sync_organization_id_fk", "tableFrom": "people_directory_entry", "tableTo": "people_directory_sync", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "organization_id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["organization_id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18310,12 +17428,8 @@ "name": "people_directory_page_organization_id_people_directory_sync_organization_id_fk", "tableFrom": "people_directory_page", "tableTo": "people_directory_sync", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "organization_id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["organization_id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18323,11 +17437,7 @@ "compositePrimaryKeys": { "people_directory_page_organization_id_run_id_page_hash_pk": { "name": "people_directory_page_organization_id_run_id_page_hash_pk", - "columns": [ - "organization_id", - "run_id", - "page_hash" - ] + "columns": ["organization_id", "run_id", "page_hash"] } }, "uniqueConstraints": {}, @@ -18381,12 +17491,8 @@ "name": "people_directory_scim_change_organization_id_organization_id_fk", "tableFrom": "people_directory_scim_change", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18537,12 +17643,8 @@ "name": "people_directory_stage_organization_id_people_directory_sync_organization_id_fk", "tableFrom": "people_directory_stage", "tableTo": "people_directory_sync", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "organization_id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["organization_id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -18550,11 +17652,7 @@ "compositePrimaryKeys": { "people_directory_stage_organization_id_run_id_external_id_pk": { "name": "people_directory_stage_organization_id_run_id_external_id_pk", - "columns": [ - "organization_id", - "run_id", - "external_id" - ] + "columns": ["organization_id", "run_id", "external_id"] } }, "uniqueConstraints": {}, @@ -18706,12 +17804,8 @@ "name": "people_directory_sync_organization_id_organization_id_fk", "tableFrom": "people_directory_sync", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18719,12 +17813,8 @@ "name": "people_directory_sync_configured_by_user_id_fk", "tableFrom": "people_directory_sync", "tableTo": "user", - "columnsFrom": [ - "configured_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["configured_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -18971,12 +18061,8 @@ "name": "permission_access_request_organization_id_organization_id_fk", "tableFrom": "permission_access_request", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18984,12 +18070,8 @@ "name": "permission_access_request_requester_id_user_id_fk", "tableFrom": "permission_access_request", "tableTo": "user", - "columnsFrom": [ - "requester_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["requester_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -18997,12 +18079,8 @@ "name": "permission_access_request_decided_by_user_id_fk", "tableFrom": "permission_access_request", "tableTo": "user", - "columnsFrom": [ - "decided_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["decided_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -19147,12 +18225,8 @@ "name": "permission_group_organization_id_organization_id_fk", "tableFrom": "permission_group", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19160,12 +18234,8 @@ "name": "permission_group_created_by_user_id_fk", "tableFrom": "permission_group", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -19267,12 +18337,8 @@ "name": "permission_group_member_permission_group_id_permission_group_id_fk", "tableFrom": "permission_group_member", "tableTo": "permission_group", - "columnsFrom": [ - "permission_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["permission_group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19280,12 +18346,8 @@ "name": "permission_group_member_organization_id_organization_id_fk", "tableFrom": "permission_group_member", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19293,12 +18355,8 @@ "name": "permission_group_member_user_id_user_id_fk", "tableFrom": "permission_group_member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19306,12 +18364,8 @@ "name": "permission_group_member_assigned_by_user_id_fk", "tableFrom": "permission_group_member", "tableTo": "user", - "columnsFrom": [ - "assigned_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["assigned_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -19401,12 +18455,8 @@ "name": "permission_group_workspace_permission_group_id_permission_group_id_fk", "tableFrom": "permission_group_workspace", "tableTo": "permission_group", - "columnsFrom": [ - "permission_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["permission_group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19414,12 +18464,8 @@ "name": "permission_group_workspace_workspace_id_workspace_id_fk", "tableFrom": "permission_group_workspace", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19427,12 +18473,8 @@ "name": "permission_group_workspace_organization_id_organization_id_fk", "tableFrom": "permission_group_workspace", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -19575,12 +18617,8 @@ "name": "permissions_user_id_user_id_fk", "tableFrom": "permissions", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -19709,12 +18747,8 @@ "name": "pinned_item_user_id_user_id_fk", "tableFrom": "pinned_item", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -19722,12 +18756,8 @@ "name": "pinned_item_workspace_id_workspace_id_fk", "tableFrom": "pinned_item", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -19858,12 +18888,8 @@ "name": "project_organization_id_organization_id_fk", "tableFrom": "project", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }, @@ -19871,12 +18897,8 @@ "name": "project_owner_id_user_id_fk", "tableFrom": "project", "tableTo": "user", - "columnsFrom": [ - "owner_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" } @@ -19886,10 +18908,7 @@ "project_id_organization_scope_unique": { "name": "project_id_organization_scope_unique", "nullsNotDistinct": false, - "columns": [ - "id", - "organization_scope_key" - ] + "columns": ["id", "organization_scope_key"] } }, "policies": {}, @@ -20095,12 +19114,8 @@ "name": "public_share_workspace_id_workspace_id_fk", "tableFrom": "public_share", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -20108,12 +19123,8 @@ "name": "public_share_created_by_user_id_fk", "tableFrom": "public_share", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -20311,12 +19322,8 @@ "name": "resource_policy_workspace_id_workspace_id_fk", "tableFrom": "resource_policy", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -20324,12 +19331,8 @@ "name": "resource_policy_organization_id_organization_id_fk", "tableFrom": "resource_policy", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -20337,12 +19340,8 @@ "name": "resource_policy_created_by_user_id_fk", "tableFrom": "resource_policy", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -20350,12 +19349,8 @@ "name": "resource_policy_updated_by_user_id_fk", "tableFrom": "resource_policy", "tableTo": "user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -20493,12 +19488,8 @@ "name": "resume_queue_paused_execution_id_paused_executions_id_fk", "tableFrom": "resume_queue", "tableTo": "paused_executions", - "columnsFrom": [ - "paused_execution_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -20780,12 +19771,8 @@ "name": "scim_connection_organization_id_organization_id_fk", "tableFrom": "scim_connection", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -20793,12 +19780,8 @@ "name": "scim_connection_created_by_user_id_fk", "tableFrom": "scim_connection", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -20918,12 +19901,8 @@ "name": "scim_credential_connection_id_scim_connection_id_fk", "tableFrom": "scim_credential", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -20931,12 +19910,8 @@ "name": "scim_credential_revoked_by_user_id_fk", "tableFrom": "scim_credential", "tableTo": "user", - "columnsFrom": [ - "revoked_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["revoked_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -20944,12 +19919,8 @@ "name": "scim_credential_created_by_user_id_fk", "tableFrom": "scim_credential", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -21086,12 +20057,8 @@ "name": "scim_group_connection_id_scim_connection_id_fk", "tableFrom": "scim_group", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -21234,12 +20201,8 @@ "name": "scim_group_mapping_group_id_scim_group_id_fk", "tableFrom": "scim_group_mapping", "tableTo": "scim_group", - "columnsFrom": [ - "group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21247,12 +20210,8 @@ "name": "scim_group_mapping_permission_group_id_permission_group_id_fk", "tableFrom": "scim_group_mapping", "tableTo": "permission_group", - "columnsFrom": [ - "permission_group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["permission_group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21260,12 +20219,8 @@ "name": "scim_group_mapping_workspace_id_workspace_id_fk", "tableFrom": "scim_group_mapping", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21273,12 +20228,8 @@ "name": "scim_group_mapping_created_by_user_id_fk", "tableFrom": "scim_group_mapping", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -21367,12 +20318,8 @@ "name": "scim_group_member_group_id_scim_group_id_fk", "tableFrom": "scim_group_member", "tableTo": "scim_group", - "columnsFrom": [ - "group_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["group_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21380,12 +20327,8 @@ "name": "scim_group_member_scim_user_id_scim_user_id_fk", "tableFrom": "scim_group_member", "tableTo": "scim_user", - "columnsFrom": [ - "scim_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["scim_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -21515,12 +20458,8 @@ "name": "scim_projection_grant_connection_id_scim_connection_id_fk", "tableFrom": "scim_projection_grant", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21528,12 +20467,8 @@ "name": "scim_projection_grant_scim_user_id_scim_user_id_fk", "tableFrom": "scim_projection_grant", "tableTo": "scim_user", - "columnsFrom": [ - "scim_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["scim_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -21644,12 +20579,8 @@ "name": "scim_request_log_connection_id_scim_connection_id_fk", "tableFrom": "scim_request_log", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -21835,12 +20766,8 @@ "name": "scim_user_connection_id_scim_connection_id_fk", "tableFrom": "scim_user", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21848,12 +20775,8 @@ "name": "scim_user_user_id_user_id_fk", "tableFrom": "scim_user", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -21943,12 +20866,8 @@ "name": "scim_user_tombstone_connection_id_scim_connection_id_fk", "tableFrom": "scim_user_tombstone", "tableTo": "scim_connection", - "columnsFrom": [ - "connection_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["connection_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -21956,12 +20875,8 @@ "name": "scim_user_tombstone_user_id_user_id_fk", "tableFrom": "scim_user_tombstone", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -22178,12 +21093,8 @@ "name": "secret_usage_workspace_id_workspace_id_fk", "tableFrom": "secret_usage", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -22281,12 +21192,8 @@ "name": "session_user_id_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -22294,12 +21201,8 @@ "name": "session_active_organization_id_organization_id_fk", "tableFrom": "session", "tableTo": "organization", - "columnsFrom": [ - "active_organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -22309,9 +21212,7 @@ "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -22444,12 +21345,8 @@ "name": "settings_user_id_user_id_fk", "tableFrom": "settings", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -22459,9 +21356,7 @@ "settings_user_id_unique": { "name": "settings_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -22605,12 +21500,8 @@ "name": "sim_link_organization_id_organization_id_fk", "tableFrom": "sim_link", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -22618,12 +21509,8 @@ "name": "sim_link_created_by_user_id_fk", "tableFrom": "sim_link", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -22677,12 +21564,8 @@ "name": "sim_trigger_state_workflow_id_workflow_id_fk", "tableFrom": "sim_trigger_state", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -22690,11 +21573,7 @@ "compositePrimaryKeys": { "sim_trigger_state_workflow_id_block_id_scope_key_pk": { "name": "sim_trigger_state_workflow_id_block_id_scope_key_pk", - "columns": [ - "workflow_id", - "block_id", - "scope_key" - ] + "columns": ["workflow_id", "block_id", "scope_key"] } }, "uniqueConstraints": {}, @@ -22785,12 +21664,8 @@ "name": "skill_workspace_id_workspace_id_fk", "tableFrom": "skill", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -22798,12 +21673,8 @@ "name": "skill_user_id_user_id_fk", "tableFrom": "skill", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -22900,12 +21771,8 @@ "name": "skill_member_skill_id_skill_id_fk", "tableFrom": "skill_member", "tableTo": "skill", - "columnsFrom": [ - "skill_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["skill_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -22913,12 +21780,8 @@ "name": "skill_member_user_id_user_id_fk", "tableFrom": "skill_member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -22926,12 +21789,8 @@ "name": "skill_member_invited_by_user_id_fk", "tableFrom": "skill_member", "tableTo": "user", - "columnsFrom": [ - "invited_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["invited_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -23009,12 +21868,8 @@ "name": "slack_app_organization_id_organization_id_fk", "tableFrom": "slack_app", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -23212,12 +22067,8 @@ "name": "slack_search_installation_organization_id_organization_id_fk", "tableFrom": "slack_search_installation", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -23225,12 +22076,8 @@ "name": "slack_search_installation_credential_id_credential_id_fk", "tableFrom": "slack_search_installation", "tableTo": "credential", - "columnsFrom": [ - "credential_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["credential_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -23238,12 +22085,8 @@ "name": "slack_search_installation_slack_app_id_slack_app_id_fk", "tableFrom": "slack_search_installation", "tableTo": "slack_app", - "columnsFrom": [ - "slack_app_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["slack_app_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -23437,12 +22280,8 @@ "name": "slack_search_turn_installation_id_slack_search_installation_id_fk", "tableFrom": "slack_search_turn", "tableTo": "slack_search_installation", - "columnsFrom": [ - "installation_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["installation_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -23580,12 +22419,8 @@ "name": "sso_domain_organization_id_organization_id_fk", "tableFrom": "sso_domain", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -23593,12 +22428,8 @@ "name": "sso_domain_created_by_user_id_fk", "tableFrom": "sso_domain", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -23743,12 +22574,8 @@ "name": "sso_provider_user_id_user_id_fk", "tableFrom": "sso_provider", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -23756,12 +22583,8 @@ "name": "sso_provider_organization_id_organization_id_fk", "tableFrom": "sso_provider", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -24082,12 +22905,8 @@ "name": "table_jobs_table_id_user_table_definitions_id_fk", "tableFrom": "table_jobs", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24095,12 +22914,8 @@ "name": "table_jobs_workspace_id_workspace_id_fk", "tableFrom": "table_jobs", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -24269,12 +23084,8 @@ "name": "table_row_executions_table_id_user_table_definitions_id_fk", "tableFrom": "table_row_executions", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24282,12 +23093,8 @@ "name": "table_row_executions_row_id_user_table_rows_id_fk", "tableFrom": "table_row_executions", "tableTo": "user_table_rows", - "columnsFrom": [ - "row_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["row_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24295,12 +23102,8 @@ "name": "table_row_executions_capability_governed_user_id_user_id_fk", "tableFrom": "table_row_executions", "tableTo": "user", - "columnsFrom": [ - "capability_governed_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["capability_governed_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -24308,10 +23111,7 @@ "compositePrimaryKeys": { "table_row_executions_row_id_group_id_pk": { "name": "table_row_executions_row_id_group_id_pk", - "columns": [ - "row_id", - "group_id" - ] + "columns": ["row_id", "group_id"] } }, "uniqueConstraints": {}, @@ -24502,12 +23302,8 @@ "name": "table_run_dispatches_table_id_user_table_definitions_id_fk", "tableFrom": "table_run_dispatches", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24515,12 +23311,8 @@ "name": "table_run_dispatches_workspace_id_workspace_id_fk", "tableFrom": "table_run_dispatches", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24528,12 +23320,8 @@ "name": "table_run_dispatches_triggered_by_user_id_user_id_fk", "tableFrom": "table_run_dispatches", "tableTo": "user", - "columnsFrom": [ - "triggered_by_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["triggered_by_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -24541,12 +23329,8 @@ "name": "table_run_dispatches_capability_governed_user_id_user_id_fk", "tableFrom": "table_run_dispatches", "tableTo": "user", - "columnsFrom": [ - "capability_governed_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["capability_governed_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -24691,12 +23475,8 @@ "name": "table_views_table_id_user_table_definitions_id_fk", "tableFrom": "table_views", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24704,12 +23484,8 @@ "name": "table_views_workspace_id_workspace_id_fk", "tableFrom": "table_views", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -24717,12 +23493,8 @@ "name": "table_views_created_by_user_id_fk", "tableFrom": "table_views", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -25335,12 +24107,8 @@ "name": "usage_log_user_id_user_id_fk", "tableFrom": "usage_log", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -25348,12 +24116,8 @@ "name": "usage_log_workspace_id_workspace_id_fk", "tableFrom": "usage_log", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -25361,12 +24125,8 @@ "name": "usage_log_workflow_id_workflow_id_fk", "tableFrom": "usage_log", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -25518,16 +24278,12 @@ "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] }, "user_normalized_email_unique": { "name": "user_normalized_email_unique", "nullsNotDistinct": false, - "columns": [ - "normalized_email" - ] + "columns": ["normalized_email"] } }, "policies": {}, @@ -25634,12 +24390,8 @@ "name": "user_stats_user_id_user_id_fk", "tableFrom": "user_stats", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -25649,9 +24401,7 @@ "user_stats_user_id_unique": { "name": "user_stats_user_id_unique", "nullsNotDistinct": false, - "columns": [ - "user_id" - ] + "columns": ["user_id"] } }, "policies": {}, @@ -25891,12 +24641,8 @@ "name": "user_table_definitions_workspace_id_workspace_id_fk", "tableFrom": "user_table_definitions", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -25904,12 +24650,8 @@ "name": "user_table_definitions_folder_id_folder_id_fk", "tableFrom": "user_table_definitions", "tableTo": "folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -25917,12 +24659,8 @@ "name": "user_table_definitions_created_by_user_id_fk", "tableFrom": "user_table_definitions", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -25989,12 +24727,8 @@ "name": "user_table_row_changes_table_id_user_table_definitions_id_fk", "tableFrom": "user_table_row_changes", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -26048,12 +24782,8 @@ "name": "user_table_row_secret_provenance_row_id_user_table_rows_id_fk", "tableFrom": "user_table_row_secret_provenance", "tableTo": "user_table_rows", - "columnsFrom": [ - "row_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["row_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -26300,12 +25030,8 @@ "name": "user_table_rows_table_id_user_table_definitions_id_fk", "tableFrom": "user_table_rows", "tableTo": "user_table_definitions", - "columnsFrom": [ - "table_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["table_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -26313,12 +25039,8 @@ "name": "user_table_rows_workspace_id_workspace_id_fk", "tableFrom": "user_table_rows", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -26326,12 +25048,8 @@ "name": "user_table_rows_created_by_user_id_fk", "tableFrom": "user_table_rows", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -26467,9 +25185,7 @@ "waitlist_email_unique": { "name": "waitlist_email_unique", "nullsNotDistinct": false, - "columns": [ - "email" - ] + "columns": ["email"] } }, "policies": {}, @@ -26812,12 +25528,8 @@ "name": "webhook_workflow_id_workflow_id_fk", "tableFrom": "webhook", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -26825,12 +25537,8 @@ "name": "webhook_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "webhook", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -26909,12 +25617,8 @@ "name": "webhook_path_claim_workflow_id_workflow_id_fk", "tableFrom": "webhook_path_claim", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -27219,12 +25923,8 @@ "name": "workflow_user_id_user_id_fk", "tableFrom": "workflow", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27232,12 +25932,8 @@ "name": "workflow_workspace_id_workspace_id_fk", "tableFrom": "workflow", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27245,12 +25941,8 @@ "name": "workflow_folder_id_folder_id_fk", "tableFrom": "workflow", "tableTo": "folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -27436,12 +26128,8 @@ "name": "workflow_blocks_workflow_id_workflow_id_fk", "tableFrom": "workflow_blocks", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -27623,12 +26311,8 @@ "name": "workflow_checkpoints_user_id_user_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27636,12 +26320,8 @@ "name": "workflow_checkpoints_workflow_id_workflow_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27649,12 +26329,8 @@ "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", "tableFrom": "workflow_checkpoints", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -27911,12 +26587,8 @@ "name": "workflow_deployment_operation_workflow_id_workflow_id_fk", "tableFrom": "workflow_deployment_operation", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27924,12 +26596,8 @@ "name": "workflow_deployment_operation_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_deployment_operation", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -27937,12 +26605,8 @@ "name": "workflow_deployment_operation_previous_active_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_deployment_operation", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "previous_active_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["previous_active_version_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -28095,12 +26759,8 @@ "name": "workflow_deployment_version_workflow_id_workflow_id_fk", "tableFrom": "workflow_deployment_version", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -28208,12 +26868,8 @@ "name": "workflow_edges_workflow_id_workflow_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -28221,12 +26877,8 @@ "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "source_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -28234,12 +26886,8 @@ "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", "tableFrom": "workflow_edges", "tableTo": "workflow_blocks", - "columnsFrom": [ - "target_block_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -28717,12 +27365,8 @@ "name": "workflow_execution_logs_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -28730,12 +27374,8 @@ "name": "workflow_execution_logs_workspace_id_workspace_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -28743,12 +27383,8 @@ "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_execution_snapshots", - "columnsFrom": [ - "state_snapshot_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -28756,12 +27392,8 @@ "name": "workflow_execution_logs_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_execution_logs", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -28866,12 +27498,8 @@ "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", "tableFrom": "workflow_execution_snapshots", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -29018,12 +27646,8 @@ "name": "workflow_mcp_server_workspace_id_workspace_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29031,12 +27655,8 @@ "name": "workflow_mcp_server_created_by_user_id_fk", "tableFrom": "workflow_mcp_server", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -29191,12 +27811,8 @@ "name": "workflow_mcp_tool_server_id_workflow_mcp_server_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow_mcp_server", - "columnsFrom": [ - "server_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["server_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29204,12 +27820,8 @@ "name": "workflow_mcp_tool_workflow_id_workflow_id_fk", "tableFrom": "workflow_mcp_tool", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -29613,12 +28225,8 @@ "name": "workflow_schedule_workflow_id_workflow_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29626,12 +28234,8 @@ "name": "workflow_schedule_deployment_version_id_workflow_deployment_version_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow_deployment_version", - "columnsFrom": [ - "deployment_version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_version_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29639,12 +28243,8 @@ "name": "workflow_schedule_deployment_operation_id_workflow_deployment_operation_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workflow_deployment_operation", - "columnsFrom": [ - "deployment_operation_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_operation_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -29652,12 +28252,8 @@ "name": "workflow_schedule_source_user_id_user_id_fk", "tableFrom": "workflow_schedule", "tableTo": "user", - "columnsFrom": [ - "source_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29665,12 +28261,8 @@ "name": "workflow_schedule_source_workspace_id_workspace_id_fk", "tableFrom": "workflow_schedule", "tableTo": "workspace", - "columnsFrom": [ - "source_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -29753,12 +28345,8 @@ "name": "workflow_subflows_workflow_id_workflow_id_fk", "tableFrom": "workflow_subflows", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -29893,12 +28481,8 @@ "name": "workflow_test_workspace_id_workspace_id_fk", "tableFrom": "workflow_test", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -29906,12 +28490,8 @@ "name": "workflow_test_body_file_id_workspace_files_id_fk", "tableFrom": "workflow_test", "tableTo": "workspace_files", - "columnsFrom": [ - "body_file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["body_file_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -29919,12 +28499,8 @@ "name": "workflow_test_created_by_user_id_user_id_fk", "tableFrom": "workflow_test", "tableTo": "user", - "columnsFrom": [ - "created_by_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -30081,12 +28657,8 @@ "name": "workflow_test_run_test_id_workflow_test_id_fk", "tableFrom": "workflow_test_run", "tableTo": "workflow_test", - "columnsFrom": [ - "test_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["test_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -30094,12 +28666,8 @@ "name": "workflow_test_run_workspace_id_workspace_id_fk", "tableFrom": "workflow_test_run", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -30107,12 +28675,8 @@ "name": "workflow_test_run_triggered_by_user_id_user_id_fk", "tableFrom": "workflow_test_run", "tableTo": "user", - "columnsFrom": [ - "triggered_by_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["triggered_by_user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -30413,12 +28977,8 @@ "name": "workspace_owner_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "owner_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -30426,12 +28986,8 @@ "name": "workspace_organization_id_organization_id_fk", "tableFrom": "workspace", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -30439,12 +28995,8 @@ "name": "workspace_project_id_project_id_fk", "tableFrom": "workspace", "tableTo": "project", - "columnsFrom": [ - "project_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["project_id"], + "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }, @@ -30452,12 +29004,8 @@ "name": "workspace_billed_account_user_id_user_id_fk", "tableFrom": "workspace", "tableTo": "user", - "columnsFrom": [ - "billed_account_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -30465,12 +29013,8 @@ "name": "workspace_forked_from_workspace_id_workspace_id_fk", "tableFrom": "workspace", "tableTo": "workspace", - "columnsFrom": [ - "forked_from_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["forked_from_workspace_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -30478,14 +29022,8 @@ "name": "workspace_project_organization_fk", "tableFrom": "workspace", "tableTo": "project", - "columnsFrom": [ - "project_id", - "organization_scope_key" - ], - "columnsTo": [ - "id", - "organization_scope_key" - ], + "columnsFrom": ["project_id", "organization_scope_key"], + "columnsTo": ["id", "organization_scope_key"], "onDelete": "no action", "onUpdate": "no action" }, @@ -30493,14 +29031,8 @@ "name": "workspace_fork_project_fk", "tableFrom": "workspace", "tableTo": "workspace", - "columnsFrom": [ - "forked_from_workspace_id", - "project_id" - ], - "columnsTo": [ - "id", - "project_id" - ], + "columnsFrom": ["forked_from_workspace_id", "project_id"], + "columnsTo": ["id", "project_id"], "onDelete": "no action", "onUpdate": "no action" } @@ -30510,10 +29042,7 @@ "workspace_id_project_unique": { "name": "workspace_id_project_unique", "nullsNotDistinct": false, - "columns": [ - "id", - "project_id" - ] + "columns": ["id", "project_id"] } }, "policies": {}, @@ -30608,12 +29137,8 @@ "name": "workspace_byok_keys_workspace_id_workspace_id_fk", "tableFrom": "workspace_byok_keys", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -30621,12 +29146,8 @@ "name": "workspace_byok_keys_created_by_user_id_fk", "tableFrom": "workspace_byok_keys", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -30697,12 +29218,8 @@ "name": "workspace_environment_workspace_id_workspace_id_fk", "tableFrom": "workspace_environment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -30847,12 +29364,8 @@ "name": "workspace_file_workspace_id_workspace_id_fk", "tableFrom": "workspace_file", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -30860,12 +29373,8 @@ "name": "workspace_file_uploaded_by_user_id_fk", "tableFrom": "workspace_file", "tableTo": "user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -30875,9 +29384,7 @@ "workspace_file_key_unique": { "name": "workspace_file_key_unique", "nullsNotDistinct": false, - "columns": [ - "key" - ] + "columns": ["key"] } }, "policies": {}, @@ -30920,12 +29427,8 @@ "name": "workspace_file_collab_state_file_id_workspace_files_id_fk", "tableFrom": "workspace_file_collab_state", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -31255,12 +29758,8 @@ "name": "workspace_file_search_chunk_build_id_workspace_file_search_build_id_fk", "tableFrom": "workspace_file_search_chunk", "tableTo": "workspace_file_search_build", - "columnsFrom": [ - "build_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["build_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -31268,10 +29767,7 @@ "compositePrimaryKeys": { "workspace_file_search_chunk_pk": { "name": "workspace_file_search_chunk_pk", - "columns": [ - "build_id", - "ordinal" - ] + "columns": ["build_id", "ordinal"] } }, "uniqueConstraints": {}, @@ -31357,12 +29853,8 @@ "name": "workspace_file_search_queue_workspace_fk", "tableFrom": "workspace_file_search_dispatch_queue", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -31541,12 +30033,8 @@ "name": "workspace_file_search_index_file_fk", "tableFrom": "workspace_file_search_index", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -31554,12 +30042,8 @@ "name": "workspace_file_search_index_workspace_fk", "tableFrom": "workspace_file_search_index", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -31567,10 +30051,7 @@ "compositePrimaryKeys": { "workspace_file_search_index_pk": { "name": "workspace_file_search_index_pk", - "columns": [ - "file_id", - "source_content_updated_at" - ] + "columns": ["file_id", "source_content_updated_at"] } }, "uniqueConstraints": {}, @@ -31845,12 +30326,8 @@ "name": "workspace_file_search_revision_file_id_workspace_files_id_fk", "tableFrom": "workspace_file_search_revision", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -31858,12 +30335,8 @@ "name": "workspace_file_search_revision_build_id_workspace_file_search_build_id_fk", "tableFrom": "workspace_file_search_revision", "tableTo": "workspace_file_search_build", - "columnsFrom": [ - "build_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["build_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -31989,12 +30462,8 @@ "name": "workspace_file_search_segment_file_fk", "tableFrom": "workspace_file_search_segment", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -32002,12 +30471,8 @@ "name": "workspace_file_search_segment_workspace_fk", "tableFrom": "workspace_file_search_segment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -32015,12 +30480,7 @@ "compositePrimaryKeys": { "workspace_file_search_segment_pk": { "name": "workspace_file_search_segment_pk", - "columns": [ - "file_id", - "source_content_updated_at", - "line_number", - "segment_number" - ] + "columns": ["file_id", "source_content_updated_at", "line_number", "segment_number"] } }, "uniqueConstraints": {}, @@ -32071,12 +30531,8 @@ "name": "workspace_file_secret_provenance_file_id_workspace_files_id_fk", "tableFrom": "workspace_file_secret_provenance", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -32284,12 +30740,8 @@ "name": "workspace_file_version_file_id_workspace_files_id_fk", "tableFrom": "workspace_file_version", "tableTo": "workspace_files", - "columnsFrom": [ - "file_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["file_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -32297,12 +30749,8 @@ "name": "workspace_file_version_workspace_id_workspace_id_fk", "tableFrom": "workspace_file_version", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -32876,12 +31324,8 @@ "name": "workspace_files_project_id_project_id_fk", "tableFrom": "workspace_files", "tableTo": "project", - "columnsFrom": [ - "project_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["project_id"], + "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }, @@ -32889,12 +31333,8 @@ "name": "workspace_files_user_id_user_id_fk", "tableFrom": "workspace_files", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -32902,12 +31342,8 @@ "name": "workspace_files_workspace_id_workspace_id_fk", "tableFrom": "workspace_files", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -32915,12 +31351,8 @@ "name": "workspace_files_organization_id_organization_id_fk", "tableFrom": "workspace_files", "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -32928,12 +31360,8 @@ "name": "workspace_files_folder_id_folder_id_fk", "tableFrom": "workspace_files", "tableTo": "folder", - "columnsFrom": [ - "folder_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -32941,12 +31369,8 @@ "name": "workspace_files_chat_id_copilot_chats_id_fk", "tableFrom": "workspace_files", "tableTo": "copilot_chats", - "columnsFrom": [ - "chat_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -33120,12 +31544,8 @@ "name": "workspace_fork_block_map_child_workspace_id_workspace_id_fk", "tableFrom": "workspace_fork_block_map", "tableTo": "workspace", - "columnsFrom": [ - "child_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["child_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -33231,12 +31651,8 @@ "name": "workspace_fork_dependent_value_child_workspace_id_workspace_id_fk", "tableFrom": "workspace_fork_dependent_value", "tableTo": "workspace", - "columnsFrom": [ - "child_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["child_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -33345,12 +31761,8 @@ "name": "workspace_fork_promote_run_child_workspace_id_workspace_id_fk", "tableFrom": "workspace_fork_promote_run", "tableTo": "workspace", - "columnsFrom": [ - "child_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["child_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -33358,12 +31770,8 @@ "name": "workspace_fork_promote_run_created_by_user_id_fk", "tableFrom": "workspace_fork_promote_run", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -33464,12 +31872,8 @@ "name": "workspace_fork_resource_map_child_workspace_id_workspace_id_fk", "tableFrom": "workspace_fork_resource_map", "tableTo": "workspace", - "columnsFrom": [ - "child_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["child_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -33477,12 +31881,8 @@ "name": "workspace_fork_resource_map_created_by_user_id_fk", "tableFrom": "workspace_fork_resource_map", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -33692,12 +32092,8 @@ "name": "workspace_fork_workflow_sync_child_workspace_id_workspace_id_fk", "tableFrom": "workspace_fork_workflow_sync", "tableTo": "workspace", - "columnsFrom": [ - "child_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["child_workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -33705,12 +32101,8 @@ "name": "workspace_fork_workflow_sync_source_workflow_id_workflow_id_fk", "tableFrom": "workspace_fork_workflow_sync", "tableTo": "workflow", - "columnsFrom": [ - "source_workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -33718,12 +32110,8 @@ "name": "workspace_fork_workflow_sync_target_workflow_id_workflow_id_fk", "tableFrom": "workspace_fork_workflow_sync", "tableTo": "workflow", - "columnsFrom": [ - "target_workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["target_workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -33844,12 +32232,8 @@ "name": "workspace_operation_receipt_workspace_id_workspace_id_fk", "tableFrom": "workspace_operation_receipt", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -33980,12 +32364,8 @@ "name": "workspace_sandbox_workspace_id_workspace_id_fk", "tableFrom": "workspace_sandbox", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -33993,12 +32373,8 @@ "name": "workspace_sandbox_created_by_user_id_fk", "tableFrom": "workspace_sandbox", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -34055,12 +32431,8 @@ "name": "workspace_visit_user_id_user_id_fk", "tableFrom": "workspace_visit", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -34068,12 +32440,8 @@ "name": "workspace_visit_workspace_id_workspace_id_fk", "tableFrom": "workspace_visit", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -34081,10 +32449,7 @@ "compositePrimaryKeys": { "workspace_visit_user_id_workspace_id_pk": { "name": "workspace_visit_user_id_workspace_id_pk", - "columns": [ - "user_id", - "workspace_id" - ] + "columns": ["user_id", "workspace_id"] } }, "uniqueConstraints": {}, @@ -34097,134 +32462,72 @@ "public.api_key_access": { "name": "api_key_access", "schema": "public", - "values": [ - "read", - "write" - ] + "values": ["read", "write"] }, "public.aws_marketplace_license_status": { "name": "aws_marketplace_license_status", "schema": "public", - "values": [ - "pending", - "active", - "inactive" - ] + "values": ["pending", "active", "inactive"] }, "public.background_work_kind": { "name": "background_work_kind", "schema": "public", - "values": [ - "deployment_side_effects", - "fork_content_copy", - "fork_sync", - "fork_rollback" - ] + "values": ["deployment_side_effects", "fork_content_copy", "fork_sync", "fork_rollback"] }, "public.background_work_status_value": { "name": "background_work_status_value", "schema": "public", - "values": [ - "pending", - "processing", - "completed", - "completed_with_warnings", - "failed" - ] + "values": ["pending", "processing", "completed", "completed_with_warnings", "failed"] }, "public.billing_blocked_reason": { "name": "billing_blocked_reason", "schema": "public", - "values": [ - "payment_failed", - "dispute" - ] + "values": ["payment_failed", "dispute"] }, "public.billing_entity_type": { "name": "billing_entity_type", "schema": "public", - "values": [ - "user", - "organization" - ] + "values": ["user", "organization"] }, "public.chat_type": { "name": "chat_type", "schema": "public", - "values": [ - "mothership", - "copilot" - ] + "values": ["mothership", "copilot"] }, "public.copilot_async_tool_status": { "name": "copilot_async_tool_status", "schema": "public", - "values": [ - "pending", - "running", - "completed", - "failed", - "cancelled", - "delivered" - ] + "values": ["pending", "running", "completed", "failed", "cancelled", "delivered"] }, "public.copilot_run_status": { "name": "copilot_run_status", "schema": "public", - "values": [ - "active", - "paused_waiting_for_tool", - "resuming", - "complete", - "error", - "cancelled" - ] + "values": ["active", "paused_waiting_for_tool", "resuming", "complete", "error", "cancelled"] }, "public.copilot_tool_permission_decision": { "name": "copilot_tool_permission_decision", "schema": "public", - "values": [ - "allow", - "allow_chat", - "always_allow", - "skip" - ] + "values": ["allow", "allow_chat", "always_allow", "skip"] }, "public.credential_group_enrollment_status": { "name": "credential_group_enrollment_status", "schema": "public", - "values": [ - "invited", - "delivery_failed", - "in_progress", - "completed", - "revoked" - ] + "values": ["invited", "delivery_failed", "in_progress", "completed", "revoked"] }, "public.credential_group_status": { "name": "credential_group_status", "schema": "public", - "values": [ - "active", - "disabled" - ] + "values": ["active", "disabled"] }, "public.credential_member_role": { "name": "credential_member_role", "schema": "public", - "values": [ - "admin", - "member" - ] + "values": ["admin", "member"] }, "public.credential_member_status": { "name": "credential_member_status", "schema": "public", - "values": [ - "active", - "pending", - "revoked" - ] + "values": ["active", "pending", "revoked"] }, "public.credential_type": { "name": "credential_type", @@ -34242,10 +32545,7 @@ "public.data_drain_cadence": { "name": "data_drain_cadence", "schema": "public", - "values": [ - "hourly", - "daily" - ] + "values": ["hourly", "daily"] }, "public.data_drain_destination": { "name": "data_drain_destination", @@ -34264,146 +32564,82 @@ "public.data_drain_run_status": { "name": "data_drain_run_status", "schema": "public", - "values": [ - "running", - "success", - "failed" - ] + "values": ["running", "success", "failed"] }, "public.data_drain_run_trigger": { "name": "data_drain_run_trigger", "schema": "public", - "values": [ - "cron", - "manual" - ] + "values": ["cron", "manual"] }, "public.data_drain_source": { "name": "data_drain_source", "schema": "public", - "values": [ - "workflow_logs", - "job_logs", - "audit_logs", - "copilot_chats", - "copilot_runs" - ] + "values": ["workflow_logs", "job_logs", "audit_logs", "copilot_chats", "copilot_runs"] }, "public.execution_large_value_reference_source": { "name": "execution_large_value_reference_source", "schema": "public", - "values": [ - "execution_log", - "paused_snapshot" - ] + "values": ["execution_log", "paused_snapshot"] }, "public.folder_resource_type": { "name": "folder_resource_type", "schema": "public", - "values": [ - "workflow", - "file", - "knowledge_base", - "table" - ] + "values": ["workflow", "file", "knowledge_base", "table"] }, "public.invitation_kind": { "name": "invitation_kind", "schema": "public", - "values": [ - "organization", - "workspace" - ] + "values": ["organization", "workspace"] }, "public.invitation_membership_intent": { "name": "invitation_membership_intent", "schema": "public", - "values": [ - "internal", - "external" - ] + "values": ["internal", "external"] }, "public.invitation_status": { "name": "invitation_status", "schema": "public", - "values": [ - "pending", - "accepted", - "rejected", - "cancelled", - "expired" - ] + "values": ["pending", "accepted", "rejected", "cancelled", "expired"] }, "public.managed_oauth_credential_status": { "name": "managed_oauth_credential_status", "schema": "public", - "values": [ - "active", - "needs_reauth", - "revoked" - ] + "values": ["active", "needs_reauth", "revoked"] }, "public.permission_type": { "name": "permission_type", "schema": "public", - "values": [ - "admin", - "write", - "read" - ] + "values": ["admin", "write", "read"] }, "public.sandbox_image_status": { "name": "sandbox_image_status", "schema": "public", - "values": [ - "pending", - "building", - "ready", - "failed" - ] + "values": ["pending", "building", "ready", "failed"] }, "public.sandbox_language": { "name": "sandbox_language", "schema": "public", - "values": [ - "javascript", - "python" - ] + "values": ["javascript", "python"] }, "public.secret_usage_scope": { "name": "secret_usage_scope", "schema": "public", - "values": [ - "workspace", - "personal" - ] + "values": ["workspace", "personal"] }, "public.secret_usage_source": { "name": "secret_usage_source", "schema": "public", - "values": [ - "workflow", - "copilot", - "mcp" - ] + "values": ["workflow", "copilot", "mcp"] }, "public.upload_session_method": { "name": "upload_session_method", "schema": "public", - "values": [ - "put", - "multipart" - ] + "values": ["put", "multipart"] }, "public.upload_session_provider": { "name": "upload_session_provider", "schema": "public", - "values": [ - "local", - "s3", - "blob", - "gcs" - ] + "values": ["local", "s3", "blob", "gcs"] }, "public.upload_session_purpose": { "name": "upload_session_purpose", @@ -34438,12 +32674,7 @@ "public.usage_log_category": { "name": "usage_log_category", "schema": "public", - "values": [ - "model", - "fixed", - "tool", - "model_unbilled" - ] + "values": ["model", "fixed", "tool", "model_unbilled"] }, "public.usage_log_source": { "name": "usage_log_source", @@ -34466,34 +32697,17 @@ "public.workspace_file_search_index_status": { "name": "workspace_file_search_index_status", "schema": "public", - "values": [ - "pending", - "ready", - "skipped", - "failed" - ] + "values": ["pending", "ready", "skipped", "failed"] }, "public.workspace_file_version_source": { "name": "workspace_file_version_source", "schema": "public", - "values": [ - "upload", - "user", - "api", - "copilot", - "workflow", - "collab", - "revert", - "unknown" - ] + "values": ["upload", "user", "api", "copilot", "workflow", "collab", "revert", "unknown"] }, "public.workspace_fork_promote_direction": { "name": "workspace_fork_promote_direction", "schema": "public", - "values": [ - "push", - "pull" - ] + "values": ["push", "pull"] }, "public.workspace_fork_resource_type": { "name": "workspace_fork_resource_type", @@ -34519,11 +32733,7 @@ "public.workspace_mode": { "name": "workspace_mode", "schema": "public", - "values": [ - "personal", - "organization", - "grandfathered_shared" - ] + "values": ["personal", "organization", "grandfathered_shared"] } }, "schemas": {}, @@ -34547,4 +32757,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 4db8b65115a..5c2664488c0 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -3188,4 +3188,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} From ec1ff223814273da190d407a754c08f3a54de260 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:24:28 -0800 Subject: [PATCH 3/8] fix(api-keys): gate read-only key creation behind a flag and tighten docs - api-key-read-only flag (global, fallback API_KEY_READ_ONLY) gates creating read keys: the server answers 400 and the create modal hides Access while it is off. Enforcement of existing read keys is never gated, since older pods would serve them as full access - Reserve the mothership-delegation: key-name prefix so delegation minting can never adopt a user's key - Expiry is checked after every other key gate, so a foreign or banned key reports invalid - Workflow MCP serve and MCP discover answer an expired key with API key has expired - Share DAY_MS from the api-keys contract; the year bound's day of slack is for clock skew - Docs: per-surface refusal shapes, what read keys can still spend, and where the expiry message appears - Integration: flag-off and reserved-name refusals, v1 search asserts 200 --- .../docs/api-reference/authentication.mdx | 10 ++- apps/docs/content/docs/cli/authentication.mdx | 2 +- apps/docs/content/docs/mcp/authentication.mdx | 2 +- apps/sim/app/api/mcp/discover/route.ts | 9 ++- .../sim/app/api/mcp/serve/[serverId]/route.ts | 19 ++++-- apps/sim/app/o/[organizationId]/layout.tsx | 4 ++ .../app/workspace/[workspaceId]/layout.tsx | 4 ++ .../providers/feature-flags-provider.tsx | 1 + .../create-api-key-modal.tsx | 11 ++-- .../read-only-access.integration.ts | 66 +++++++++++++++++-- apps/sim/lib/api-key/feature-flag.ts | 11 ++++ apps/sim/lib/api-key/orchestration/index.ts | 48 ++++++++++---- apps/sim/lib/api-key/reserved-names.ts | 5 ++ apps/sim/lib/api-key/service.ts | 8 ++- apps/sim/lib/api/contracts/api-keys.ts | 3 + .../lib/api/server/routes/v2-api-key-auth.ts | 13 ++-- apps/sim/lib/core/config/env.ts | 1 + apps/sim/lib/core/config/feature-flags.ts | 5 ++ apps/sim/lib/mothership/chat/delegation.ts | 3 +- 19 files changed, 180 insertions(+), 45 deletions(-) create mode 100644 apps/sim/lib/api-key/feature-flag.ts create mode 100644 apps/sim/lib/api-key/reserved-names.ts diff --git a/apps/docs/content/docs/api-reference/authentication.mdx b/apps/docs/content/docs/api-reference/authentication.mdx index 0a5d04db648..58b962765fe 100644 --- a/apps/docs/content/docs/api-reference/authentication.mdx +++ b/apps/docs/content/docs/api-reference/authentication.mdx @@ -38,13 +38,17 @@ Delete a key from the same settings page to revoke it. Update applications that | Access | Allows | | --- | --- | | **Full access** | Everything the key's identity can do: reads, changes, deploys, and workflow runs | -| **Read only** | The operations the [`api:read` scope](#oauth-access-tokens) allows, including searches sent as POST requests and search chat, which `search:read` covers | +| **Read only** | The operations the [`api:read` scope](#oauth-access-tokens) allows, including searches sent as POST requests and search chat | -A read-only key cannot run, resume, or cancel workflows, or create, change, or delete anything. Those requests fail with `403` and `error.details.code` `READ_ONLY_API_KEY`. Access narrows a key; it never grants more than the key's identity already has. Access is fixed at creation, so create a new key to change it. Keys created before access levels existed have full access. Keys created from the deploy modal or for a workflow MCP server always have full access, because they exist to run workflows. +A read-only key cannot change workspace resources or run, resume, or cancel workflows. Reads can still cost credits: searches use embedding credits, and search chat uses model credits and keeps a private conversation history. Selector lookups call third-party services with your connected accounts. + +A refused request fails with `403` and the message `This API key is read-only and cannot perform this operation`. Where the surface carries a code, it is `READ_ONLY_API_KEY`: in `error.details.code` on the v2 API and the Sim MCP server, in `details.code` on the v1 API and workflow execution, and in `error.data.code` on a workflow MCP server. + +Access narrows a key; it never grants more than the key's identity already has. Access is fixed at creation, so create a new key to change it. Keys created before access levels existed have full access. Keys created from the deploy modal or for a workflow MCP server always have full access, because they exist to run workflows. If **Access** isn't shown when you create a key, read-only keys aren't available on your deployment yet. ### Expiration [#key-expiration] -A key expires 30 days, 90 days, or 1 year after creation, or never. The settings page defaults to never. After it expires, every request with the key fails with `401` and the message `API key has expired`; create a replacement before then. The key list shows each key's expiration date. `GET /api/v2/meta` reports the calling key's `expiresAt` and `scopes`. +A key expires 30 days, 90 days, or 1 year after creation, or never. The settings page defaults to never. After it expires, every request with the key fails with `401`. The v1 and v2 APIs, both MCP servers, and workflow execution answer with the message `API key has expired`. Create a replacement before then. The key list shows each key's expiration date. `GET /api/v2/meta` reports the calling key's `expiresAt` and `scopes`. ## Send an API key [#using-api-keys] diff --git a/apps/docs/content/docs/cli/authentication.mdx b/apps/docs/content/docs/cli/authentication.mdx index 1475ac1b6c1..6f50b83d4c6 100644 --- a/apps/docs/content/docs/cli/authentication.mdx +++ b/apps/docs/content/docs/cli/authentication.mdx @@ -154,7 +154,7 @@ export SIM_WORKSPACE="2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67" sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --input '{"source":"nightly"}' --output json ``` -The environment key overrides stored authentication. Use a workspace key only for supported workspace-scoped operations; organization audit logs and fork administration require a personal credential. A job that runs workflows needs a **Full access** key; a **Read only** key suits jobs that only read, such as exporting logs. Choose an expiration your secret rotation covers: an expired key fails with `API key has expired`. See [key access and expiration](/api-reference/authentication#key-access). Never commit credentials. `SIM_CONFIG_DIR` relocates local state when a runner has no writable home directory. +The environment key overrides stored authentication. Use a workspace key only for supported workspace-scoped operations; organization audit logs and fork administration require a personal credential. A job that runs workflows needs a **Full access** key; a **Read only** key suits jobs that only read, such as exporting logs. Choose an expiration your secret rotation covers: an expired key fails with `401` and `API key has expired`. See [key access and expiration](/api-reference/authentication#key-access). Never commit credentials. `SIM_CONFIG_DIR` relocates local state when a runner has no writable home directory. ### GitHub Actions diff --git a/apps/docs/content/docs/mcp/authentication.mdx b/apps/docs/content/docs/mcp/authentication.mdx index 32af01718d3..e0976b7e730 100644 --- a/apps/docs/content/docs/mcp/authentication.mdx +++ b/apps/docs/content/docs/mcp/authentication.mdx @@ -55,7 +55,7 @@ A personal key uses your current access in the workspaces you can reach. A works The Cursor process must receive `SIM_API_KEY` for its environment interpolation to work. For a self-hosted deployment, replace the Cloud URL in both examples with your server URL. -For an agent that only reads, create a **Read only** key: it reaches the operations `api:read` allows, and a write tool call fails with `READ_ONLY_API_KEY`. See [key access](/api-reference/authentication#key-access). +For an agent that only reads, create a **Read only** key: it reaches the operations `api:read` allows, and a tool call that changes something or runs a workflow fails with `403` and the code `READ_ONLY_API_KEY`. Search and search chat still use credits. See [key access](/api-reference/authentication#key-access). Keys created in Sim settings never expire unless you choose an expiration. Revoke a key when it is no longer needed. Prefer OAuth for an app that diff --git a/apps/sim/app/api/mcp/discover/route.ts b/apps/sim/app/api/mcp/discover/route.ts index 381fee62ab3..dbbe810cd17 100644 --- a/apps/sim/app/api/mcp/discover/route.ts +++ b/apps/sim/app/api/mcp/discover/route.ts @@ -3,6 +3,7 @@ import { workflowMcpServer, workspace } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, isNull, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' +import { API_KEY_EXPIRED } from '@/lib/api-key/policy-messages' import { checkHybridAuth } from '@/lib/auth/hybrid' import { getBaseUrl } from '@/lib/core/utils/urls' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' @@ -21,7 +22,13 @@ export const GET = withRouteHandler(async (request: NextRequest) => { if (!auth.success || !auth.userId) { return NextResponse.json( - { success: false, error: 'Authentication required. Provide X-API-Key header.' }, + { + success: false, + error: + auth.error === API_KEY_EXPIRED + ? API_KEY_EXPIRED + : 'Authentication required. Provide X-API-Key header.', + }, { status: 401 } ) } diff --git a/apps/sim/app/api/mcp/serve/[serverId]/route.ts b/apps/sim/app/api/mcp/serve/[serverId]/route.ts index 19fc099ba35..7bfefdb42dd 100644 --- a/apps/sim/app/api/mcp/serve/[serverId]/route.ts +++ b/apps/sim/app/api/mcp/serve/[serverId]/route.ts @@ -41,7 +41,11 @@ import { mcpServeRouteParamsSchema, mcpToolCallParamsSchema, } from '@/lib/api/contracts/mcp' -import { PERSONAL_KEY_DENIED, READ_ONLY_API_KEY_DENIED } from '@/lib/api-key/policy-messages' +import { + API_KEY_EXPIRED, + PERSONAL_KEY_DENIED, + READ_ONLY_API_KEY_DENIED, +} from '@/lib/api-key/policy-messages' import { type AuthResult, checkHybridAuth } from '@/lib/auth/hybrid' import { InvalidOAuthAccessTokenError, @@ -487,10 +491,14 @@ async function resolveWorkflowMcpBillingAttribution( * A 401 that points OAuth clients at this server's protected-resource metadata, * so they can discover Sim's authorization server and start the flow. */ -function unauthorizedResponse(serverId: string, invalidToken = false): NextResponse { +function unauthorizedResponse( + serverId: string, + invalidToken = false, + error?: string +): NextResponse { return withWorkflowMcpAuthChallenge( NextResponse.json( - { error: invalidToken ? 'Invalid access token' : 'Unauthorized' }, + { error: invalidToken ? 'Invalid access token' : (error ?? 'Unauthorized') }, { status: 401, ...(invalidToken && { headers: { 'WWW-Authenticate': 'Bearer error="invalid_token"' } }), @@ -565,7 +573,10 @@ async function authorizeMcpServeRequest( } } if (!auth.success || !auth.userId) { - return { response: unauthorizedResponse(server.id) } + const expired = auth.error === API_KEY_EXPIRED + return { + response: unauthorizedResponse(server.id, false, expired ? API_KEY_EXPIRED : undefined), + } } if (!auth.principal) { throw new Error('Authenticated MCP request is missing its principal') diff --git a/apps/sim/app/o/[organizationId]/layout.tsx b/apps/sim/app/o/[organizationId]/layout.tsx index ddaa31bf583..4f9527a7af7 100644 --- a/apps/sim/app/o/[organizationId]/layout.tsx +++ b/apps/sim/app/o/[organizationId]/layout.tsx @@ -3,6 +3,7 @@ import { dehydrate, HydrationBoundary } from '@tanstack/react-query' import { cookies } from 'next/headers' import { redirect } from 'next/navigation' import { SettingsNavigationProvider } from '@/components/settings/settings-navigation-provider' +import { isReadOnlyApiKeyCreationEnabled } from '@/lib/api-key/feature-flag' import { getSession } from '@/lib/auth' import { getActiveOrganizationId } from '@/lib/auth/session-response' import { canUseBenchmarks } from '@/lib/benchmarks/config' @@ -89,6 +90,7 @@ export default async function OrganizationLayout({ simLinksEnabled, peopleEnabled, simLinkOrganizationId, + readOnlyApiKeysEnabled, ] = await Promise.all([ prefetchOrganizationSidebar( queryClient, @@ -113,6 +115,7 @@ export default async function OrganizationLayout({ userId: session.user.id, sessionId: session.session.id, }), + isReadOnlyApiKeyCreationEnabled(), ]) const initialSidebarCollapsed = cookieStore.get('sidebar_collapsed')?.value === '1' @@ -128,6 +131,7 @@ export default async function OrganizationLayout({ 'mothership-plan-mode': benchmarkEnabled, 'mothership-memory-spaces': benchmarkEnabled, projects: projectsEnabled, + 'api-key-read-only': readOnlyApiKeysEnabled, }} > diff --git a/apps/sim/app/workspace/[workspaceId]/layout.tsx b/apps/sim/app/workspace/[workspaceId]/layout.tsx index fb9ac90703f..bac856a0651 100644 --- a/apps/sim/app/workspace/[workspaceId]/layout.tsx +++ b/apps/sim/app/workspace/[workspaceId]/layout.tsx @@ -4,6 +4,7 @@ import { cookies } from 'next/headers' import { redirect } from 'next/navigation' import { SettingsNavigationProvider } from '@/components/settings/settings-navigation-provider' import type { WorkspaceHostContext } from '@/lib/api/contracts/workspaces' +import { isReadOnlyApiKeyCreationEnabled } from '@/lib/api-key/feature-flag' import { getSession } from '@/lib/auth' import { getActiveOrganizationId } from '@/lib/auth/session-response' import { isChangelogEnabled } from '@/lib/changelog/feature-flag' @@ -137,6 +138,7 @@ async function WorkspaceContent({ computerUseEnabled, projectsEnabled, simLinkOrganizationId, + readOnlyApiKeysEnabled, ] = await Promise.all([ cookies(), orgSettings, @@ -157,6 +159,7 @@ async function WorkspaceContent({ isComputerUseAvailable(hostContext.hostOrganizationId), isProjectsEnabled(), resolveSimLinkOrganization(principal), + isReadOnlyApiKeyCreationEnabled(), prefetchWorkspaceAccess(queryClient, workspaceId, principal), prefetchWorkspaceForkAvailability(queryClient, workspaceId, principal, hostContext), ]) @@ -173,6 +176,7 @@ async function WorkspaceContent({ 'mothership-computer-use': computerUseEnabled, 'mothership-plan-mode': planModeEnabled, projects: projectsEnabled, + 'api-key-read-only': readOnlyApiKeysEnabled, }} > diff --git a/apps/sim/app/workspace/[workspaceId]/providers/feature-flags-provider.tsx b/apps/sim/app/workspace/[workspaceId]/providers/feature-flags-provider.tsx index f33fd8f230f..083d412a7e4 100644 --- a/apps/sim/app/workspace/[workspaceId]/providers/feature-flags-provider.tsx +++ b/apps/sim/app/workspace/[workspaceId]/providers/feature-flags-provider.tsx @@ -11,6 +11,7 @@ export interface WorkspaceFeatureFlags { 'mothership-computer-use'?: boolean 'mothership-memory-spaces'?: boolean projects?: boolean + 'api-key-read-only'?: boolean } const FeatureFlagsContext = createContext(null) diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/components/create-api-key-modal/create-api-key-modal.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/components/create-api-key-modal/create-api-key-modal.tsx index 4fcfd3fe941..e96fe9dbe76 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/components/create-api-key-modal/create-api-key-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/components/create-api-key-modal/create-api-key-modal.tsx @@ -14,13 +14,12 @@ import { } from '@sim/emcn' import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' -import type { ApiKeyAccessLevel } from '@/lib/api/contracts/api-keys' +import { type ApiKeyAccessLevel, DAY_MS } from '@/lib/api/contracts/api-keys' +import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider' import { type CreatedApiKey, useCreateApiKey } from '@/hooks/queries/api-keys' const logger = createLogger('CreateApiKeyModal') -const DAY_MS = 24 * 60 * 60 * 1000 - const EXPIRY_OPTIONS = [ { value: '30', label: '30 days' }, { value: '90', label: '90 days' }, @@ -76,6 +75,8 @@ export function CreateApiKeyModal({ const [newKey, setNewKey] = useState(null) const [showNewKeyDialog, setShowNewKeyDialog] = useState(false) const createApiKeyMutation = useCreateApiKey() + const readOnlyKeysEnabled = useFeatureFlag('api-key-read-only') + const canChooseAccess = !fullAccessOnly && readOnlyKeysEnabled /** * The form is seeded when the modal OPENS, not when this component mounts. @@ -127,7 +128,7 @@ export function CreateApiKeyModal({ const settings = { name: trimmedName, source, - access: fullAccessOnly ? 'write' : access, + access: canChooseAccess ? access : 'write', expiresAt: expiresAtFor(expiry), } as const const data = await createApiKeyMutation.mutateAsync( @@ -195,7 +196,7 @@ export function CreateApiKeyModal({ autoComplete='off' required /> - {!fullAccessOnly && ( + {canChooseAccess && ( authMock) +vi.mock('@/lib/core/config/feature-flags', () => featureFlagsMock) import { hashApiKey } from '@/lib/api-key/crypto' import { READ_ONLY_API_KEY_DENIED } from '@/lib/api-key/policy-messages' @@ -50,11 +54,13 @@ const userId = generateId() const workspaceId = generateId() const workflowId = generateId() const mcpServerId = generateId() +const knowledgeBaseId = generateId() const legacyKey = `sk-sim-fixture-${generateId()}` const expiredKey = `sk-sim-fixture-${generateId()}` let readPersonalKey = '' let readWorkspaceKey = '' +let readOnlyKeysEnabled = false type RouteHandler = (request: NextRequest, context: { params: Promise }) => Promise @@ -157,6 +163,22 @@ describe('read-only and expiring API keys in PostgreSQL', () => { createdBy: userId, name: 'Read-only key fixture', }) + await db.insert(knowledgeBase).values({ + id: knowledgeBaseId, + userId, + workspaceId, + name: 'Read-only key fixture', + }) + await db.insert(knowledgeBaseTagDefinitions).values({ + id: generateId(), + knowledgeBaseId, + tagSlot: 'tag1', + displayName: 'Topic', + fieldType: 'text', + }) + featureFlagsMockFns.mockIsFeatureEnabled.mockImplementation( + async (flag) => flag === 'api-key-read-only' && readOnlyKeysEnabled + ) await db.insert(apiKey).values([ { id: generateId(), @@ -197,7 +219,7 @@ describe('read-only and expiring API keys in PostgreSQL', () => { 'next tuesday', ]) { const created = await call(createPersonalKey, '/api/users/me/api-keys', { - body: { name: `Bad expiry ${generateId()}`, access: 'read', expiresAt }, + body: { name: `Bad expiry ${generateId()}`, expiresAt }, }) expect(created.status, expiresAt).toBe(400) } @@ -209,7 +231,31 @@ describe('read-only and expiring API keys in PostgreSQL', () => { expect(after).toHaveLength(before.length) }) + it('refuses to create a read-only key while the api-key-read-only flag is off', async () => { + const before = await db.select({ id: apiKey.id }).from(apiKey).where(eq(apiKey.userId, userId)) + const personal = await call(createPersonalKey, '/api/users/me/api-keys', { + body: { name: `Flag off personal ${generateId()}`, access: 'read' }, + }) + expect(personal.status).toBe(400) + expect(personal.body).toEqual({ error: 'Read-only API keys are not available yet' }) + const scoped = await call(createWorkspaceKey, `/api/workspaces/${workspaceId}/api-keys`, { + body: { name: `Flag off workspace ${generateId()}`, access: 'read' }, + params: { id: workspaceId }, + }) + expect(scoped.status).toBe(400) + const after = await db.select({ id: apiKey.id }).from(apiKey).where(eq(apiKey.userId, userId)) + expect(after).toHaveLength(before.length) + }) + + it('reserves the delegation key-name prefix', async () => { + const created = await call(createPersonalKey, '/api/users/me/api-keys', { + body: { name: `mothership-delegation:${userId}`, access: 'write' }, + }) + expect(created.status).toBe(400) + }) + it('mints read-only personal and workspace keys that report their access and expiry', async () => { + readOnlyKeysEnabled = true const expiresAt = new Date(Date.now() + 30 * DAY_MS).toISOString() const personal = await call(createPersonalKey, '/api/users/me/api-keys', { body: { name: `Read personal ${generateId()}`, access: 'read', expiresAt }, @@ -262,12 +308,18 @@ describe('read-only and expiring API keys in PostgreSQL', () => { expect(workflowMcpList.status).toBe(200) } - /** Search reads through POST, so the v1 write gate lets it through to the route's own checks. */ - const search = await call(v1KnowledgeSearch, '/api/v1/knowledge/search', { - key: readPersonalKey, - body: { workspaceId, knowledgeBaseIds: [generateId()], query: 'fixture' }, - }) - expect(JSON.stringify(search.body)).not.toContain('READ_ONLY_API_KEY') + /** Search reads through POST, so the v1 write gate lets it through. Tag-only, so nothing embeds. */ + for (const key of [readPersonalKey, readWorkspaceKey]) { + const search = await call(v1KnowledgeSearch, '/api/v1/knowledge/search', { + key, + body: { + workspaceId, + knowledgeBaseIds: knowledgeBaseId, + tagFilters: [{ tagName: 'Topic', value: 'fixture' }], + }, + }) + expect(search.status, JSON.stringify(search.body)).toBe(200) + } }) it('refuses every write path with READ_ONLY_API_KEY and changes nothing', async () => { diff --git a/apps/sim/lib/api-key/feature-flag.ts b/apps/sim/lib/api-key/feature-flag.ts new file mode 100644 index 00000000000..43e9b529a36 --- /dev/null +++ b/apps/sim/lib/api-key/feature-flag.ts @@ -0,0 +1,11 @@ +import { isFeatureEnabled } from '@/lib/core/config/feature-flags' + +/** + * Whether new read-only API keys may be created. A pod older than the release + * that enforces key access serves a read-only key as full access, so this turns + * on only after every pod enforces it. Enforcement of existing read-only keys + * never depends on it. + */ +export function isReadOnlyApiKeyCreationEnabled(): Promise { + return isFeatureEnabled('api-key-read-only') +} diff --git a/apps/sim/lib/api-key/orchestration/index.ts b/apps/sim/lib/api-key/orchestration/index.ts index 9e060bbb25f..c59b94fc10e 100644 --- a/apps/sim/lib/api-key/orchestration/index.ts +++ b/apps/sim/lib/api-key/orchestration/index.ts @@ -6,8 +6,11 @@ import { createLogger } from '@sim/logger' import { toError } from '@sim/utils/errors' import { generateShortId } from '@sim/utils/id' import { and, eq } from 'drizzle-orm' +import { DAY_MS } from '@/lib/api/contracts/api-keys' import { createApiKey, createWorkspaceApiKey } from '@/lib/api-key/auth' import { hashApiKey } from '@/lib/api-key/crypto' +import { isReadOnlyApiKeyCreationEnabled } from '@/lib/api-key/feature-flag' +import { DELEGATION_KEY_NAME_PREFIX } from '@/lib/api-key/reserved-names' import { PlatformEvents } from '@/lib/core/telemetry' const logger = createLogger('ApiKeyOrchestration') @@ -30,9 +33,7 @@ export function apiKeyCreationErrorStatus(code: ApiKeyOrchestrationErrorCode | u return 500 } -/** Also the shortest lifetime a key may be created with. */ -const DAY_MS = 24 * 60 * 60 * 1000 -/** The longest lifetime a key may be created with: a year, with a day of slack for time zones. */ +/** The longest lifetime a key may be created with: a year, with a day of slack for clock skew. */ const MAX_API_KEY_LIFETIME_MS = 366 * DAY_MS /** @@ -54,6 +55,7 @@ function resolveApiKeyExpiry(expiresAt: string | null | undefined): ResolvedExpi if (!Number.isFinite(lifetimeMs)) { return { ok: false, error: 'Expiration must be a valid date' } } + /** The shortest lifetime a key may be created with is one day. */ if (lifetimeMs < DAY_MS) { return { ok: false, error: 'Expiration must be at least one day from now' } } @@ -63,6 +65,26 @@ function resolveApiKeyExpiry(expiresAt: string | null | undefined): ResolvedExpi return { ok: true, expiresAt: date } } +type ResolvedIssueSettings = + | { ok: true; access: ApiKeyAccess; expiresAt: Date | null } + | { ok: false; error: string } + +/** Validates what a caller asked a new key to be, before anything is written. */ +async function resolveIssueSettings( + params: ApiKeyIssueSettings & { name: string } +): Promise { + if (params.name.startsWith(DELEGATION_KEY_NAME_PREFIX)) { + return { ok: false, error: `API key names may not start with "${DELEGATION_KEY_NAME_PREFIX}"` } + } + const access = params.access ?? 'write' + if (access === 'read' && !(await isReadOnlyApiKeyCreationEnabled())) { + return { ok: false, error: 'Read-only API keys are not available yet' } + } + const expiry = resolveApiKeyExpiry(params.expiresAt) + if (!expiry.ok) return expiry + return { ok: true, access, expiresAt: expiry.expiresAt } +} + export interface PerformCreateWorkspaceApiKeyParams extends ApiKeyIssueSettings { workspaceId: string userId: string @@ -109,9 +131,9 @@ export interface PerformCreatePersonalApiKeyResult { export async function performCreatePersonalApiKey( params: PerformCreatePersonalApiKeyParams ): Promise { - const expiry = resolveApiKeyExpiry(params.expiresAt) - if (!expiry.ok) return { success: false, errorCode: 'validation', error: expiry.error } - const access = params.access ?? 'write' + const settings = await resolveIssueSettings(params) + if (!settings.ok) return { success: false, errorCode: 'validation', error: settings.error } + const { access, expiresAt } = settings try { const existing = await db .select({ id: apiKey.id }) @@ -149,7 +171,7 @@ export async function performCreatePersonalApiKey( keyHash: hashApiKey(plainKey), type: 'personal', access, - expiresAt: expiry.expiresAt, + expiresAt, createdAt: new Date(), updatedAt: new Date(), }) @@ -175,7 +197,7 @@ export async function performCreatePersonalApiKey( keyName: params.name, keyType: 'personal', access, - expiresAt: expiry.expiresAt?.toISOString() ?? null, + expiresAt: expiresAt?.toISOString() ?? null, source: params.source ?? 'settings', }, request: params.request, @@ -193,16 +215,16 @@ export async function performCreatePersonalApiKey( export async function performCreateWorkspaceApiKey( params: PerformCreateWorkspaceApiKeyParams ): Promise { - const expiry = resolveApiKeyExpiry(params.expiresAt) - if (!expiry.ok) return { success: false, errorCode: 'validation', error: expiry.error } - const access = params.access ?? 'write' + const settings = await resolveIssueSettings(params) + if (!settings.ok) return { success: false, errorCode: 'validation', error: settings.error } + const { access, expiresAt } = settings try { const key = await createWorkspaceApiKey({ workspaceId: params.workspaceId, userId: params.userId, name: params.name, access, - expiresAt: expiry.expiresAt, + expiresAt, }) if (params.captureAnalytics !== false) { @@ -235,7 +257,7 @@ export async function performCreateWorkspaceApiKey( keyName: params.name, keyType: 'workspace', access, - expiresAt: expiry.expiresAt?.toISOString() ?? null, + expiresAt: expiresAt?.toISOString() ?? null, source: params.source ?? 'settings', }, }) diff --git a/apps/sim/lib/api-key/reserved-names.ts b/apps/sim/lib/api-key/reserved-names.ts new file mode 100644 index 00000000000..7c312d5b5b0 --- /dev/null +++ b/apps/sim/lib/api-key/reserved-names.ts @@ -0,0 +1,5 @@ +/** + * Names the server mints its own rolling delegation keys under. A user may not + * create a key with one, so the minter can never adopt or rotate a user's key. + */ +export const DELEGATION_KEY_NAME_PREFIX = 'mothership-delegation:' diff --git a/apps/sim/lib/api-key/service.ts b/apps/sim/lib/api-key/service.ts index 7d9a43ad7ab..7ff3ae1515d 100644 --- a/apps/sim/lib/api-key/service.ts +++ b/apps/sim/lib/api-key/service.ts @@ -102,9 +102,6 @@ export async function authenticateApiKeyFromHeader( if (options.userId && record.userId !== options.userId) return INVALID if (options.keyTypes?.length && !options.keyTypes.includes(keyType)) return INVALID - if (record.expiresAt && record.expiresAt < new Date()) { - return { success: false, error: API_KEY_EXPIRED, expired: true } - } if ( options.workspaceId && @@ -126,6 +123,11 @@ export async function authenticateApiKeyFromHeader( if (permission === null) return INVALID } + /** Last, so a key that fails any other gate reports invalid rather than expired. */ + if (record.expiresAt && record.expiresAt < new Date()) { + return { success: false, error: API_KEY_EXPIRED, expired: true } + } + logger.debug('API key matched via hash lookup', { keyId: record.id, keyType }) setRequestAuth( { kind: keyType === 'personal' ? 'personal_api_key' : 'workspace_api_key' }, diff --git a/apps/sim/lib/api/contracts/api-keys.ts b/apps/sim/lib/api/contracts/api-keys.ts index 7cde5bfac87..04cbc0efc0f 100644 --- a/apps/sim/lib/api/contracts/api-keys.ts +++ b/apps/sim/lib/api/contracts/api-keys.ts @@ -1,6 +1,9 @@ import { z } from 'zod' import { defineRouteContract } from '@/lib/api/contracts/types' +/** One day in milliseconds: a key's expiry options and its creation bounds are counted in days. */ +export const DAY_MS = 24 * 60 * 60 * 1000 + const apiKeyAccessSchema = z.enum(['read', 'write']) export type ApiKeyAccessLevel = z.output diff --git a/apps/sim/lib/api/server/routes/v2-api-key-auth.ts b/apps/sim/lib/api/server/routes/v2-api-key-auth.ts index 26cf238c084..bb636387d10 100644 --- a/apps/sim/lib/api/server/routes/v2-api-key-auth.ts +++ b/apps/sim/lib/api/server/routes/v2-api-key-auth.ts @@ -83,9 +83,6 @@ interface ApiKeyRow { function requireValidRow(row: ApiKeyRow | undefined): ApiKeyRow { if (!row) throw new V2ApiKeyUnauthenticatedError() - if (row.expiresAt && row.expiresAt < new Date()) { - throw new V2ApiKeyUnauthenticatedError(API_KEY_EXPIRED) - } if (row.type === 'personal' && row.workspaceId === null) { if (row.userBanned === null) { throw new Error(`Personal API key ${row.id} is missing its credential owner`) @@ -96,10 +93,14 @@ function requireValidRow(row: ApiKeyRow | undefined): ApiKeyRow { * intact, so refusing the key here is what ends its machine access. */ if (row.userSuspendedAt) throw new V2ApiKeyUnauthenticatedError() - return row + } else if (row.type !== 'workspace' || !row.workspaceId) { + throw new Error(`API key ${row.id} has an invalid persisted type/workspace combination`) + } + /** Last, so a key that fails any other gate reports invalid rather than expired. */ + if (row.expiresAt && row.expiresAt < new Date()) { + throw new V2ApiKeyUnauthenticatedError(API_KEY_EXPIRED) } - if (row.type === 'workspace' && row.workspaceId) return row - throw new Error(`API key ${row.id} has an invalid persisted type/workspace combination`) + return row } async function personalSubscription(userId: string): Promise { diff --git a/apps/sim/lib/core/config/env.ts b/apps/sim/lib/core/config/env.ts index 01b51480d1a..ff948f35a8f 100644 --- a/apps/sim/lib/core/config/env.ts +++ b/apps/sim/lib/core/config/env.ts @@ -620,6 +620,7 @@ export const env = createEnv({ CHANGELOG: z.boolean().optional(), // Fallback for the `changelog` feature flag off AppConfig SIM_LINKS: z.boolean().optional(), // Fallback for the `sim-links` feature flag off AppConfig PEOPLE: z.boolean().optional(), // Fallback for the `people` feature flag off AppConfig + API_KEY_READ_ONLY: z.boolean().optional(), // Fallback for the `api-key-read-only` feature flag off AppConfig MSHIP_MODEL_SELECTOR: z.boolean().optional(), INBOX_ENABLED: z.boolean().optional(), // Enable inbox (Sim Mailer) on self-hosted (bypasses hosted requirements) SANDBOXES_ENABLED: z.boolean().optional(), // Enable custom sandboxes on self-hosted (bypasses hosted requirements) diff --git a/apps/sim/lib/core/config/feature-flags.ts b/apps/sim/lib/core/config/feature-flags.ts index 5394541ae6e..42d83122109 100644 --- a/apps/sim/lib/core/config/feature-flags.ts +++ b/apps/sim/lib/core/config/feature-flags.ts @@ -77,6 +77,11 @@ const FEATURE_FLAGS = { 'Enable the organization People directory, org chart, profile imports, and directory sync. Supports organization rollout; disabled by default.', fallback: 'PEOPLE', }, + 'api-key-read-only': { + description: + 'Allow creating read-only API keys. Turn on only after every pod runs a release that enforces key access, since older pods treat a read-only key as full access. Enforcement of existing read-only keys never depends on this flag. Global; disabled by default.', + fallback: 'API_KEY_READ_ONLY', + }, 'mothership-model-selector': { description: 'Show the Mothership model selector, model-specific effort levels, and Fast for supported ' + diff --git a/apps/sim/lib/mothership/chat/delegation.ts b/apps/sim/lib/mothership/chat/delegation.ts index 928353270a0..18b46064da2 100644 --- a/apps/sim/lib/mothership/chat/delegation.ts +++ b/apps/sim/lib/mothership/chat/delegation.ts @@ -4,6 +4,7 @@ import { generateShortId } from '@sim/utils/id' import { and, eq, gt } from 'drizzle-orm' import { createApiKey } from '@/lib/api-key/auth' import { decryptApiKey, hashApiKey } from '@/lib/api-key/crypto' +import { DELEGATION_KEY_NAME_PREFIX } from '@/lib/api-key/reserved-names' import { acquireAdvisoryXactLock } from '@/lib/db/advisory-locks' import { traceMothershipQuery, @@ -16,7 +17,7 @@ const DELEGATION_TTL_MS = 12 * 60 * 60 * 1000 const MIN_REMAINING_MS = 30 * 60 * 1000 function delegationName(userId: string): string { - return `mothership-delegation:${userId}` + return `${DELEGATION_KEY_NAME_PREFIX}${userId}` } /** From f9686a41eb2251f6fd68a4a2a4023146ccfb930d Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:30:44 -0800 Subject: [PATCH 4/8] fix(api-keys): give the key row caption a props interface --- .../[workspaceId]/settings/components/api-keys/api-keys.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx index 033dd06fb15..6e3119b7230 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/api-keys/api-keys.tsx @@ -49,8 +49,12 @@ function formatLastUsed(dateString?: string | null): string { return formatDate(new Date(dateString)) } +interface ApiKeyRowBadgeProps { + apiKey: ApiKey +} + /** The row caption: last use and expiry, after a tag when the key is read-only. */ -function ApiKeyRowBadge({ apiKey }: { apiKey: ApiKey }) { +function ApiKeyRowBadge({ apiKey }: ApiKeyRowBadgeProps) { const parts = [`last used ${formatLastUsed(apiKey.lastUsed).toLowerCase()}`] if (apiKey.expiresAt) { const expiresAt = new Date(apiKey.expiresAt) From 647685dd9dc0a06f6ce2142ba33ff913308fa832 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:34:48 -0800 Subject: [PATCH 5/8] fix(api-keys): surface key validation errors from Copilot key creation --- apps/sim/lib/api-key/application/create-api-key.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/sim/lib/api-key/application/create-api-key.ts b/apps/sim/lib/api-key/application/create-api-key.ts index 4ea3c77aaf5..4d4572d0d18 100644 --- a/apps/sim/lib/api-key/application/create-api-key.ts +++ b/apps/sim/lib/api-key/application/create-api-key.ts @@ -40,6 +40,9 @@ export const createCopilotWorkspaceApiKey = defineAuthorizedWorkspaceUseCase({ if (result.errorCode === 'conflict') { throw new OrchestrationError('conflict', result.error ?? 'API key name already exists') } + if (result.errorCode === 'validation') { + throw new OrchestrationError('validation', result.error ?? 'Invalid API key settings') + } throw new Error('Failed to create workspace API key') } return { key: result.key, workspaceId: context.workspaceId } From 0d6c3760f9cb371d0e2483e1ba0950d9a085e231 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:43:46 -0800 Subject: [PATCH 6/8] test(api-keys): compare audit actors with the principal's actor projection --- apps/sim/lib/knowledge/application/documents.test.ts | 3 ++- apps/sim/lib/knowledge/application/folders.test.ts | 3 ++- .../lib/knowledge/application/knowledge-bases.test.ts | 3 ++- apps/sim/lib/workflows/application/crud.test.ts | 11 +++++++---- apps/sim/lib/workflows/application/folders.test.ts | 6 ++++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/apps/sim/lib/knowledge/application/documents.test.ts b/apps/sim/lib/knowledge/application/documents.test.ts index 92fe406159a..76f1bf59ec5 100644 --- a/apps/sim/lib/knowledge/application/documents.test.ts +++ b/apps/sim/lib/knowledge/application/documents.test.ts @@ -1,3 +1,4 @@ +import { toPrincipalActor } from '@sim/auth/principal' import { queueTableRows, resetDbChainMock, schemaMock } from '@sim/testing' import { createPersonalApiKeyPrincipal, @@ -379,7 +380,7 @@ describe('knowledge document application use cases', () => { actorName: 'Workspace API key', metadata: expect.objectContaining({ operation: 'knowledge.documents.upload', - actor: createWorkspaceApiKeyPrincipal(), + actor: toPrincipalActor(createWorkspaceApiKeyPrincipal()), }), }) ) diff --git a/apps/sim/lib/knowledge/application/folders.test.ts b/apps/sim/lib/knowledge/application/folders.test.ts index 262bf5fe8ef..0642e307483 100644 --- a/apps/sim/lib/knowledge/application/folders.test.ts +++ b/apps/sim/lib/knowledge/application/folders.test.ts @@ -1,3 +1,4 @@ +import { toPrincipalActor } from '@sim/auth/principal' import { createWorkspaceApiKeyPrincipal } from '@sim/testing/factories/principal.factory' import { auditMock, auditMockFns } from '@sim/testing/mocks/audit.mock' import { folderQueriesMock, folderQueriesMockFns } from '@sim/testing/mocks/folder-queries.mock' @@ -114,7 +115,7 @@ describe('knowledge folder application use cases', () => { actorName: 'Workspace API key', metadata: expect.objectContaining({ operation: 'knowledge.folders.create', - actor: createWorkspaceApiKeyPrincipal(), + actor: toPrincipalActor(createWorkspaceApiKeyPrincipal()), }), }) ) diff --git a/apps/sim/lib/knowledge/application/knowledge-bases.test.ts b/apps/sim/lib/knowledge/application/knowledge-bases.test.ts index 31c8267a3e0..3d65d45acdf 100644 --- a/apps/sim/lib/knowledge/application/knowledge-bases.test.ts +++ b/apps/sim/lib/knowledge/application/knowledge-bases.test.ts @@ -1,3 +1,4 @@ +import { toPrincipalActor } from '@sim/auth/principal' import { createSessionPrincipal, createWorkspaceApiKeyPrincipal, @@ -235,7 +236,7 @@ describe('knowledge base application use cases', () => { actorName: 'Workspace API key', metadata: expect.objectContaining({ operation: 'knowledge.create', - actor: createWorkspaceApiKeyPrincipal({ keyId: 'workspace-key-1' }), + actor: toPrincipalActor(createWorkspaceApiKeyPrincipal({ keyId: 'workspace-key-1' })), }), }) ) diff --git a/apps/sim/lib/workflows/application/crud.test.ts b/apps/sim/lib/workflows/application/crud.test.ts index 9c1a9955fbe..640057a7a5e 100644 --- a/apps/sim/lib/workflows/application/crud.test.ts +++ b/apps/sim/lib/workflows/application/crud.test.ts @@ -1,3 +1,4 @@ +import { toPrincipalActor } from '@sim/auth/principal' import { createPersonalApiKeyPrincipal, createWorkspaceApiKeyPrincipal, @@ -218,10 +219,12 @@ describe('authorized workflow CRUD and version reads', () => { actorId: null, actorName: 'Workspace API key', metadata: expect.objectContaining({ - actor: createWorkspaceApiKeyPrincipal({ - keyId: 'workspace-key-1', - workspaceId: WORKSPACE_ID, - }), + actor: toPrincipalActor( + createWorkspaceApiKeyPrincipal({ + keyId: 'workspace-key-1', + workspaceId: WORKSPACE_ID, + }) + ), }), }) ) diff --git a/apps/sim/lib/workflows/application/folders.test.ts b/apps/sim/lib/workflows/application/folders.test.ts index 4d8a9d78346..3f70c3fb79a 100644 --- a/apps/sim/lib/workflows/application/folders.test.ts +++ b/apps/sim/lib/workflows/application/folders.test.ts @@ -1,4 +1,4 @@ -import type { Principal } from '@sim/auth/principal' +import { type Principal, toPrincipalActor } from '@sim/auth/principal' import { createPersonalApiKeyPrincipal, createSessionPrincipal, @@ -160,7 +160,9 @@ describe('workflow folder application operations', () => { actorId: null, actorName: 'Workspace API key', metadata: expect.objectContaining({ - actor: createWorkspaceApiKeyPrincipal({ keyId: 'workspace-1', workspaceId: 'ws-1' }), + actor: toPrincipalActor( + createWorkspaceApiKeyPrincipal({ keyId: 'workspace-1', workspaceId: 'ws-1' }) + ), }), }) ) From 82958a69e4c3fb729ed393ef766407cbe8ee205e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:51:40 -0800 Subject: [PATCH 7/8] fix(api-keys): provide feature flags to account settings and clarify meta scopes - The account settings layout resolves api-key-read-only and wraps its sections in FeatureFlagsProvider, as the workspace and organization layouts do, so personal API key settings no longer throw from the create modal's flag read - The /api/v2/meta scopes description says read-only keys are also refused every operation that declares no API scope; OpenAPI regenerated --- apps/docs/openapi-v2-resources.json | 2 +- apps/sim/app/account/settings/layout.test.tsx | 45 +++++++++++++++++++ apps/sim/app/account/settings/layout.tsx | 31 ++++++++++--- apps/sim/lib/api/contracts/v2/meta.ts | 2 +- 4 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 apps/sim/app/account/settings/layout.test.tsx diff --git a/apps/docs/openapi-v2-resources.json b/apps/docs/openapi-v2-resources.json index b511a1a4d79..1a858de5f42 100644 --- a/apps/docs/openapi-v2-resources.json +++ b/apps/docs/openapi-v2-resources.json @@ -18651,7 +18651,7 @@ "type": "string", "enum": ["api:read", "api:write", "search:read"] }, - "description": "API scopes the calling credential holds. A read-only API key holds only api:read and is refused every operation that changes state; a full-access key holds api:read and api:write; an OAuth access token holds what it was granted." + "description": "API scopes the calling credential holds. A read-only API key holds only api:read: it is refused every operation that changes state and every operation that declares no API scope, so api:read alone does not authorize those. A full-access key holds api:read and api:write; an OAuth access token holds what it was granted." } }, "required": ["v2Enabled", "keyType", "expiresAt", "scopes"], diff --git a/apps/sim/app/account/settings/layout.test.tsx b/apps/sim/app/account/settings/layout.test.tsx new file mode 100644 index 00000000000..55dd1b7a9f7 --- /dev/null +++ b/apps/sim/app/account/settings/layout.test.tsx @@ -0,0 +1,45 @@ +import type { ReactNode } from 'react' +import { authMockFns } from '@sim/testing' +import { featureFlagsMock, featureFlagsMockFns } from '@sim/testing/mocks/feature-flags.mock' +import { nextNavigationMock } from '@sim/testing/mocks/next-navigation.mock' +import { renderToStaticMarkup } from 'react-dom/server' +import { beforeEach, describe, expect, it, vi } from 'vitest' + +vi.mock('next/navigation', () => nextNavigationMock) +vi.mock('@/lib/core/config/feature-flags', () => featureFlagsMock) +vi.mock('@/lib/permissions/super-user', () => ({ isPlatformAdmin: vi.fn(async () => false) })) +vi.mock('@/components/settings/standalone-settings-shell', () => ({ + StandaloneSettingsShell: ({ children }: { children: ReactNode }) => children, +})) + +import AccountSettingsLayout from '@/app/account/settings/layout' +import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider' + +/** Stands in for the personal API keys page, whose create modal reads this flag on every render. */ +function ReadOnlyKeysFlag() { + return {`read-only keys ${useFeatureFlag('api-key-read-only') ? 'on' : 'off'}`} +} + +async function renderAccountSettings(): Promise { + const element = await AccountSettingsLayout({ children: }) + return renderToStaticMarkup(element) +} + +describe('AccountSettingsLayout', () => { + beforeEach(() => { + authMockFns.mockGetSession.mockResolvedValue({ + user: { id: 'viewer-1' }, + session: { id: 'session-1' }, + }) + }) + + it.each([ + [true, 'on'], + [false, 'off'], + ])('gives account sections the read-only key flag (%s)', async (enabled, rendered) => { + featureFlagsMockFns.mockIsFeatureEnabled.mockImplementation( + async (flag) => flag === 'api-key-read-only' && enabled + ) + expect(await renderAccountSettings()).toContain(`read-only keys ${rendered}`) + }) +}) diff --git a/apps/sim/app/account/settings/layout.tsx b/apps/sim/app/account/settings/layout.tsx index e18e8bb84f1..2cc46a3d1f8 100644 --- a/apps/sim/app/account/settings/layout.tsx +++ b/apps/sim/app/account/settings/layout.tsx @@ -1,21 +1,38 @@ import { redirect } from 'next/navigation' import { StandaloneSettingsShell } from '@/components/settings/standalone-settings-shell' +import { isReadOnlyApiKeyCreationEnabled } from '@/lib/api-key/feature-flag' import { getSession } from '@/lib/auth' import { resolveDeploymentShape } from '@/lib/core/config/deployment-shape' import { isPlatformAdmin } from '@/lib/permissions/super-user' +import { FeatureFlagsProvider } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider' export default async function AccountSettingsLayout({ children }: { children: React.ReactNode }) { const session = await getSession() if (!session?.user) redirect('/login') - const isSuperUser = await isPlatformAdmin(session.user.id) + const [isSuperUser, readOnlyApiKeysEnabled] = await Promise.all([ + isPlatformAdmin(session.user.id), + isReadOnlyApiKeyCreationEnabled(), + ]) + /** Account settings host no workspace surface, so only the flags its sections read are on. */ return ( - - {children} - + + {children} + + ) } diff --git a/apps/sim/lib/api/contracts/v2/meta.ts b/apps/sim/lib/api/contracts/v2/meta.ts index 4e82909e20b..7787b01243d 100644 --- a/apps/sim/lib/api/contracts/v2/meta.ts +++ b/apps/sim/lib/api/contracts/v2/meta.ts @@ -25,7 +25,7 @@ export const v2MetaSchema = z scopes: z .array(z.enum(['api:read', 'api:write', 'search:read'])) .describe( - 'API scopes the calling credential holds. A read-only API key holds only api:read and is refused every operation that changes state; a full-access key holds api:read and api:write; an OAuth access token holds what it was granted.' + 'API scopes the calling credential holds. A read-only API key holds only api:read: it is refused every operation that changes state and every operation that declares no API scope, so api:read alone does not authorize those. A full-access key holds api:read and api:write; an OAuth access token holds what it was granted.' ), }) .meta({ From 329c1203df0965d22ae3838b768f43511741b444 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 10 Nov 2026 13:56:46 -0800 Subject: [PATCH 8/8] test(api-keys): assert the account layout's flag value instead of rendered text --- apps/sim/app/account/settings/layout.test.tsx | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/sim/app/account/settings/layout.test.tsx b/apps/sim/app/account/settings/layout.test.tsx index 55dd1b7a9f7..a3214f53af2 100644 --- a/apps/sim/app/account/settings/layout.test.tsx +++ b/apps/sim/app/account/settings/layout.test.tsx @@ -15,14 +15,19 @@ vi.mock('@/components/settings/standalone-settings-shell', () => ({ import AccountSettingsLayout from '@/app/account/settings/layout' import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider' -/** Stands in for the personal API keys page, whose create modal reads this flag on every render. */ -function ReadOnlyKeysFlag() { - return {`read-only keys ${useFeatureFlag('api-key-read-only') ? 'on' : 'off'}`} -} - -async function renderAccountSettings(): Promise { - const element = await AccountSettingsLayout({ children: }) - return renderToStaticMarkup(element) +/** + * Renders the account layout around a section that reads the read-only key flag the way the + * personal API keys page's create modal does on every render, and returns what it read. + */ +async function readFlagInAccountSettings(): Promise { + let observed: boolean | undefined + function ReadOnlyKeysSection() { + observed = useFeatureFlag('api-key-read-only') + return null + } + renderToStaticMarkup(await AccountSettingsLayout({ children: })) + if (observed === undefined) throw new Error('The account section never rendered') + return observed } describe('AccountSettingsLayout', () => { @@ -33,13 +38,10 @@ describe('AccountSettingsLayout', () => { }) }) - it.each([ - [true, 'on'], - [false, 'off'], - ])('gives account sections the read-only key flag (%s)', async (enabled, rendered) => { + it.each([true, false])('gives account sections the read-only key flag (%s)', async (enabled) => { featureFlagsMockFns.mockIsFeatureEnabled.mockImplementation( async (flag) => flag === 'api-key-read-only' && enabled ) - expect(await renderAccountSettings()).toContain(`read-only keys ${rendered}`) + expect(await readFlagInAccountSettings()).toBe(enabled) }) })