diff --git a/apps/docs/content/docs/cli/knowledge.mdx b/apps/docs/content/docs/cli/knowledge.mdx index 29bad7ed758..b08a06d5396 100644 --- a/apps/docs/content/docs/cli/knowledge.mdx +++ b/apps/docs/content/docs/cli/knowledge.mdx @@ -173,7 +173,7 @@ sim knowledge restore API request and response schemas: [restoreKnowledgeBase](/api-reference/knowledge-bases/restoreKnowledgeBase). -## Search and export +## Search ### Search knowledge @@ -201,6 +201,8 @@ sim knowledge search [options] API request and response schemas: [searchKnowledge](/api-reference/knowledge-bases/searchKnowledge). +## Export and import + ### Export a knowledge base as a .simkb.zip bundle ```bash @@ -231,6 +233,71 @@ sim knowledge export [options] API request and response schemas: [exportKnowledgeBase](/api-reference/knowledge-bases/exportKnowledgeBase). +### Create a knowledge base from an exported .simkb.zip bundle + +```bash +sim knowledge import [options] +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `path` | Yes | Bundle archive written by `sim knowledge export` | + + + +**Options** + + + +| Option | Required | Description | +| --- | --- | --- | +| `--name ` | No | Name for the new knowledge base; defaults to the bundle's own name. | +| `--no-wait` | No | Return once the import is started instead of watching it. | + + + +API request and response schemas: [createKnowledgeImport](/api-reference/knowledge-bases/createKnowledgeImport), [createKnowledgeImportPartUrls](/api-reference/knowledge-bases/createKnowledgeImportPartUrls), [completeKnowledgeImport](/api-reference/knowledge-bases/completeKnowledgeImport), [cancelKnowledgeImport](/api-reference/knowledge-bases/cancelKnowledgeImport), [getKnowledgeImport](/api-reference/knowledge-bases/getKnowledgeImport). + +### Get knowledge base import + +```bash +sim knowledge imports get +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `importId` | Yes | Unique knowledge-base import identifier. | + + + +API request and response schemas: [getKnowledgeImport](/api-reference/knowledge-bases/getKnowledgeImport). + +### Stop a running import + +```bash +sim knowledge imports cancel +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `importId` | Yes | Unique knowledge-base import identifier. | + + + +API request and response schemas: [cancelKnowledgeImport](/api-reference/knowledge-bases/cancelKnowledgeImport). + ## Documents ### List documents diff --git a/apps/docs/content/docs/cli/reference.mdx b/apps/docs/content/docs/cli/reference.mdx index a7ad4a0f55b..5e6b7136d8e 100644 --- a/apps/docs/content/docs/cli/reference.mdx +++ b/apps/docs/content/docs/cli/reference.mdx @@ -2491,6 +2491,46 @@ sim knowledge documents upload [options] API request and response schemas: [createKnowledgeDocumentUpload](/api-reference/knowledge-bases/createKnowledgeDocumentUpload), [createKnowledgeDocumentUploadPartUrls](/api-reference/knowledge-bases/createKnowledgeDocumentUploadPartUrls), [completeKnowledgeDocumentUpload](/api-reference/knowledge-bases/completeKnowledgeDocumentUpload), [abortKnowledgeDocumentUpload](/api-reference/knowledge-bases/abortKnowledgeDocumentUpload). +### sim knowledge imports cancel + +Stop a running import + +```bash +sim knowledge imports cancel +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `importId` | Yes | Unique knowledge-base import identifier. | + + + +API request and response schemas: [cancelKnowledgeImport](/api-reference/knowledge-bases/cancelKnowledgeImport). + +### sim knowledge imports get + +Get knowledge base import + +```bash +sim knowledge imports get +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `importId` | Yes | Unique knowledge-base import identifier. | + + + +API request and response schemas: [getKnowledgeImport](/api-reference/knowledge-bases/getKnowledgeImport). + ### sim knowledge create Create knowledge base @@ -3079,6 +3119,37 @@ sim knowledge export [options] API request and response schemas: [exportKnowledgeBase](/api-reference/knowledge-bases/exportKnowledgeBase). +### sim knowledge import + +Create a knowledge base from an exported .simkb.zip bundle + +```bash +sim knowledge import [options] +``` + +**Arguments** + + + +| Argument | Required | Description | +| --- | --- | --- | +| `path` | Yes | Bundle archive written by `sim knowledge export` | + + + +**Options** + + + +| Option | Required | Description | +| --- | --- | --- | +| `--name ` | No | Name for the new knowledge base; defaults to the bundle's own name. | +| `--no-wait` | No | Return once the import is started instead of watching it. | + + + +API request and response schemas: [createKnowledgeImport](/api-reference/knowledge-bases/createKnowledgeImport), [createKnowledgeImportPartUrls](/api-reference/knowledge-bases/createKnowledgeImportPartUrls), [completeKnowledgeImport](/api-reference/knowledge-bases/completeKnowledgeImport), [cancelKnowledgeImport](/api-reference/knowledge-bases/cancelKnowledgeImport), [getKnowledgeImport](/api-reference/knowledge-bases/getKnowledgeImport). + ### sim knowledge ls List knowledge resources and child folders together diff --git a/apps/docs/content/docs/knowledgebase/export-import.mdx b/apps/docs/content/docs/knowledgebase/export-import.mdx index 0b151f397df..61ad1694ca9 100644 --- a/apps/docs/content/docs/knowledgebase/export-import.mdx +++ b/apps/docs/content/docs/knowledgebase/export-import.mdx @@ -1,9 +1,9 @@ --- -title: Export -description: Download a knowledge base's documents, chunks, tags, and settings in one archive. +title: Export and import +description: Move a knowledge base's documents, chunks, tags, and settings between workspaces and deployments in one archive. --- -Export a knowledge base as a `.simkb.zip` archive. It carries the base's configuration, tag definitions and values, stored document files, and completed chunk text, with vectors included by default. +Export a knowledge base as a `.simkb.zip` archive. It carries the base's configuration, tag definitions and values, stored document files, and completed chunk text, with vectors included by default. Import the archive into any workspace, on this deployment or another, to create a new knowledge base from it. ## Access and scope @@ -34,6 +34,60 @@ sim knowledge export --output-file kb.zip --no-vectors The CLI uses the selected workspace profile. An existing output file requires `--force` to overwrite it. See the [CLI reference](/cli/reference). +## Import an archive + +Importing creates a new knowledge base from a `.simkb.zip` archive. It never changes an existing base. + +### Access + +Import requires workspace write access and both the **Knowledge Base Creation** and **Knowledge Base Uploads** capabilities. OAuth callers need `api:write`; a workspace API key is accepted. + +### CLI + +```bash +sim knowledge import ./kb.simkb.zip +sim knowledge import ./kb.simkb.zip --name "Product Documentation (copy)" +sim knowledge import ./kb.simkb.zip --no-wait +``` + +The new base takes the archive's name unless you pass `--name`. Knowledge base names are unique within a workspace, so importing next to the original needs a new name. The command uploads the archive, waits for the import to finish, and prints the new base's id with how many documents were imported. With `--no-wait` it returns as soon as the import starts. + +To check on or stop an import that is still running: + +```bash +sim knowledge imports get +sim knowledge imports cancel +``` + +### API + +An import is three requests, like other large uploads: + +1. `POST /api/v2/knowledge/imports` with the workspace, an optional `name`, and the archive's file name, type, and size. The response carries the import id, an upload token, and signed transfer instructions. +2. Upload the archive's bytes as instructed. Multipart transfers request part URLs from `POST /api/v2/knowledge/imports/{importId}/parts`. +3. `POST /api/v2/knowledge/imports/{importId}/complete` to start the import. + +Poll `GET /api/v2/knowledge/imports/{importId}?workspaceId={workspaceId}` until `status` is `completed`, `failed`, or `canceled`. See [Create knowledge base import](/api-reference/knowledge-bases/createKnowledgeImport) for the request contracts. + +### What the import creates + +The new base is created at the workspace root with the archive's description, chunking configuration, and tag definitions. Each document keeps its filename, tag values, and enabled flag, and its original file when the archive has one. It is attributed to the person who imported it. + +How a document is indexed depends on the embedding model: + +- **Same model**: when the archive includes vectors from the embedding model and dimensions this deployment uses, documents are indexed directly from the archive's chunks and vectors. Nothing is re-embedded, so nothing is billed for embeddings, and chunk enabled flags are kept. +- **Different model or no vectors**: documents are processed from their original files, exactly as uploads are, and appear in the base as their processing finishes. A document with chunks but no original file is re-embedded from its chunk text instead. + +A document the archive carries only as chunks, such as one from a [connector](/knowledgebase/connectors), is stored as a plain-text file holding its chunk text, so it can still be reprocessed later. + +`documentsImported` counts documents created; re-indexed documents may still be processing when the import completes. Documents that cannot be imported, such as an unsupported file type or a storage limit reached partway through, are skipped and reported in `failures`; the rest of the import continues. + +### Limits + +Archives must be `.zip` files of at most **5 GiB**, and every document file at most **100 MB**. The archive is validated before anything is created, so a damaged or modified archive fails without leaving a partial base. Imports count toward storage and usage limits like uploads do. + +Canceling stops after the document in progress. Documents already imported stay in the new base. Starting an import records one audit event, naming the knowledge base it creates. + ## Archive contents ```text diff --git a/apps/docs/content/docs/knowledgebase/index.mdx b/apps/docs/content/docs/knowledgebase/index.mdx index 048fde441ee..223c31a1825 100644 --- a/apps/docs/content/docs/knowledgebase/index.mdx +++ b/apps/docs/content/docs/knowledgebase/index.mdx @@ -63,4 +63,4 @@ A query search across multiple bases requires the same embedding model and dimen - [Tags and filtering](/knowledgebase/tags) for narrowing a search - [Debugging retrieval](/knowledgebase/debugging-retrieval) for missing or irrelevant results - [Chunking strategies](/knowledgebase/chunking-strategies) for passage sizes and boundaries -- [Export](/knowledgebase/export-import) for downloading documents, chunks, tags, and settings +- [Export and import](/knowledgebase/export-import) for moving documents, chunks, tags, and settings between workspaces and deployments diff --git a/apps/docs/openapi-v2-knowledge.json b/apps/docs/openapi-v2-knowledge.json index 18b8770ecdd..cadd389f3d1 100644 --- a/apps/docs/openapi-v2-knowledge.json +++ b/apps/docs/openapi-v2-knowledge.json @@ -668,12 +668,109 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/connectors": { + "/api/v2/knowledge/imports": { + "post": { + "operationId": "createKnowledgeImport", + "summary": "Create knowledge base import", + "description": "Start importing a knowledge base bundle produced by an export. The response carries signed transfer instructions for the archive; once its bytes are uploaded, complete the import to create the knowledge base. Bundles must be `.zip` archives of at most 5 GiB.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.imports.create", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], + "requestBody": { + "required": true, + "description": "Workspace, bundle archive, and an optional name for the new knowledge base.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateKnowledgeImportRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "name": "Product Documentation", + "source": { + "type": "upload", + "name": "product-documentation.simkb.zip", + "contentType": "application/zip", + "size": 7340032 + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "The created import and its upload instructions.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2CreateKnowledgeImportResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + } + }, + "/api/v2/knowledge/imports/{importId}": { "get": { - "operationId": "listKnowledgeConnectors", - "summary": "List knowledge connectors", - "description": "List external sources connected to a knowledge base with cursor pagination. Stored API keys are never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.connectors.list", + "operationId": "getKnowledgeImport", + "summary": "Get knowledge base import", + "description": "Get an import's progress and outcome. During `uploading`, the signed upload token is required; omitting it returns `404`.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.imports.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ @@ -686,72 +783,35 @@ ], "parameters": [ { - "name": "knowledgeBaseId", + "name": "importId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Unique knowledge-base import identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Unique knowledge-base import identifier." } }, { "name": "workspaceId", "in": "query", "required": true, - "description": "Workspace that owns the knowledge base.", + "description": "Workspace that owns the import.", "schema": { "type": "string", "minLength": 1, "maxLength": 128, - "description": "Workspace that owns the knowledge base." - } - }, - { - "name": "sortBy", - "in": "query", - "required": false, - "description": "Field used to sort the result.", - "schema": { - "default": "createdAt", - "description": "Field used to sort the result.", - "type": "string", - "enum": ["connectorType", "createdAt", "updatedAt"] - } - }, - { - "name": "sortOrder", - "in": "query", - "required": false, - "description": "Sort direction.", - "schema": { - "default": "desc", - "description": "Sort direction.", - "type": "string", - "enum": ["asc", "desc"] - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Maximum connectors to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "schema": { - "default": 50, - "description": "Maximum connectors to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "type": "integer", - "minimum": 1, - "maximum": 100 + "description": "Workspace that owns the import." } }, { - "name": "cursor", - "in": "query", + "name": "upload-token", + "in": "header", "required": false, - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "description": "Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.", "schema": { - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "description": "Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.", "type": "string", "minLength": 1 } @@ -759,7 +819,7 @@ ], "responses": { "200": { - "description": "A page of knowledge connectors.", + "description": "The requested knowledge base import.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -774,36 +834,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorListResponse" - }, - "examples": { - "example1": { - "summary": "Response example 1", - "value": { - "data": [ - { - "id": "kc-9f8e7d6c", - "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", - "connectorType": "notion", - "credentialId": "cred-4b3a2c1d", - "sourceConfig": { - "pageIds": ["page-123"] - }, - "syncMode": "full", - "syncIntervalMinutes": 1440, - "status": "active", - "lastSyncAt": "2026-06-20T14:02:11.000Z", - "lastSyncError": null, - "lastSyncDocCount": 42, - "nextSyncAt": "2026-06-21T14:02:11.000Z", - "consecutiveFailures": 0, - "createdAt": "2026-06-01T09:14:00.000Z", - "updatedAt": "2026-06-20T14:02:11.000Z" - } - ], - "nextCursor": null - } - } + "$ref": "#/components/schemas/V2KnowledgeImportResponse" } } } @@ -831,11 +862,11 @@ } } }, - "post": { - "operationId": "createKnowledgeConnector", - "summary": "Create knowledge connector", - "description": "Validate and connect an external source, then queue its initial synchronization. The `apiKey` field is never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.connectors.create", + "delete": { + "operationId": "cancelKnowledgeImport", + "summary": "Cancel knowledge base import", + "description": "Cancel an import. During its upload the transfer is aborted; while processing, it stops after the document in flight and the documents already imported stay in the new knowledge base. Settled imports return `409`.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.imports.cancel", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -848,45 +879,43 @@ ], "parameters": [ { - "name": "knowledgeBaseId", + "name": "importId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Unique knowledge-base import identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Unique knowledge-base import identifier." } - } - ], - "requestBody": { - "required": true, - "description": "Workspace, connector type, authentication reference, source configuration, and sync schedule.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateKnowledgeConnectorRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "connectorType": "notion", - "credentialId": "cred-4b3a2c1d", - "sourceConfig": { - "pageIds": ["page-123"] - }, - "syncIntervalMinutes": 1440 - } - } - } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the import.", + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the import." + } + }, + { + "name": "upload-token", + "in": "header", + "required": false, + "description": "Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.", + "schema": { + "description": "Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.", + "type": "string", + "minLength": 1 } } - }, + ], "responses": { - "201": { - "description": "The created connector without secret material.", + "200": { + "description": "The canceled knowledge base import.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -901,33 +930,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorResponse" - }, - "examples": { - "example1": { - "summary": "Response example 1", - "value": { - "data": { - "id": "kc-9f8e7d6c", - "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", - "connectorType": "notion", - "credentialId": "cred-4b3a2c1d", - "sourceConfig": { - "pageIds": ["page-123"] - }, - "syncMode": "full", - "syncIntervalMinutes": 1440, - "status": "active", - "lastSyncAt": "2026-06-20T14:02:11.000Z", - "lastSyncError": null, - "lastSyncDocCount": 42, - "nextSyncAt": "2026-06-21T14:02:11.000Z", - "consecutiveFailures": 0, - "createdAt": "2026-06-01T09:14:00.000Z", - "updatedAt": "2026-06-20T14:02:11.000Z" - } - } - } + "$ref": "#/components/schemas/V2CancelKnowledgeImportResponse" } } } @@ -947,12 +950,6 @@ "409": { "$ref": "#/components/responses/Conflict" }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -965,61 +962,80 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}": { - "get": { - "operationId": "getKnowledgeConnector", - "summary": "Get knowledge connector", - "description": "Get one connector and its ten most recent synchronization attempts. Stored API keys are never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.connectors.read", - "x-oauth-scope": "api:read", + "/api/v2/knowledge/imports/{importId}/parts": { + "post": { + "operationId": "createKnowledgeImportPartUrls", + "summary": "Create knowledge base import part URLs", + "description": "Create signed URLs for multipart bundle upload parts. Requires the `uploading` state; other states return `409`.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.imports.parts", + "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:read"] + "oauthBearer": ["api:write"] } ], "parameters": [ { - "name": "connectorId", + "name": "importId", "in": "path", "required": true, - "description": "Connector selected for the operation.", + "description": "Unique knowledge-base import identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Connector selected for the operation." + "description": "Unique knowledge-base import identifier." } }, { - "name": "knowledgeBaseId", - "in": "path", + "name": "workspaceId", + "in": "query", "required": true, - "description": "Knowledge base that owns the connector.", + "description": "Workspace that owns the import.", "schema": { "type": "string", "minLength": 1, - "description": "Knowledge base that owns the connector." + "maxLength": 128, + "description": "Workspace that owns the import." } }, { - "name": "workspaceId", - "in": "query", + "name": "upload-token", + "in": "header", "required": true, - "description": "Workspace that owns the knowledge base.", + "description": "Signed upload control token returned when the upload session was created.", "schema": { "type": "string", "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." + "description": "Signed upload control token returned when the upload session was created." } } ], + "requestBody": { + "required": true, + "description": "Multipart part numbers for which signed URLs should be created.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateKnowledgeImportPartUrlsRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "partNumbers": [1, 2, 3] + } + } + } + } + } + }, "responses": { "200": { - "description": "The connector and recent synchronization history.", + "description": "The signed multipart upload URLs.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1034,34 +1050,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorDetailResponse" - }, - "examples": { - "example1": { - "summary": "Response example 1", - "value": { - "data": { - "id": "kc-9f8e7d6c", - "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", - "connectorType": "notion", - "credentialId": "cred-4b3a2c1d", - "sourceConfig": { - "pageIds": ["page-123"] - }, - "syncMode": "full", - "syncIntervalMinutes": 1440, - "status": "active", - "lastSyncAt": "2026-06-20T14:02:11.000Z", - "lastSyncError": null, - "lastSyncDocCount": 42, - "nextSyncAt": "2026-06-21T14:02:11.000Z", - "consecutiveFailures": 0, - "createdAt": "2026-06-01T09:14:00.000Z", - "updatedAt": "2026-06-20T14:02:11.000Z", - "syncLogs": [] - } - } - } + "$ref": "#/components/schemas/V2CreateKnowledgeImportPartUrlsResponse" } } } @@ -1078,6 +1067,15 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -1088,12 +1086,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "patch": { - "operationId": "updateKnowledgeConnector", - "summary": "Update knowledge connector", - "description": "Update connector source configuration, schedule, or active state. Replacing source configuration on a runnable connector queues an immediate synchronization; paused connectors retain the change without synchronizing until resumed. Source configuration cannot be replaced while synchronization is already in progress. Authentication material cannot be changed through this operation. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.connectors.update", + } + }, + "/api/v2/knowledge/imports/{importId}/complete": { + "post": { + "operationId": "completeKnowledgeImport", + "summary": "Complete knowledge base import upload", + "description": "Verify the uploaded bundle and start creating the knowledge base under the same import ID. Vectors are reused when the bundle was embedded with this deployment's model; otherwise documents are re-indexed. Completion records an audit event. Repeating it returns the running import.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.imports.complete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -1106,51 +1106,43 @@ ], "parameters": [ { - "name": "connectorId", + "name": "importId", "in": "path", "required": true, - "description": "Connector selected for the operation.", + "description": "Unique knowledge-base import identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Connector selected for the operation." + "description": "Unique knowledge-base import identifier." } }, { - "name": "knowledgeBaseId", - "in": "path", + "name": "workspaceId", + "in": "query", "required": true, - "description": "Knowledge base that owns the connector.", + "description": "Workspace that owns the import.", "schema": { "type": "string", "minLength": 1, - "description": "Knowledge base that owns the connector." + "maxLength": 128, + "description": "Workspace that owns the import." } - } - ], - "requestBody": { - "required": true, - "description": "Workspace scope and at least one mutable connector field.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeConnectorRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "status": "paused" - } - } - } + }, + { + "name": "upload-token", + "in": "header", + "required": true, + "description": "Signed upload control token returned when the upload session was created.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Signed upload control token returned when the upload session was created." } } - }, + ], "responses": { "200": { - "description": "The updated connector.", + "description": "The knowledge base import after its upload completed.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1165,33 +1157,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeConnectorResponse" - }, - "examples": { - "example1": { - "summary": "Response example 1", - "value": { - "data": { - "id": "kc-9f8e7d6c", - "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", - "connectorType": "notion", - "credentialId": "cred-4b3a2c1d", - "sourceConfig": { - "pageIds": ["page-123"] - }, - "syncMode": "full", - "syncIntervalMinutes": 1440, - "status": "paused", - "lastSyncAt": "2026-06-20T14:02:11.000Z", - "lastSyncError": null, - "lastSyncDocCount": 42, - "nextSyncAt": "2026-06-21T14:02:11.000Z", - "consecutiveFailures": 0, - "createdAt": "2026-06-01T09:14:00.000Z", - "updatedAt": "2026-06-20T14:03:00.000Z" - } - } - } + "$ref": "#/components/schemas/V2CompleteKnowledgeImportResponse" } } } @@ -1202,6 +1168,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, "403": { "$ref": "#/components/responses/Forbidden" }, @@ -1211,12 +1180,6 @@ "409": { "$ref": "#/components/responses/Conflict" }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -1227,43 +1190,34 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "delete": { - "operationId": "deleteKnowledgeConnector", - "summary": "Delete knowledge connector", - "description": "Delete a connector and optionally its synchronized documents. Documents are retained by default. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.connectors.delete", - "x-oauth-scope": "api:write", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/connectors": { + "get": { + "operationId": "listKnowledgeConnectors", + "summary": "List knowledge connectors", + "description": "List external sources connected to a knowledge base with cursor pagination. Stored API keys are never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.connectors.list", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], "parameters": [ - { - "name": "connectorId", - "in": "path", - "required": true, - "description": "Connector selected for the operation.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Connector selected for the operation." - } - }, { "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Knowledge base that owns the connector.", + "description": "Unique knowledge base identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Knowledge base that owns the connector." + "description": "Unique knowledge base identifier." } }, { @@ -1279,19 +1233,57 @@ } }, { - "name": "deleteDocuments", + "name": "sortBy", "in": "query", "required": false, - "description": "Also permanently delete documents produced by this connector.", + "description": "Field used to sort the result.", "schema": { - "description": "Also permanently delete documents produced by this connector.", - "type": "boolean" + "default": "createdAt", + "description": "Field used to sort the result.", + "type": "string", + "enum": ["connectorType", "createdAt", "updatedAt"] + } + }, + { + "name": "sortOrder", + "in": "query", + "required": false, + "description": "Sort direction.", + "schema": { + "default": "desc", + "description": "Sort direction.", + "type": "string", + "enum": ["asc", "desc"] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum connectors to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "schema": { + "default": 50, + "description": "Maximum connectors to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "type": "integer", + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "schema": { + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "type": "string", + "minLength": 1 } } ], "responses": { "200": { - "description": "Connector deletion acknowledgement and document counts.", + "description": "A page of knowledge connectors.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1306,18 +1298,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorDeleteResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorListResponse" }, "examples": { "example1": { "summary": "Response example 1", "value": { - "data": { - "id": "kc-9f8e7d6c", - "deleted": true, - "documentsDeleted": 0, - "documentsKept": 42 - } + "data": [ + { + "id": "kc-9f8e7d6c", + "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", + "connectorType": "notion", + "credentialId": "cred-4b3a2c1d", + "sourceConfig": { + "pageIds": ["page-123"] + }, + "syncMode": "full", + "syncIntervalMinutes": 1440, + "status": "active", + "lastSyncAt": "2026-06-20T14:02:11.000Z", + "lastSyncError": null, + "lastSyncDocCount": 42, + "nextSyncAt": "2026-06-21T14:02:11.000Z", + "consecutiveFailures": 0, + "createdAt": "2026-06-01T09:14:00.000Z", + "updatedAt": "2026-06-20T14:02:11.000Z" + } + ], + "nextCursor": null } } } @@ -1346,14 +1354,12 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}/sync": { + }, "post": { - "operationId": "syncKnowledgeConnector", - "summary": "Sync knowledge connector", - "description": "Queue a connector synchronization. Rehydration forces existing documents to be fetched and indexed again. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.connectors.sync", + "operationId": "createKnowledgeConnector", + "summary": "Create knowledge connector", + "description": "Validate and connect an external source, then queue its initial synchronization. The `apiKey` field is never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.connectors.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -1365,43 +1371,37 @@ } ], "parameters": [ - { - "name": "connectorId", - "in": "path", - "required": true, - "description": "Connector selected for the operation.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Connector selected for the operation." - } - }, { "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Knowledge base that owns the connector.", + "description": "Unique knowledge base identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Knowledge base that owns the connector." + "description": "Unique knowledge base identifier." } } ], "requestBody": { "required": true, - "description": "Workspace scope and optional full rehydration control.", + "description": "Workspace, connector type, authentication reference, source configuration, and sync schedule.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SyncKnowledgeConnectorRequest" + "$ref": "#/components/schemas/CreateKnowledgeConnectorRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "rehydrate": false + "connectorType": "notion", + "credentialId": "cred-4b3a2c1d", + "sourceConfig": { + "pageIds": ["page-123"] + }, + "syncIntervalMinutes": 1440 } } } @@ -1409,8 +1409,8 @@ } }, "responses": { - "200": { - "description": "Synchronization was queued.", + "201": { + "description": "The created connector without secret material.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1425,7 +1425,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorSyncResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorResponse" }, "examples": { "example1": { @@ -1433,7 +1433,22 @@ "value": { "data": { "id": "kc-9f8e7d6c", - "syncTriggered": true + "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", + "connectorType": "notion", + "credentialId": "cred-4b3a2c1d", + "sourceConfig": { + "pageIds": ["page-123"] + }, + "syncMode": "full", + "syncIntervalMinutes": 1440, + "status": "active", + "lastSyncAt": "2026-06-20T14:02:11.000Z", + "lastSyncError": null, + "lastSyncDocCount": 42, + "nextSyncAt": "2026-06-21T14:02:11.000Z", + "consecutiveFailures": 0, + "createdAt": "2026-06-01T09:14:00.000Z", + "updatedAt": "2026-06-20T14:02:11.000Z" } } } @@ -1474,12 +1489,12 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}/documents": { + "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}": { "get": { - "operationId": "listKnowledgeConnectorDocuments", - "summary": "List knowledge connector documents", - "description": "List documents produced by one connector with opaque cursor pagination. Excluded documents are omitted unless explicitly requested. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.connectors.documents.list", + "operationId": "getKnowledgeConnector", + "summary": "Get knowledge connector", + "description": "Get one connector and its ten most recent synchronization attempts. Stored API keys are never returned. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.connectors.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ @@ -1524,45 +1539,11 @@ "maxLength": 128, "description": "Workspace that owns the knowledge base." } - }, - { - "name": "includeExcluded", - "in": "query", - "required": false, - "description": "Include documents explicitly excluded by a user.", - "schema": { - "description": "Include documents explicitly excluded by a user.", - "type": "boolean" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Maximum connector documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "schema": { - "default": 50, - "description": "Maximum connector documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "type": "integer", - "minimum": 1, - "maximum": 100 - } - }, - { - "name": "cursor", - "in": "query", - "required": false, - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "schema": { - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "type": "string", - "minLength": 1 - } } ], "responses": { "200": { - "description": "A page of connector documents.", + "description": "The connector and recent synchronization history.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1577,25 +1558,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorDocumentListResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorDetailResponse" }, "examples": { "example1": { "summary": "Response example 1", "value": { - "data": [ - { - "id": "doc-8a7b6c5d", - "filename": "Product requirements", - "externalId": "page-123", - "sourceUrl": "https://www.notion.so/page-123", - "enabled": true, - "userExcluded": false, - "createdAt": "2026-06-01T09:15:00.000Z", - "processingStatus": "completed" - } - ], - "nextCursor": null + "data": { + "id": "kc-9f8e7d6c", + "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", + "connectorType": "notion", + "credentialId": "cred-4b3a2c1d", + "sourceConfig": { + "pageIds": ["page-123"] + }, + "syncMode": "full", + "syncIntervalMinutes": 1440, + "status": "active", + "lastSyncAt": "2026-06-20T14:02:11.000Z", + "lastSyncError": null, + "lastSyncDocCount": 42, + "nextSyncAt": "2026-06-21T14:02:11.000Z", + "consecutiveFailures": 0, + "createdAt": "2026-06-01T09:14:00.000Z", + "updatedAt": "2026-06-20T14:02:11.000Z", + "syncLogs": [] + } } } } @@ -1626,10 +1614,10 @@ } }, "patch": { - "operationId": "updateKnowledgeConnectorDocuments", - "summary": "Update knowledge connector documents", - "description": "Exclude connector documents from knowledge search or restore previously excluded documents. Only documents produced by the selected connector can change. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.connectors.documents.update", + "operationId": "updateKnowledgeConnector", + "summary": "Update knowledge connector", + "description": "Update connector source configuration, schedule, or active state. Replacing source configuration on a runnable connector queues an immediate synchronization; paused connectors retain the change without synchronizing until resumed. Source configuration cannot be replaced while synchronization is already in progress. Authentication material cannot be changed through this operation. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.connectors.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -1666,19 +1654,18 @@ ], "requestBody": { "required": true, - "description": "Workspace, restore or exclude operation, and selected document identifiers.", + "description": "Workspace scope and at least one mutable connector field.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeConnectorDocumentsRequest" + "$ref": "#/components/schemas/UpdateKnowledgeConnectorRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "operation": "exclude", - "documentIds": ["doc-8a7b6c5d"] + "status": "paused" } } } @@ -1687,7 +1674,7 @@ }, "responses": { "200": { - "description": "The selected connector documents were updated.", + "description": "The updated connector.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1702,16 +1689,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeConnectorDocumentsUpdateResponse" + "$ref": "#/components/schemas/UpdateKnowledgeConnectorResponse" }, "examples": { "example1": { "summary": "Response example 1", "value": { "data": { - "operation": "exclude", - "updatedCount": 1, - "documentIds": ["doc-8a7b6c5d"] + "id": "kc-9f8e7d6c", + "knowledgeBaseId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", + "connectorType": "notion", + "credentialId": "cred-4b3a2c1d", + "sourceConfig": { + "pageIds": ["page-123"] + }, + "syncMode": "full", + "syncIntervalMinutes": 1440, + "status": "paused", + "lastSyncAt": "2026-06-20T14:02:11.000Z", + "lastSyncError": null, + "lastSyncDocCount": 42, + "nextSyncAt": "2026-06-21T14:02:11.000Z", + "consecutiveFailures": 0, + "createdAt": "2026-06-01T09:14:00.000Z", + "updatedAt": "2026-06-20T14:03:00.000Z" } } } @@ -1731,6 +1732,9 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -1747,130 +1751,43 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/search": { - "post": { - "operationId": "searchKnowledge", - "summary": "Search knowledge", - "description": "Search one or more knowledge bases with semantic vector retrieval, optional hybrid full-text retrieval, and structured tag filters. Every result names the `knowledgeBaseId` it came from. A request body over 2 MiB is a `413`. Reranking returns `409` when the stored results cannot pass secret-provenance enforcement.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.search", - "x-oauth-scope": "api:read", + }, + "delete": { + "operationId": "deleteKnowledgeConnector", + "summary": "Delete knowledge connector", + "description": "Delete a connector and optionally its synchronized documents. Documents are retained by default. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.connectors.delete", + "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:read"] + "oauthBearer": ["api:write"] } ], - "requestBody": { - "required": true, - "description": "Knowledge bases, query, result limit, retrieval mode, and optional tag filters.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SearchKnowledgeRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "knowledgeBaseIds": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"], - "query": "How do I reset my password?", - "topK": 10 - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Matching document chunks ordered by relevance.", - "headers": { - "X-RateLimit-Limit": { - "$ref": "#/components/headers/X-RateLimit-Limit" - }, - "X-RateLimit-Remaining": { - "$ref": "#/components/headers/X-RateLimit-Remaining" - }, - "X-RateLimit-Reset": { - "$ref": "#/components/headers/X-RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2KnowledgeSearchResponse" - } - } - } - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "402": { - "$ref": "#/components/responses/UsageLimitExceeded" - }, - "403": { - "$ref": "#/components/responses/Forbidden" - }, - "404": { - "$ref": "#/components/responses/NotFound" - }, - "409": { - "$ref": "#/components/responses/Conflict" - }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, - "429": { - "$ref": "#/components/responses/RateLimited" - }, - "500": { - "$ref": "#/components/responses/InternalError" - }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable" - } - } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/tags": { - "get": { - "operationId": "listKnowledgeTags", - "summary": "List tags", - "description": "List the knowledge base's tag definitions with display names, write slots, and field types. Filters and document reads use display names; document writes use slots. Returns one page; `nextCursor` is always null.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.tags.list", - "x-oauth-scope": "api:read", - "tags": ["Knowledge Bases"], - "security": [ + "parameters": [ { - "apiKey": [] + "name": "connectorId", + "in": "path", + "required": true, + "description": "Connector selected for the operation.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Connector selected for the operation." + } }, - { - "oauthBearer": ["api:read"] - } - ], - "parameters": [ { "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Knowledge base that owns the connector.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Knowledge base that owns the connector." } }, { @@ -1881,13 +1798,24 @@ "schema": { "type": "string", "minLength": 1, + "maxLength": 128, "description": "Workspace that owns the knowledge base." } + }, + { + "name": "deleteDocuments", + "in": "query", + "required": false, + "description": "Also permanently delete documents produced by this connector.", + "schema": { + "description": "Also permanently delete documents produced by this connector.", + "type": "boolean" + } } ], "responses": { "200": { - "description": "The knowledge base tag vocabulary.", + "description": "Connector deletion acknowledgement and document counts.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1902,7 +1830,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeTagListResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorDeleteResponse" + }, + "examples": { + "example1": { + "summary": "Response example 1", + "value": { + "data": { + "id": "kc-9f8e7d6c", + "deleted": true, + "documentsDeleted": 0, + "documentsKept": 42 + } + } + } } } } @@ -1929,12 +1870,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}/sync": { "post": { - "operationId": "createKnowledgeTag", - "summary": "Create tag", - "description": "Create a tag definition. Write document values by `tagSlot` and filter by `displayName`. Omitting `tagSlot` selects a free slot; exhaustion returns `400`. An occupied slot or duplicate name returns `409`. Use Bulk save tag definitions for multiple definitions. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.tags.create", + "operationId": "syncKnowledgeConnector", + "summary": "Sync knowledge connector", + "description": "Queue a connector synchronization. Rehydration forces existing documents to be fetched and indexed again. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.connectors.sync", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -1946,33 +1889,43 @@ } ], "parameters": [ + { + "name": "connectorId", + "in": "path", + "required": true, + "description": "Connector selected for the operation.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Connector selected for the operation." + } + }, { "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Knowledge base that owns the connector.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Knowledge base that owns the connector." } } ], "requestBody": { "required": true, - "description": "Workspace scope, display name, field type, and optional slot.", + "description": "Workspace scope and optional full rehydration control.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateKnowledgeTagRequest" + "$ref": "#/components/schemas/SyncKnowledgeConnectorRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "displayName": "category", - "fieldType": "text" + "rehydrate": false } } } @@ -1980,8 +1933,8 @@ } }, "responses": { - "201": { - "description": "The created tag definition.", + "200": { + "description": "Synchronization was queued.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -1996,7 +1949,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeTagResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorSyncResponse" + }, + "examples": { + "example1": { + "summary": "Response example 1", + "value": { + "data": { + "id": "kc-9f8e7d6c", + "syncTriggered": true + } + } + } } } } @@ -2032,55 +1996,213 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "put": { - "operationId": "bulkSaveKnowledgeTagDefinitions", - "summary": "Bulk save tag definitions", - "description": "Create or update tag definitions, preserving unspecified slots. Updates require `originalDisplayName`; other entries create tags. Slot and name conflicts appear in per-definition `errors` with HTTP `200`, leaving conflicting values unchanged. Use Update document to set tag values. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.tags.bulk_save", - "x-oauth-scope": "api:write", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/connectors/{connectorId}/documents": { + "get": { + "operationId": "listKnowledgeConnectorDocuments", + "summary": "List knowledge connector documents", + "description": "List documents produced by one connector with opaque cursor pagination. Excluded documents are omitted unless explicitly requested. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.connectors.documents.list", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], "parameters": [ + { + "name": "connectorId", + "in": "path", + "required": true, + "description": "Connector selected for the operation.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Connector selected for the operation." + } + }, { "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Knowledge base that owns the connector.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Knowledge base that owns the connector." + } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + }, + { + "name": "includeExcluded", + "in": "query", + "required": false, + "description": "Include documents explicitly excluded by a user.", + "schema": { + "description": "Include documents explicitly excluded by a user.", + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum connector documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "schema": { + "default": 50, + "description": "Maximum connector documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "type": "integer", + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "schema": { + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "type": "string", + "minLength": 1 } } ], - "requestBody": { - "required": true, - "description": "Workspace scope and the tag definitions to create or update.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BulkSaveKnowledgeTagDefinitionsRequest" + "responses": { + "200": { + "description": "A page of connector documents.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" }, - "examples": { - "example1": { + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeConnectorDocumentListResponse" + }, + "examples": { + "example1": { + "summary": "Response example 1", + "value": { + "data": [ + { + "id": "doc-8a7b6c5d", + "filename": "Product requirements", + "externalId": "page-123", + "sourceUrl": "https://www.notion.so/page-123", + "enabled": true, + "userExcluded": false, + "createdAt": "2026-06-01T09:15:00.000Z", + "processingStatus": "completed" + } + ], + "nextCursor": null + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + }, + "patch": { + "operationId": "updateKnowledgeConnectorDocuments", + "summary": "Update knowledge connector documents", + "description": "Exclude connector documents from knowledge search or restore previously excluded documents. Only documents produced by the selected connector can change. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.connectors.documents.update", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], + "parameters": [ + { + "name": "connectorId", + "in": "path", + "required": true, + "description": "Connector selected for the operation.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Connector selected for the operation." + } + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Knowledge base that owns the connector.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Knowledge base that owns the connector." + } + } + ], + "requestBody": { + "required": true, + "description": "Workspace, restore or exclude operation, and selected document identifiers.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateKnowledgeConnectorDocumentsRequest" + }, + "examples": { + "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "definitions": [ - { - "tagSlot": "tag1", - "displayName": "category", - "fieldType": "text" - } - ] + "operation": "exclude", + "documentIds": ["doc-8a7b6c5d"] } } } @@ -2089,7 +2211,7 @@ }, "responses": { "200": { - "description": "Definitions created and updated by the save.", + "description": "The selected connector documents were updated.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2104,7 +2226,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2BulkSaveKnowledgeTagDefinitionsResponse" + "$ref": "#/components/schemas/V2KnowledgeConnectorDocumentsUpdateResponse" + }, + "examples": { + "example1": { + "summary": "Response example 1", + "value": { + "data": { + "operation": "exclude", + "updatedCount": 1, + "documentIds": ["doc-8a7b6c5d"] + } + } + } } } } @@ -2137,60 +2271,49 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "delete": { - "operationId": "deleteKnowledgeTagDefinitions", - "summary": "Delete tag definitions", - "description": "Delete unused tag definitions by default. With `unused=false`, permanently delete all definitions and their values from documents and chunks. Use Delete tag to remove one definition. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.tags.cleanup", - "x-oauth-scope": "api:write", + } + }, + "/api/v2/knowledge/search": { + "post": { + "operationId": "searchKnowledge", + "summary": "Search knowledge", + "description": "Search one or more knowledge bases with semantic vector retrieval, optional hybrid full-text retrieval, and structured tag filters. Every result names the `knowledgeBaseId` it came from. A request body over 2 MiB is a `413`. Reranking returns `409` when the stored results cannot pass secret-provenance enforcement.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.search", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], - "parameters": [ - { - "name": "knowledgeBaseId", - "in": "path", - "required": true, - "description": "Unique knowledge base identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge base identifier." - } - }, - { - "name": "workspaceId", - "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", - "schema": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." - } - }, - { - "name": "unused", - "in": "query", - "required": false, - "description": "Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass `unused=false` to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable.", - "schema": { - "description": "Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass `unused=false` to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable.", - "type": "boolean" + "requestBody": { + "required": true, + "description": "Knowledge bases, query, result limit, retrieval mode, and optional tag filters.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SearchKnowledgeRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "knowledgeBaseIds": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"], + "query": "How do I reset my password?", + "topK": 10 + } + } + } } } - ], + }, "responses": { "200": { - "description": "Number of tag definitions removed.", + "description": "Matching document chunks ordered by relevance.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2205,7 +2328,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2DeleteKnowledgeTagDefinitionsResponse" + "$ref": "#/components/schemas/V2KnowledgeSearchResponse" } } } @@ -2216,12 +2339,24 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -2234,12 +2369,12 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/documents": { + "/api/v2/knowledge/{knowledgeBaseId}/tags": { "get": { - "operationId": "listKnowledgeDocuments", - "summary": "List documents", - "description": "List documents with filename search, state and tag filters, sorting, and cursor pagination. Tag values use display names; use List tags to resolve the slots required for writes.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.documents.list", + "operationId": "listKnowledgeTags", + "summary": "List tags", + "description": "List the knowledge base's tag definitions with display names, write slots, and field types. Filters and document reads use display names; document writes use slots. Returns one page; `nextCursor` is always null.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.tags.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ @@ -2272,104 +2407,105 @@ "minLength": 1, "description": "Workspace that owns the knowledge base." } + } + ], + "responses": { + "200": { + "description": "The knowledge base tag vocabulary.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeTagListResponse" + } + } + } }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Maximum documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "schema": { - "default": 50, - "description": "Maximum documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "type": "integer", - "minimum": 1, - "maximum": 100 - } + "400": { + "$ref": "#/components/responses/BadRequest" }, - { - "name": "search", - "in": "query", - "required": false, - "description": "Case-insensitive substring match against the document filename.", - "schema": { - "description": "Case-insensitive substring match against the document filename.", - "type": "string", - "minLength": 1, - "maxLength": 200 - } + "401": { + "$ref": "#/components/responses/Unauthorized" }, - { - "name": "enabledFilter", - "in": "query", - "required": false, - "description": "Filter by whether documents are enabled for search.", - "schema": { - "default": "all", - "description": "Filter by whether documents are enabled for search.", - "type": "string", - "enum": ["all", "enabled", "disabled"] - } + "403": { + "$ref": "#/components/responses/Forbidden" }, - { - "name": "sortBy", - "in": "query", - "required": false, - "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `filename`.", - "schema": { - "default": "uploadedAt", - "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `filename`.", - "type": "string", - "enum": [ - "filename", - "fileSize", - "tokenCount", - "chunkCount", - "uploadedAt", - "processingStatus", - "enabled" - ] - } + "404": { + "$ref": "#/components/responses/NotFound" }, - { - "name": "sortOrder", - "in": "query", - "required": false, - "description": "Sort direction.", - "schema": { - "default": "desc", - "description": "Sort direction.", - "type": "string", - "enum": ["asc", "desc"] - } + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + }, + "post": { + "operationId": "createKnowledgeTag", + "summary": "Create tag", + "description": "Create a tag definition. Write document values by `tagSlot` and filter by `displayName`. Omitting `tagSlot` selects a free slot; exhaustion returns `400`. An occupied slot or duplicate name returns `409`. Use Bulk save tag definitions for multiple definitions. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.tags.create", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ { - "name": "cursor", - "in": "query", - "required": false, - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "schema": { - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "type": "string", - "minLength": 1 - } + "apiKey": [] }, { - "name": "tagFilters", - "in": "query", - "required": false, - "description": "A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored.", + "oauthBearer": ["api:write"] + } + ], + "parameters": [ + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", "schema": { - "description": "A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored.", - "examples": [ - "[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]" - ], - "type": "string" + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." } } ], + "requestBody": { + "required": true, + "description": "Workspace scope, display name, field type, and optional slot.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateKnowledgeTagRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "displayName": "category", + "fieldType": "text" + } + } + } + } + } + }, "responses": { - "200": { - "description": "A page of knowledge documents.", + "201": { + "description": "The created tag definition.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2384,7 +2520,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentListResponse" + "$ref": "#/components/schemas/V2KnowledgeTagResponse" } } } @@ -2401,6 +2537,15 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -2412,11 +2557,11 @@ } } }, - "patch": { - "operationId": "bulkUpdateKnowledgeDocuments", - "summary": "Bulk enable or disable documents", - "description": "Enable or disable selected documents, or use `selectAll` for the entire knowledge base. Use Delete document to remove documents individually. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.bulk", + "put": { + "operationId": "bulkSaveKnowledgeTagDefinitions", + "summary": "Bulk save tag definitions", + "description": "Create or update tag definitions, preserving unspecified slots. Updates require `originalDisplayName`; other entries create tags. Slot and name conflicts appear in per-definition `errors` with HTTP `200`, leaving conflicting values unchanged. Use Update document to set tag values. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.tags.bulk_save", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -2442,19 +2587,24 @@ ], "requestBody": { "required": true, - "description": "Operation and the documents it applies to.", + "description": "Workspace scope and the tag definitions to create or update.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BulkUpdateKnowledgeDocumentsRequest" + "$ref": "#/components/schemas/BulkSaveKnowledgeTagDefinitionsRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "operation": "disable", - "documentIds": ["b2d4f8a0-1c3e-4a5b-9d7c-2e6f0a8b4c12"] + "definitions": [ + { + "tagSlot": "tag1", + "displayName": "category", + "fieldType": "text" + } + ] } } } @@ -2463,7 +2613,7 @@ }, "responses": { "200": { - "description": "The number and identifiers of the documents that changed.", + "description": "Definitions created and updated by the save.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2478,7 +2628,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2BulkKnowledgeDocumentsResponse" + "$ref": "#/components/schemas/V2BulkSaveKnowledgeTagDefinitionsResponse" } } } @@ -2512,11 +2662,11 @@ } } }, - "post": { - "operationId": "uploadKnowledgeDocument", - "summary": "Upload document", - "description": "Upload one document as multipart form data. Processing continues asynchronously after the document is accepted.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.upload", + "delete": { + "operationId": "deleteKnowledgeTagDefinitions", + "summary": "Delete tag definitions", + "description": "Delete unused tag definitions by default. With `unused=false`, permanently delete all definitions and their values from documents and chunks. Use Delete tag to remove one definition. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.tags.cleanup", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -2550,22 +2700,21 @@ "maxLength": 128, "description": "Workspace that owns the knowledge base." } - } - ], - "requestBody": { - "required": true, - "description": "Multipart form containing the document file.", - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/UploadKnowledgeDocumentForm" - } + }, + { + "name": "unused", + "in": "query", + "required": false, + "description": "Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass `unused=false` to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable.", + "schema": { + "description": "Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass `unused=false` to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable.", + "type": "boolean" } } - }, + ], "responses": { - "201": { - "description": "The accepted document queued for processing.", + "200": { + "description": "Number of tag definitions removed.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2580,7 +2729,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentSummaryResponse" + "$ref": "#/components/schemas/V2DeleteKnowledgeTagDefinitionsResponse" } } } @@ -2591,21 +2740,12 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, - "402": { - "$ref": "#/components/responses/UsageLimitExceeded" - }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -2618,20 +2758,20 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads": { - "post": { - "operationId": "createKnowledgeDocumentUpload", - "summary": "Create document upload", - "description": "Create a resumable upload session and receive direct PUT or multipart transfer instructions.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.upload.create", - "x-oauth-scope": "api:write", + "/api/v2/knowledge/{knowledgeBaseId}/documents": { + "get": { + "operationId": "listKnowledgeDocuments", + "summary": "List documents", + "description": "List documents with filename search, state and tag filters, sorting, and cursor pagination. Tag values use display names; use List tags to resolve the slots required for writes.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.documents.list", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], "parameters": [ @@ -2645,151 +2785,115 @@ "minLength": 1, "description": "Unique knowledge base identifier." } - } - ], - "requestBody": { - "required": true, - "description": "Document metadata used to authorize and initialize the upload.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateKnowledgeDocumentUploadRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "name": "getting-started.pdf", - "contentType": "application/pdf", - "size": 248913 - } - } - } - } - } - }, - "responses": { - "201": { - "description": "The created upload session and transfer instructions.", - "headers": { - "X-RateLimit-Limit": { - "$ref": "#/components/headers/X-RateLimit-Limit" - }, - "X-RateLimit-Remaining": { - "$ref": "#/components/headers/X-RateLimit-Remaining" - }, - "X-RateLimit-Reset": { - "$ref": "#/components/headers/X-RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2CreateKnowledgeDocumentUploadResponse" - } - } - } - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "402": { - "$ref": "#/components/responses/UsageLimitExceeded" - }, - "403": { - "$ref": "#/components/responses/Forbidden" - }, - "404": { - "$ref": "#/components/responses/NotFound" - }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, - "429": { - "$ref": "#/components/responses/RateLimited" - }, - "500": { - "$ref": "#/components/responses/InternalError" }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable" - } - } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}": { - "delete": { - "operationId": "abortKnowledgeDocumentUpload", - "summary": "Abort document upload", - "description": "Abort an incomplete upload session and discard its uploaded data. Completed uploads cannot be aborted.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.upload.cancel", - "x-oauth-scope": "api:write", - "tags": ["Knowledge Bases"], - "security": [ { - "apiKey": [] + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Workspace that owns the knowledge base." + } }, { - "oauthBearer": ["api:write"] - } - ], - "parameters": [ + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "schema": { + "default": 50, + "description": "Maximum documents to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "type": "integer", + "minimum": 1, + "maximum": 100 + } + }, { - "name": "knowledgeBaseId", - "in": "path", - "required": true, - "description": "Unique knowledge base identifier.", + "name": "search", + "in": "query", + "required": false, + "description": "Case-insensitive substring match against the document filename.", "schema": { + "description": "Case-insensitive substring match against the document filename.", "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "maxLength": 200 } }, { - "name": "uploadId", - "in": "path", - "required": true, - "description": "Upload session identifier returned when the upload was created.", + "name": "enabledFilter", + "in": "query", + "required": false, + "description": "Filter by whether documents are enabled for search.", "schema": { + "default": "all", + "description": "Filter by whether documents are enabled for search.", "type": "string", - "minLength": 1, - "description": "Upload session identifier returned when the upload was created." + "enum": ["all", "enabled", "disabled"] } }, { - "name": "workspaceId", + "name": "sortBy", "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", + "required": false, + "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `filename`.", "schema": { + "default": "uploadedAt", + "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `filename`.", "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." + "enum": [ + "filename", + "fileSize", + "tokenCount", + "chunkCount", + "uploadedAt", + "processingStatus", + "enabled" + ] } }, { - "name": "upload-token", - "in": "header", - "required": true, - "description": "Signed upload control token returned when the upload session was created.", + "name": "sortOrder", + "in": "query", + "required": false, + "description": "Sort direction.", "schema": { + "default": "desc", + "description": "Sort direction.", "type": "string", - "minLength": 1, - "description": "Signed upload control token returned when the upload session was created." + "enum": ["asc", "desc"] + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "schema": { + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "type": "string", + "minLength": 1 + } + }, + { + "name": "tagFilters", + "in": "query", + "required": false, + "description": "A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored.", + "schema": { + "description": "A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored.", + "examples": [ + "[{\"tagName\":\"category\",\"operator\":\"eq\",\"value\":\"billing\"}]" + ], + "type": "string" } } ], "responses": { "200": { - "description": "The aborted upload session.", + "description": "A page of knowledge documents.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2804,7 +2908,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentUploadResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentListResponse" } } } @@ -2821,9 +2925,6 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -2834,14 +2935,12 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}/parts": { - "post": { - "operationId": "createKnowledgeDocumentUploadPartUrls", - "summary": "Create document upload part URLs", - "description": "Create short-lived signed PUT URLs for up to 100 multipart part numbers.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.upload.parts", + }, + "patch": { + "operationId": "bulkUpdateKnowledgeDocuments", + "summary": "Bulk enable or disable documents", + "description": "Enable or disable selected documents, or use `selectAll` for the entire knowledge base. Use Delete document to remove documents individually. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.bulk", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -2863,55 +2962,23 @@ "minLength": 1, "description": "Unique knowledge base identifier." } - }, - { - "name": "uploadId", - "in": "path", - "required": true, - "description": "Upload session identifier returned when the upload was created.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Upload session identifier returned when the upload was created." - } - }, - { - "name": "workspaceId", - "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", - "schema": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." - } - }, - { - "name": "upload-token", - "in": "header", - "required": true, - "description": "Signed upload control token returned when the upload session was created.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Signed upload control token returned when the upload session was created." - } } ], "requestBody": { "required": true, - "description": "Multipart part numbers for which signed URLs should be created.", + "description": "Operation and the documents it applies to.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateKnowledgeDocumentUploadPartUrlsRequest" + "$ref": "#/components/schemas/BulkUpdateKnowledgeDocumentsRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { - "partNumbers": [1, 2, 3] + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "operation": "disable", + "documentIds": ["b2d4f8a0-1c3e-4a5b-9d7c-2e6f0a8b4c12"] } } } @@ -2920,7 +2987,7 @@ }, "responses": { "200": { - "description": "Signed URLs for the requested upload parts.", + "description": "The number and identifiers of the documents that changed.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -2935,7 +3002,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentUploadPartUrlsResponse" + "$ref": "#/components/schemas/V2BulkKnowledgeDocumentsResponse" } } } @@ -2952,9 +3019,6 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -2971,14 +3035,12 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}/complete": { + }, "post": { - "operationId": "completeKnowledgeDocumentUpload", - "summary": "Complete document upload", - "description": "Verify a direct upload or assemble multipart parts, create the knowledge document, and queue asynchronous processing.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.upload.complete", + "operationId": "uploadKnowledgeDocument", + "summary": "Upload document", + "description": "Upload one document as multipart form data. Processing continues asynchronously after the document is accepted.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.upload", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -3001,17 +3063,6 @@ "description": "Unique knowledge base identifier." } }, - { - "name": "uploadId", - "in": "path", - "required": true, - "description": "Upload session identifier returned when the upload was created.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Upload session identifier returned when the upload was created." - } - }, { "name": "workspaceId", "in": "query", @@ -3023,122 +3074,22 @@ "maxLength": 128, "description": "Workspace that owns the knowledge base." } - }, - { - "name": "upload-token", - "in": "header", - "required": true, - "description": "Signed upload control token returned when the upload session was created.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Signed upload control token returned when the upload session was created." - } } ], - "responses": { - "200": { - "description": "The completed upload and queued document.", - "headers": { - "X-RateLimit-Limit": { - "$ref": "#/components/headers/X-RateLimit-Limit" - }, - "X-RateLimit-Remaining": { - "$ref": "#/components/headers/X-RateLimit-Remaining" - }, - "X-RateLimit-Reset": { - "$ref": "#/components/headers/X-RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentUploadResponse" - } + "requestBody": { + "required": true, + "description": "Multipart form containing the document file.", + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/UploadKnowledgeDocumentForm" } } - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "403": { - "$ref": "#/components/responses/Forbidden" - }, - "404": { - "$ref": "#/components/responses/NotFound" - }, - "409": { - "$ref": "#/components/responses/Conflict" - }, - "429": { - "$ref": "#/components/responses/RateLimited" - }, - "500": { - "$ref": "#/components/responses/InternalError" - }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable" - } - } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}": { - "get": { - "operationId": "getKnowledgeDocument", - "summary": "Get document", - "description": "Get document metadata, processing status, and source connector details.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.documents.read", - "x-oauth-scope": "api:read", - "tags": ["Knowledge Bases"], - "security": [ - { - "apiKey": [] - }, - { - "oauthBearer": ["api:read"] - } - ], - "parameters": [ - { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "knowledgeBaseId", - "in": "path", - "required": true, - "description": "Unique knowledge base identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge base identifier." - } - }, - { - "name": "workspaceId", - "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Workspace that owns the knowledge base." - } } - ], + }, "responses": { - "200": { - "description": "The requested knowledge document.", + "201": { + "description": "The accepted document queued for processing.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3153,7 +3104,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDocumentResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentSummaryResponse" } } } @@ -3164,12 +3115,21 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -3180,12 +3140,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "patch": { - "operationId": "updateKnowledgeDocument", - "summary": "Update document", - "description": "Rename a document, change search availability, update tag slots, or requeue processing. Omitted fields remain unchanged; indexing state is read-only. Use List tags to resolve names to slots and Get document for source connector details, which this response omits. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.update", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads": { + "post": { + "operationId": "createKnowledgeDocumentUpload", + "summary": "Create document upload", + "description": "Create a resumable upload session and receive direct PUT or multipart transfer instructions.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.upload.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -3197,17 +3159,6 @@ } ], "parameters": [ - { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, { "name": "knowledgeBaseId", "in": "path", @@ -3222,19 +3173,20 @@ ], "requestBody": { "required": true, - "description": "Filename, search state, tag slot values, or a processing retry.", + "description": "Document metadata used to authorize and initialize the upload.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeDocumentRequest" + "$ref": "#/components/schemas/CreateKnowledgeDocumentUploadRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "enabled": false, - "tag1": "billing" + "name": "getting-started.pdf", + "contentType": "application/pdf", + "size": 248913 } } } @@ -3242,8 +3194,8 @@ } }, "responses": { - "200": { - "description": "The updated document, or the requeue acknowledgement.", + "201": { + "description": "The created upload session and transfer instructions.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3258,7 +3210,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2UpdateKnowledgeDocumentResponse" + "$ref": "#/components/schemas/V2CreateKnowledgeDocumentUploadResponse" } } } @@ -3269,6 +3221,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, "403": { "$ref": "#/components/responses/Forbidden" }, @@ -3291,12 +3246,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}": { "delete": { - "operationId": "deleteKnowledgeDocument", - "summary": "Delete document", - "description": "Remove a document from listings and search. Uploaded documents and their chunks are deleted. Connector documents are excluded while retaining their stored data; later synchronization does not re-add them.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.delete", + "operationId": "abortKnowledgeDocumentUpload", + "summary": "Abort document upload", + "description": "Abort an incomplete upload session and discard its uploaded data. Completed uploads cannot be aborted.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.upload.cancel", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -3309,25 +3266,25 @@ ], "parameters": [ { - "name": "documentId", + "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Unique knowledge document identifier.", + "description": "Unique knowledge base identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge document identifier." + "description": "Unique knowledge base identifier." } }, { - "name": "knowledgeBaseId", + "name": "uploadId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Upload session identifier returned when the upload was created.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Upload session identifier returned when the upload was created." } }, { @@ -3338,13 +3295,25 @@ "schema": { "type": "string", "minLength": 1, + "maxLength": 128, "description": "Workspace that owns the knowledge base." } + }, + { + "name": "upload-token", + "in": "header", + "required": true, + "description": "Signed upload control token returned when the upload session was created.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Signed upload control token returned when the upload session was created." + } } ], "responses": { "200": { - "description": "Knowledge document deletion acknowledgement.", + "description": "The aborted upload session.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3359,7 +3328,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDeleteResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentUploadResponse" } } } @@ -3376,6 +3345,9 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -3388,85 +3360,91 @@ } } }, - "/api/v2/knowledge/folders": { - "get": { - "operationId": "listKnowledgeFolders", - "summary": "List folders", - "description": "List folders in the knowledge-base folder tree with filtering and sorting. Returns one page; `nextCursor` is always null. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.folders.list", - "x-oauth-scope": "api:read", + "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}/parts": { + "post": { + "operationId": "createKnowledgeDocumentUploadPartUrls", + "summary": "Create document upload part URLs", + "description": "Create short-lived signed PUT URLs for up to 100 multipart part numbers.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.upload.parts", + "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:read"] + "oauthBearer": ["api:write"] } ], "parameters": [ { - "name": "workspaceId", - "in": "query", + "name": "knowledgeBaseId", + "in": "path", "required": true, - "description": "Workspace whose folders should be listed.", + "description": "Unique knowledge base identifier.", "schema": { "type": "string", "minLength": 1, - "maxLength": 128, - "description": "Workspace whose folders should be listed." - } - }, - { - "name": "parentPath", - "in": "query", - "required": false, - "description": "Restrict results to direct children of this parent path. Unknown folder paths contribute no matches.", - "schema": { - "description": "Restrict results to direct children of this parent path. Unknown folder paths contribute no matches.", - "$ref": "#/components/schemas/FolderPathInput" + "description": "Unique knowledge base identifier." } }, { - "name": "search", - "in": "query", - "required": false, - "description": "Case-insensitive substring match against the folder name.", + "name": "uploadId", + "in": "path", + "required": true, + "description": "Upload session identifier returned when the upload was created.", "schema": { - "description": "Case-insensitive substring match against the folder name.", "type": "string", "minLength": 1, - "maxLength": 200 + "description": "Upload session identifier returned when the upload was created." } }, { - "name": "sortBy", + "name": "workspaceId", "in": "query", - "required": false, - "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `name`.", + "required": true, + "description": "Workspace that owns the knowledge base.", "schema": { - "default": "name", - "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `name`.", "type": "string", - "enum": ["name", "createdAt", "updatedAt"] + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." } }, { - "name": "sortOrder", - "in": "query", - "required": false, - "description": "Sort direction.", + "name": "upload-token", + "in": "header", + "required": true, + "description": "Signed upload control token returned when the upload session was created.", "schema": { - "default": "asc", - "description": "Sort direction.", "type": "string", - "enum": ["asc", "desc"] + "minLength": 1, + "description": "Signed upload control token returned when the upload session was created." } } ], + "requestBody": { + "required": true, + "description": "Multipart part numbers for which signed URLs should be created.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateKnowledgeDocumentUploadPartUrlsRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "partNumbers": [1, 2, 3] + } + } + } + } + } + }, "responses": { "200": { - "description": "A page of knowledge-base folders.", + "description": "Signed URLs for the requested upload parts.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3481,7 +3459,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeFolderListResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentUploadPartUrlsResponse" } } } @@ -3498,9 +3476,15 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -3511,12 +3495,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/uploads/{uploadId}/complete": { "post": { - "operationId": "createKnowledgeFolder", - "summary": "Create folder", - "description": "Create a folder in the knowledge-base folder tree. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.folders.create", + "operationId": "completeKnowledgeDocumentUpload", + "summary": "Complete document upload", + "description": "Verify a direct upload or assemble multipart parts, create the knowledge document, and queue asynchronous processing.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.upload.complete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -3527,29 +3513,56 @@ "oauthBearer": ["api:write"] } ], - "requestBody": { - "required": true, - "description": "Workspace and canonical path for a new knowledge-base folder.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateKnowledgeFolderRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "path": "/Product" - } - } - } + "parameters": [ + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." + } + }, + { + "name": "uploadId", + "in": "path", + "required": true, + "description": "Upload session identifier returned when the upload was created.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Upload session identifier returned when the upload was created." + } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + }, + { + "name": "upload-token", + "in": "header", + "required": true, + "description": "Signed upload control token returned when the upload session was created.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Signed upload control token returned when the upload session was created." } } - }, + ], "responses": { - "201": { - "description": "The created knowledge-base folder.", + "200": { + "description": "The completed upload and queued document.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3564,7 +3577,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeFolderResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentUploadResponse" } } } @@ -3584,12 +3597,6 @@ "409": { "$ref": "#/components/responses/Conflict" }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -3600,46 +3607,62 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "patch": { - "operationId": "relocateKnowledgeFolder", - "summary": "Rename or move folder", - "description": "Rename or move a folder and atomically rewrite descendant paths. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.folders.relocate", - "x-oauth-scope": "api:write", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}": { + "get": { + "operationId": "getKnowledgeDocument", + "summary": "Get document", + "description": "Get document metadata, processing status, and source connector details.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.documents.read", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], - "requestBody": { - "required": true, - "description": "Current and destination canonical paths for a knowledge-base folder.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RelocateKnowledgeFolderRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "path": "/Product", - "destinationPath": "/Archive/Product" - } - } - } + "parameters": [ + { + "name": "documentId", + "in": "path", + "required": true, + "description": "Unique knowledge document identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge document identifier." + } + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." + } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Workspace that owns the knowledge base." } } - }, + ], "responses": { "200": { - "description": "The relocated knowledge-base folder.", + "description": "The requested knowledge document.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3654,7 +3677,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeFolderResponse" + "$ref": "#/components/schemas/V2KnowledgeDocumentResponse" } } } @@ -3671,15 +3694,6 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -3691,14 +3705,14 @@ } } }, - "delete": { - "operationId": "deleteKnowledgeFolder", - "summary": "Delete folder", - "description": "Archive an empty folder, or set `recursive=true` to archive its subfolders and knowledge bases. Use Restore knowledge base to recover knowledge bases.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.folders.delete", - "x-oauth-scope": "api:write", - "tags": ["Knowledge Bases"], - "security": [ + "patch": { + "operationId": "updateKnowledgeDocument", + "summary": "Update document", + "description": "Rename a document, change search availability, update tag slots, or requeue processing. Omitted fields remain unchanged; indexing state is read-only. Use List tags to resolve names to slots and Get document for source connector details, which this response omits. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.update", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ { "apiKey": [] }, @@ -3708,122 +3722,16 @@ ], "parameters": [ { - "name": "workspaceId", - "in": "query", + "name": "documentId", + "in": "path", "required": true, - "description": "Workspace containing the folder.", + "description": "Unique knowledge document identifier.", "schema": { "type": "string", "minLength": 1, - "maxLength": 128, - "description": "Workspace containing the folder." - } - }, - { - "name": "path", - "in": "query", - "required": true, - "description": "Path of the folder to delete.", - "schema": { - "description": "Path of the folder to delete.", - "$ref": "#/components/schemas/NonRootFolderPathInput" - } - }, - { - "name": "recursive", - "in": "query", - "required": false, - "description": "Delete the folder's contents and nested folders too. Required for a non-empty folder. Only the listed case-sensitive spellings are accepted.", - "schema": { - "description": "Delete the folder's contents and nested folders too. Required for a non-empty folder. Only the listed case-sensitive spellings are accepted.", - "enum": [ - "true", - "1", - "yes", - "on", - "y", - "enabled", - "false", - "0", - "no", - "off", - "n", - "disabled" - ], - "default": "false", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Folder deletion acknowledgement and deleted item counts.", - "headers": { - "X-RateLimit-Limit": { - "$ref": "#/components/headers/X-RateLimit-Limit" - }, - "X-RateLimit-Remaining": { - "$ref": "#/components/headers/X-RateLimit-Remaining" - }, - "X-RateLimit-Reset": { - "$ref": "#/components/headers/X-RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2DeleteKnowledgeFolderResponse" - } - } + "description": "Unique knowledge document identifier." } }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "403": { - "$ref": "#/components/responses/Forbidden" - }, - "404": { - "$ref": "#/components/responses/NotFound" - }, - "409": { - "$ref": "#/components/responses/Conflict" - }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "429": { - "$ref": "#/components/responses/RateLimited" - }, - "500": { - "$ref": "#/components/responses/InternalError" - }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable" - } - } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/restore": { - "post": { - "operationId": "restoreKnowledgeBase", - "summary": "Restore knowledge base", - "description": "Restore a knowledge base and the documents and connectors archived with it. Active knowledge bases return unchanged without a new audit event. An archived workspace returns `409`; an archived containing folder moves the restored knowledge base to the workspace root. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.restore", - "x-oauth-scope": "api:write", - "tags": ["Knowledge Bases"], - "security": [ - { - "apiKey": [] - }, - { - "oauthBearer": ["api:write"] - } - ], - "parameters": [ { "name": "knowledgeBaseId", "in": "path", @@ -3838,17 +3746,19 @@ ], "requestBody": { "required": true, - "description": "Workspace scope for the knowledge base.", + "description": "Filename, search state, tag slot values, or a processing retry.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RestoreKnowledgeBaseRequest" + "$ref": "#/components/schemas/UpdateKnowledgeDocumentRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64" + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "enabled": false, + "tag1": "billing" } } } @@ -3857,7 +3767,7 @@ }, "responses": { "200": { - "description": "The restored knowledge base.", + "description": "The updated document, or the requeue acknowledgement.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3872,7 +3782,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeBaseResponse" + "$ref": "#/components/schemas/V2UpdateKnowledgeDocumentResponse" } } } @@ -3889,9 +3799,6 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -3908,14 +3815,12 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/from-workspace-files": { - "post": { - "operationId": "addWorkspaceFilesToKnowledgeBase", - "summary": "Index workspace files", - "description": "Queue stored workspace files for indexing without re-uploading bytes. Unreadable, unsupported, or over-100 MiB files appear in `failed`; valid files are queued. Partial success returns `200`. Use Get document to poll processing after receiving document IDs. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.documents.add_workspace_files", + }, + "delete": { + "operationId": "deleteKnowledgeDocument", + "summary": "Delete document", + "description": "Remove a document from listings and search. Uploaded documents and their chunks are deleted. Connector documents are excluded while retaining their stored data; later synchronization does not re-add them.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -3927,6 +3832,17 @@ } ], "parameters": [ + { + "name": "documentId", + "in": "path", + "required": true, + "description": "Unique knowledge document identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge document identifier." + } + }, { "name": "knowledgeBaseId", "in": "path", @@ -3937,31 +3853,22 @@ "minLength": 1, "description": "Unique knowledge base identifier." } - } - ], - "requestBody": { - "required": true, - "description": "Workspace scope and the workspace file references to index.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddWorkspaceFilesToKnowledgeBaseRequest" - }, - "examples": { - "example1": { - "summary": "Request example 1", - "value": { - "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "fileReferences": ["handbook.pdf"] - } - } - } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Workspace that owns the knowledge base." } } - }, + ], "responses": { "200": { - "description": "Files queued for indexing, with any that could not be.", + "description": "Knowledge document deletion acknowledgement.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -3976,7 +3883,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2AddWorkspaceFilesToKnowledgeBaseResponse" + "$ref": "#/components/schemas/V2KnowledgeDeleteResponse" } } } @@ -3987,21 +3894,12 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, - "402": { - "$ref": "#/components/responses/UsageLimitExceeded" - }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, - "413": { - "$ref": "#/components/responses/PayloadTooLarge" - }, - "415": { - "$ref": "#/components/responses/UnsupportedMediaType" - }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -4014,12 +3912,12 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}/chunks": { + "/api/v2/knowledge/folders": { "get": { - "operationId": "listKnowledgeChunks", - "summary": "List chunks", - "description": "List document chunks with content search, enabled filtering, sorting, and cursor pagination. Tags use slots; use List tags to resolve display names. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.chunks.list", + "operationId": "listKnowledgeFolders", + "summary": "List folders", + "description": "List folders in the knowledge-base folder tree with filtering and sorting. Returns one page; `nextCursor` is always null. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.folders.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ @@ -4032,73 +3930,49 @@ ], "parameters": [ { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "knowledgeBaseId", - "in": "path", + "name": "workspaceId", + "in": "query", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Workspace whose folders should be listed.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "maxLength": 128, + "description": "Workspace whose folders should be listed." } }, { - "name": "workspaceId", + "name": "parentPath", "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", + "required": false, + "description": "Restrict results to direct children of this parent path. Unknown folder paths contribute no matches.", "schema": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." + "description": "Restrict results to direct children of this parent path. Unknown folder paths contribute no matches.", + "$ref": "#/components/schemas/FolderPathInput" } }, { "name": "search", "in": "query", "required": false, - "description": "Case-insensitive substring match against chunk content.", + "description": "Case-insensitive substring match against the folder name.", "schema": { - "description": "Case-insensitive substring match against chunk content.", + "description": "Case-insensitive substring match against the folder name.", "type": "string", "minLength": 1, "maxLength": 200 } }, { - "name": "enabled", + "name": "sortBy", "in": "query", "required": false, - "description": "Restrict to enabled or disabled chunks. `all` returns both.", + "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `name`.", "schema": { - "default": "all", - "description": "Restrict to enabled or disabled chunks. `all` returns both.", - "type": "string", - "enum": ["true", "false", "all"] - } - }, - { - "name": "sortBy", - "in": "query", - "required": false, - "description": "Field used to sort the result.", - "schema": { - "default": "chunkIndex", - "description": "Field used to sort the result.", + "default": "name", + "description": "Field used to sort the result. Do not rely on case-insensitive ordering when sorting by `name`.", "type": "string", - "enum": ["chunkIndex", "tokenCount", "enabled"] + "enum": ["name", "createdAt", "updatedAt"] } }, { @@ -4112,35 +3986,11 @@ "type": "string", "enum": ["asc", "desc"] } - }, - { - "name": "limit", - "in": "query", - "required": false, - "description": "Maximum chunks to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "schema": { - "default": 50, - "description": "Maximum chunks to return per page. Must be a whole number from 1 to 100. Defaults to 50.", - "type": "integer", - "minimum": 1, - "maximum": 100 - } - }, - { - "name": "cursor", - "in": "query", - "required": false, - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "schema": { - "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", - "type": "string", - "minLength": 1 - } } ], "responses": { "200": { - "description": "A page of document chunks.", + "description": "A page of knowledge-base folders.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4155,7 +4005,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeChunkListResponse" + "$ref": "#/components/schemas/V2KnowledgeFolderListResponse" } } } @@ -4172,8 +4022,8 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" + "413": { + "$ref": "#/components/responses/PayloadTooLarge" }, "429": { "$ref": "#/components/responses/RateLimited" @@ -4187,10 +4037,10 @@ } }, "post": { - "operationId": "createKnowledgeChunk", - "summary": "Create chunk", - "description": "Append a chunk and embed it before returning. It inherits the document's tags and next `chunkIndex`. Search includes it when the chunk and document are enabled and the document has completed processing. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.chunks.create", + "operationId": "createKnowledgeFolder", + "summary": "Create folder", + "description": "Create a folder in the knowledge-base folder tree. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.folders.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -4201,44 +4051,20 @@ "oauthBearer": ["api:write"] } ], - "parameters": [ - { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "knowledgeBaseId", - "in": "path", - "required": true, - "description": "Unique knowledge base identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge base identifier." - } - } - ], "requestBody": { "required": true, - "description": "Workspace scope and the text to embed.", + "description": "Workspace and canonical path for a new knowledge-base folder.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateKnowledgeChunkRequest" + "$ref": "#/components/schemas/CreateKnowledgeFolderRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "content": "To reset your password, open Settings and choose Security." + "path": "/Product" } } } @@ -4247,7 +4073,7 @@ }, "responses": { "201": { - "description": "The created chunk.", + "description": "The created knowledge-base folder.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4262,7 +4088,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeChunkResponse" + "$ref": "#/components/schemas/V2KnowledgeFolderResponse" } } } @@ -4279,6 +4105,9 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -4297,10 +4126,10 @@ } }, "patch": { - "operationId": "bulkUpdateKnowledgeChunks", - "summary": "Bulk update chunks", - "description": "Enable, disable, or delete multiple chunks in one best-effort request. Unknown chunk IDs appear in `errors` without failing the request; `processed` counts matched chunks, not changes. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.chunks.bulk", + "operationId": "relocateKnowledgeFolder", + "summary": "Rename or move folder", + "description": "Rename or move a folder and atomically rewrite descendant paths. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.folders.relocate", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -4311,45 +4140,21 @@ "oauthBearer": ["api:write"] } ], - "parameters": [ - { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "knowledgeBaseId", - "in": "path", - "required": true, - "description": "Unique knowledge base identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge base identifier." - } - } - ], "requestBody": { "required": true, - "description": "Workspace scope, the operation to apply, and the chunks to apply it to.", + "description": "Current and destination canonical paths for a knowledge-base folder.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BulkUpdateKnowledgeChunksRequest" + "$ref": "#/components/schemas/RelocateKnowledgeFolderRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "operation": "disable", - "chunkIds": ["4c1f9e77-2b3a-4f8d-9e10-6a2c8d4b1e05"] + "path": "/Product", + "destinationPath": "/Archive/Product" } } } @@ -4358,7 +4163,7 @@ }, "responses": { "200": { - "description": "Outcome of the bulk chunk operation.", + "description": "The relocated knowledge-base folder.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4373,7 +4178,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2BulkKnowledgeChunksResponse" + "$ref": "#/components/schemas/V2KnowledgeFolderResponse" } } } @@ -4390,6 +4195,9 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -4406,74 +4214,74 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}/chunks/{chunkId}": { - "get": { - "operationId": "getKnowledgeChunk", - "summary": "Get chunk", - "description": "Get one chunk of a document, including the exact text that was embedded. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.chunks.read", - "x-oauth-scope": "api:read", + }, + "delete": { + "operationId": "deleteKnowledgeFolder", + "summary": "Delete folder", + "description": "Archive an empty folder, or set `recursive=true` to archive its subfolders and knowledge bases. Use Restore knowledge base to recover knowledge bases.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.folders.delete", + "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:read"] + "oauthBearer": ["api:write"] } ], "parameters": [ { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "chunkId", - "in": "path", + "name": "workspaceId", + "in": "query", "required": true, - "description": "Unique chunk identifier.", + "description": "Workspace containing the folder.", "schema": { "type": "string", "minLength": 1, - "description": "Unique chunk identifier." + "maxLength": 128, + "description": "Workspace containing the folder." } }, { - "name": "knowledgeBaseId", - "in": "path", + "name": "path", + "in": "query", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Path of the folder to delete.", "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Path of the folder to delete.", + "$ref": "#/components/schemas/NonRootFolderPathInput" } }, { - "name": "workspaceId", + "name": "recursive", "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", + "required": false, + "description": "Delete the folder's contents and nested folders too. Required for a non-empty folder. Only the listed case-sensitive spellings are accepted.", "schema": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." + "description": "Delete the folder's contents and nested folders too. Required for a non-empty folder. Only the listed case-sensitive spellings are accepted.", + "enum": [ + "true", + "1", + "yes", + "on", + "y", + "enabled", + "false", + "0", + "no", + "off", + "n", + "disabled" + ], + "default": "false", + "type": "string" } } ], "responses": { "200": { - "description": "The requested chunk.", + "description": "Folder deletion acknowledgement and deleted item counts.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4488,7 +4296,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeChunkResponse" + "$ref": "#/components/schemas/V2DeleteKnowledgeFolderResponse" } } } @@ -4508,6 +4316,9 @@ "409": { "$ref": "#/components/responses/Conflict" }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -4518,12 +4329,14 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "patch": { - "operationId": "updateKnowledgeChunk", - "summary": "Update chunk", - "description": "Correct chunk text or disable it from search. Changing `content` re-embeds immediately and recalculates document token and character counts; disabling retains the index. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.chunks.update", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/restore": { + "post": { + "operationId": "restoreKnowledgeBase", + "summary": "Restore knowledge base", + "description": "Restore a knowledge base and the documents and connectors archived with it. Active knowledge bases return unchanged without a new audit event. An archived workspace returns `409`; an archived containing folder moves the restored knowledge base to the workspace root. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.restore", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -4536,27 +4349,108 @@ ], "parameters": [ { - "name": "documentId", - "in": "path", - "required": true, - "description": "Unique knowledge document identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique knowledge document identifier." - } - }, - { - "name": "chunkId", + "name": "knowledgeBaseId", "in": "path", "required": true, - "description": "Unique chunk identifier.", + "description": "Unique knowledge base identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique chunk identifier." + "description": "Unique knowledge base identifier." } + } + ], + "requestBody": { + "required": true, + "description": "Workspace scope for the knowledge base.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RestoreKnowledgeBaseRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "The restored knowledge base.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeBaseResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/from-workspace-files": { + "post": { + "operationId": "addWorkspaceFilesToKnowledgeBase", + "summary": "Index workspace files", + "description": "Queue stored workspace files for indexing without re-uploading bytes. Unreadable, unsupported, or over-100 MiB files appear in `failed`; valid files are queued. Partial success returns `200`. Use Get document to poll processing after receiving document IDs. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.documents.add_workspace_files", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] }, + { + "oauthBearer": ["api:write"] + } + ], + "parameters": [ { "name": "knowledgeBaseId", "in": "path", @@ -4571,18 +4465,18 @@ ], "requestBody": { "required": true, - "description": "Workspace scope and the fields to update. At least one is required.", + "description": "Workspace scope and the workspace file references to index.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeChunkRequest" + "$ref": "#/components/schemas/AddWorkspaceFilesToKnowledgeBaseRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "enabled": false + "fileReferences": ["handbook.pdf"] } } } @@ -4591,7 +4485,7 @@ }, "responses": { "200": { - "description": "The updated chunk.", + "description": "Files queued for indexing, with any that could not be.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4606,7 +4500,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeChunkResponse" + "$ref": "#/components/schemas/V2AddWorkspaceFilesToKnowledgeBaseResponse" } } } @@ -4617,15 +4511,15 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "402": { + "$ref": "#/components/responses/UsageLimitExceeded" + }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -4642,20 +4536,22 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "delete": { - "operationId": "deleteKnowledgeChunk", - "summary": "Delete chunk", - "description": "Permanently remove one chunk and subtract it from document counts. Remaining `chunkIndex` values stay stable and may become non-contiguous. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.chunks.delete", - "x-oauth-scope": "api:write", + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}/chunks": { + "get": { + "operationId": "listKnowledgeChunks", + "summary": "List chunks", + "description": "List document chunks with content search, enabled filtering, sorting, and cursor pagination. Tags use slots; use List tags to resolve display names. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.chunks.list", + "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:write"] + "oauthBearer": ["api:read"] } ], "parameters": [ @@ -4670,17 +4566,6 @@ "description": "Unique knowledge document identifier." } }, - { - "name": "chunkId", - "in": "path", - "required": true, - "description": "Unique chunk identifier.", - "schema": { - "type": "string", - "minLength": 1, - "description": "Unique chunk identifier." - } - }, { "name": "knowledgeBaseId", "in": "path", @@ -4703,11 +4588,83 @@ "maxLength": 128, "description": "Workspace that owns the knowledge base." } + }, + { + "name": "search", + "in": "query", + "required": false, + "description": "Case-insensitive substring match against chunk content.", + "schema": { + "description": "Case-insensitive substring match against chunk content.", + "type": "string", + "minLength": 1, + "maxLength": 200 + } + }, + { + "name": "enabled", + "in": "query", + "required": false, + "description": "Restrict to enabled or disabled chunks. `all` returns both.", + "schema": { + "default": "all", + "description": "Restrict to enabled or disabled chunks. `all` returns both.", + "type": "string", + "enum": ["true", "false", "all"] + } + }, + { + "name": "sortBy", + "in": "query", + "required": false, + "description": "Field used to sort the result.", + "schema": { + "default": "chunkIndex", + "description": "Field used to sort the result.", + "type": "string", + "enum": ["chunkIndex", "tokenCount", "enabled"] + } + }, + { + "name": "sortOrder", + "in": "query", + "required": false, + "description": "Sort direction.", + "schema": { + "default": "asc", + "description": "Sort direction.", + "type": "string", + "enum": ["asc", "desc"] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum chunks to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "schema": { + "default": 50, + "description": "Maximum chunks to return per page. Must be a whole number from 1 to 100. Defaults to 50.", + "type": "integer", + "minimum": 1, + "maximum": 100 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "schema": { + "description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.", + "type": "string", + "minLength": 1 + } } ], "responses": { "200": { - "description": "Chunk deletion acknowledgement.", + "description": "A page of document chunks.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4722,7 +4679,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeDeleteResponse" + "$ref": "#/components/schemas/V2KnowledgeChunkListResponse" } } } @@ -4752,14 +4709,12 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/tags/{tagId}": { - "patch": { - "operationId": "updateKnowledgeTag", - "summary": "Update tag", - "description": "Rename a tag or change its slot-compatible `fieldType`. Renaming changes read and filter names without moving the slot or its values. Slots are fixed for a tag's lifetime; an incompatible type returns `400` and requires creating a new tag. A duplicate display name returns `409`. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.tags.update", + }, + "post": { + "operationId": "createKnowledgeChunk", + "summary": "Create chunk", + "description": "Append a chunk and embed it before returning. It inherits the document's tags and next `chunkIndex`. Search includes it when the chunk and document are enabled and the document has completed processing. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.chunks.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ @@ -4772,14 +4727,14 @@ ], "parameters": [ { - "name": "tagId", + "name": "documentId", "in": "path", "required": true, - "description": "Unique tag definition identifier.", + "description": "Unique knowledge document identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique tag definition identifier." + "description": "Unique knowledge document identifier." } }, { @@ -4796,18 +4751,18 @@ ], "requestBody": { "required": true, - "description": "Workspace scope and the fields to update. At least one is required.", + "description": "Workspace scope and the text to embed.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeTagRequest" + "$ref": "#/components/schemas/CreateKnowledgeChunkRequest" }, "examples": { "example1": { "summary": "Request example 1", "value": { "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", - "displayName": "topic" + "content": "To reset your password, open Settings and choose Security." } } } @@ -4815,8 +4770,8 @@ } }, "responses": { - "200": { - "description": "The updated tag definition.", + "201": { + "description": "The created chunk.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4831,7 +4786,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeTagResponse" + "$ref": "#/components/schemas/V2KnowledgeChunkResponse" } } } @@ -4848,9 +4803,6 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" - }, "413": { "$ref": "#/components/responses/PayloadTooLarge" }, @@ -4868,14 +4820,14 @@ } } }, - "delete": { - "operationId": "deleteKnowledgeTag", - "summary": "Delete tag", - "description": "Permanently delete a tag definition and its values from every document and chunk in the knowledge base. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", - "x-sim-operation": "knowledge.tags.delete", - "x-oauth-scope": "api:write", - "tags": ["Knowledge Bases"], - "security": [ + "patch": { + "operationId": "bulkUpdateKnowledgeChunks", + "summary": "Bulk update chunks", + "description": "Enable, disable, or delete multiple chunks in one best-effort request. Unknown chunk IDs appear in `errors` without failing the request; `processed` counts matched chunks, not changes. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.chunks.bulk", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ { "apiKey": [] }, @@ -4885,14 +4837,14 @@ ], "parameters": [ { - "name": "tagId", + "name": "documentId", "in": "path", "required": true, - "description": "Unique tag definition identifier.", + "description": "Unique knowledge document identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique tag definition identifier." + "description": "Unique knowledge document identifier." } }, { @@ -4905,23 +4857,32 @@ "minLength": 1, "description": "Unique knowledge base identifier." } - }, - { - "name": "workspaceId", - "in": "query", - "required": true, - "description": "Workspace that owns the knowledge base.", - "schema": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." - } } ], + "requestBody": { + "required": true, + "description": "Workspace scope, the operation to apply, and the chunks to apply it to.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkUpdateKnowledgeChunksRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "operation": "disable", + "chunkIds": ["4c1f9e77-2b3a-4f8d-9e10-6a2c8d4b1e05"] + } + } + } + } + } + }, "responses": { "200": { - "description": "Tag deletion acknowledgement.", + "description": "Outcome of the bulk chunk operation.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -4936,7 +4897,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2DeleteKnowledgeTagResponse" + "$ref": "#/components/schemas/V2BulkKnowledgeChunksResponse" } } } @@ -4953,8 +4914,11 @@ "404": { "$ref": "#/components/responses/NotFound" }, - "409": { - "$ref": "#/components/responses/Conflict" + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" }, "429": { "$ref": "#/components/responses/RateLimited" @@ -4968,12 +4932,12 @@ } } }, - "/api/v2/knowledge/{knowledgeBaseId}/tags/next-slot": { + "/api/v2/knowledge/{knowledgeBaseId}/documents/{documentId}/chunks/{chunkId}": { "get": { - "operationId": "getNextKnowledgeTagSlot", - "summary": "Get next tag slot", - "description": "Get the next available slot and remaining capacity for a field type. This does not reserve a slot. Create tag selects a free slot when `tagSlot` is omitted. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.tags.read_next_slot", + "operationId": "getKnowledgeChunk", + "summary": "Get chunk", + "description": "Get one chunk of a document, including the exact text that was embedded. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.chunks.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], "security": [ @@ -4985,6 +4949,28 @@ } ], "parameters": [ + { + "name": "documentId", + "in": "path", + "required": true, + "description": "Unique knowledge document identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge document identifier." + } + }, + { + "name": "chunkId", + "in": "path", + "required": true, + "description": "Unique chunk identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique chunk identifier." + } + }, { "name": "knowledgeBaseId", "in": "path", @@ -5007,23 +4993,11 @@ "maxLength": 128, "description": "Workspace that owns the knowledge base." } - }, - { - "name": "fieldType", - "in": "query", - "required": true, - "description": "Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3.", - "schema": { - "type": "string", - "enum": ["text", "number", "date", "boolean"], - "description": "Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3.", - "examples": ["text"] - } } ], "responses": { "200": { - "description": "Slot availability for the requested field type.", + "description": "The requested chunk.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -5038,7 +5012,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2NextKnowledgeTagSlotResponse" + "$ref": "#/components/schemas/V2KnowledgeChunkResponse" } } } @@ -5055,6 +5029,9 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -5065,52 +5042,80 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - }, - "/api/v2/knowledge/{knowledgeBaseId}/tags/usage": { - "get": { - "operationId": "listKnowledgeTagUsage", - "summary": "List tag usage", - "description": "Count the documents and chunks with a value for each defined tag. Returns one page; `nextCursor` is always null. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", - "x-sim-operation": "knowledge.tags.read_usage", - "x-oauth-scope": "api:read", + }, + "patch": { + "operationId": "updateKnowledgeChunk", + "summary": "Update chunk", + "description": "Correct chunk text or disable it from search. Changing `content` re-embeds immediately and recalculates document token and character counts; disabling retains the index. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.chunks.update", + "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], "security": [ { "apiKey": [] }, { - "oauthBearer": ["api:read"] + "oauthBearer": ["api:write"] } ], "parameters": [ { - "name": "knowledgeBaseId", + "name": "documentId", "in": "path", "required": true, - "description": "Unique knowledge base identifier.", + "description": "Unique knowledge document identifier.", "schema": { "type": "string", "minLength": 1, - "description": "Unique knowledge base identifier." + "description": "Unique knowledge document identifier." } }, { - "name": "workspaceId", - "in": "query", + "name": "chunkId", + "in": "path", "required": true, - "description": "Workspace that owns the knowledge base.", + "description": "Unique chunk identifier.", "schema": { "type": "string", "minLength": 1, - "maxLength": 128, - "description": "Workspace that owns the knowledge base." + "description": "Unique chunk identifier." + } + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." } } ], + "requestBody": { + "required": true, + "description": "Workspace scope and the fields to update. At least one is required.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateKnowledgeChunkRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "enabled": false + } + } + } + } + } + }, "responses": { "200": { - "description": "Usage counts for every defined tag.", + "description": "The updated chunk.", "headers": { "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" @@ -5125,7 +5130,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/V2KnowledgeTagUsageListResponse" + "$ref": "#/components/schemas/V2KnowledgeChunkResponse" } } } @@ -5142,6 +5147,15 @@ "404": { "$ref": "#/components/responses/NotFound" }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, "429": { "$ref": "#/components/responses/RateLimited" }, @@ -5152,417 +5166,1276 @@ "$ref": "#/components/responses/ServiceUnavailable" } } - } - } - }, - "components": { - "securitySchemes": { - "apiKey": { - "type": "apiKey", - "in": "header", - "name": "X-API-Key", - "description": "Send a personal or workspace API key in `X-API-Key`. See [key types and access](https://docs.sim.ai/api-reference/authentication#key-types); operations that reject workspace keys say so in their description." }, - "oauthBearer": { - "type": "oauth2", - "description": "Send a Sim OAuth access token in `Authorization: Bearer`. See [OAuth authentication and scopes](https://docs.sim.ai/api-reference/authentication#oauth-access-tokens).", - "flows": { - "authorizationCode": { - "authorizationUrl": "https://www.sim.ai/api/auth/oauth2/authorize", - "tokenUrl": "https://www.sim.ai/api/auth/oauth2/token", - "refreshUrl": "https://www.sim.ai/api/auth/oauth2/token", - "scopes": { - "api:read": "Read your workspaces, workflows, files, tables, and logs", - "api:write": "Read, create, change, run, and delete resources in your workspaces", - "offline_access": "Stay signed in without asking again" - } + "delete": { + "operationId": "deleteKnowledgeChunk", + "summary": "Delete chunk", + "description": "Permanently remove one chunk and subtract it from document counts. Remaining `chunkIndex` values stay stable and may become non-contiguous. Connector-synced chunks are read-only and return `403` with `error.details.code: \"CONNECTOR_MANAGED_RESOURCE_READ_ONLY\"`; change the source and re-sync, or exclude the document. Documents that have not finished processing return `409` with their current status. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.chunks.delete", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] } - } - } - }, - "headers": { - "Content-Type": { - "description": "MIME type of the file, defaulting to application/octet-stream when the stored type is unavailable.", - "schema": { - "type": "string", - "title": "Content type", - "description": "MIME type of the file, defaulting to application/octet-stream when the stored type is unavailable." - } - }, - "Content-Disposition": { - "description": "Attachment disposition containing sanitized and RFC 5987 encoded filenames.", - "schema": { - "type": "string", - "title": "Content disposition", - "description": "Attachment disposition containing sanitized and RFC 5987 encoded filenames." - } - }, - "Content-Length": { - "description": "File size in bytes.", - "schema": { - "type": "string", - "pattern": "^(0|[1-9]\\d*)$", - "title": "Content length", - "description": "File size in bytes." - } - }, - "X-RateLimit-Limit": { - "description": "Maximum requests allowed in the current window.", - "schema": { - "type": "integer", - "minimum": 0, - "maximum": 9007199254740991, - "title": "Rate limit", - "description": "Maximum requests allowed in the current window." - } - }, - "X-RateLimit-Remaining": { - "description": "Requests remaining in the current window.", - "schema": { - "type": "integer", - "minimum": 0, - "maximum": 9007199254740991, - "title": "Rate limit remaining", - "description": "Requests remaining in the current window." - } - }, - "X-RateLimit-Reset": { - "description": "ISO 8601 timestamp when the current rate-limit window resets.", - "schema": { - "type": "string", - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", - "title": "Rate limit reset", - "description": "ISO 8601 timestamp when the current rate-limit window resets." - } - }, - "Retry-After": { - "description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset.", - "schema": { - "type": "integer", - "minimum": 0, - "maximum": 9007199254740991, - "title": "Retry after", - "description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset." - } - }, - "X-Run-Id": { - "description": "Identifier assigned to the workflow run.", - "schema": { - "type": "string", - "minLength": 1, - "title": "Run identifier", - "description": "Identifier assigned to the workflow run." - } - } - }, - "responses": { - "BadRequest": { - "description": "The request is invalid. This includes a query parameter sent with no value (`?limit=`, `?search=`), which is rejected rather than read as zero, empty, or the parameter default — omit the parameter instead.", - "content": { - "application/json": { + ], + "parameters": [ + { + "name": "documentId", + "in": "path", + "required": true, + "description": "Unique knowledge document identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "BAD_REQUEST", - "message": "Invalid request" - } + "type": "string", + "minLength": 1, + "description": "Unique knowledge document identifier." } - } - } - }, - "Unauthorized": { - "description": "The API credential is missing or invalid.", - "content": { - "application/json": { + }, + { + "name": "chunkId", + "in": "path", + "required": true, + "description": "Unique chunk identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "UNAUTHORIZED", - "message": "Authentication required" - } + "type": "string", + "minLength": 1, + "description": "Unique chunk identifier." } - } - } - }, - "UsageLimitExceeded": { - "description": "The workspace has exceeded its usage or billing limits.", - "content": { - "application/json": { + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "USAGE_LIMIT_EXCEEDED", - "message": "Usage limit exceeded. Please upgrade your plan to continue." - } + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." } - } - } - }, - "Forbidden": { - "description": "The caller lacks the rights this operation requires. When the cause is one a caller can act on, `error.details.code` names it. A resource in a workspace the caller cannot reach at all answers `404` instead, so absence and denial are indistinguishable.", - "content": { - "application/json": { + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", "schema": { - "$ref": "#/components/schemas/V2Error" + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + } + ], + "responses": { + "200": { + "description": "Chunk deletion acknowledgement.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } }, - "example": { - "error": { - "code": "FORBIDDEN", - "message": "Insufficient workspace permissions", - "details": { - "code": "INSUFFICIENT_WORKSPACE_ROLE" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeDeleteResponse" } } } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" } } - }, - "NotFound": { - "description": "The requested resource was not found.", - "content": { - "application/json": { + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/tags/{tagId}": { + "patch": { + "operationId": "updateKnowledgeTag", + "summary": "Update tag", + "description": "Rename a tag or change its slot-compatible `fieldType`. Renaming changes read and filter names without moving the slot or its values. Slots are fixed for a tag's lifetime; an incompatible type returns `400` and requires creating a new tag. A duplicate display name returns `409`. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.tags.update", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], + "parameters": [ + { + "name": "tagId", + "in": "path", + "required": true, + "description": "Unique tag definition identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "NOT_FOUND", - "message": "Not found" - } + "type": "string", + "minLength": 1, + "description": "Unique tag definition identifier." } - } - } - }, - "Conflict": { - "description": "The request conflicts with current resource state.", - "content": { - "application/json": { + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "CONFLICT", - "message": "The request conflicts with current knowledge resource state" - } + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." } } - } - }, - "PayloadTooLarge": { - "description": "The request, or a resource collection it must materialize, exceeds the allowed size: an oversized request body, a generated artifact past the download ceiling, or a workspace folder tree too large to load in full.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "PAYLOAD_TOO_LARGE", - "message": "Request body is too large" + ], + "requestBody": { + "required": true, + "description": "Workspace scope and the fields to update. At least one is required.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateKnowledgeTagRequest" + }, + "examples": { + "example1": { + "summary": "Request example 1", + "value": { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "displayName": "topic" + } + } } } } - } - }, - "UnsupportedMediaType": { - "description": "The request uses an unsupported media type.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/V2Error" + }, + "responses": { + "200": { + "description": "The updated tag definition.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } }, - "example": { - "error": { - "code": "UNSUPPORTED_MEDIA_TYPE", - "message": "Request body must be sent as application/json" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeTagResponse" + } } } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "413": { + "$ref": "#/components/responses/PayloadTooLarge" + }, + "415": { + "$ref": "#/components/responses/UnsupportedMediaType" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" } } }, - "RateLimited": { - "description": "The caller exceeded the request rate limit.", - "headers": { - "Retry-After": { - "$ref": "#/components/headers/Retry-After" + "delete": { + "operationId": "deleteKnowledgeTag", + "summary": "Delete tag", + "description": "Permanently delete a tag definition and its values from every document and chunk in the knowledge base. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:write`.", + "x-sim-operation": "knowledge.tags.delete", + "x-oauth-scope": "api:write", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] } - }, - "content": { - "application/json": { + ], + "parameters": [ + { + "name": "tagId", + "in": "path", + "required": true, + "description": "Unique tag definition identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "RATE_LIMITED", - "message": "API rate limit exceeded", - "details": { - "retryAfter": "2026-01-01T00:00:30.000Z" - } - } + "type": "string", + "minLength": 1, + "description": "Unique tag definition identifier." } - } - } - }, - "InternalError": { - "description": "An unexpected server error occurred.", - "content": { - "application/json": { + }, + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", "schema": { - "$ref": "#/components/schemas/V2Error" - }, - "example": { - "error": { - "code": "INTERNAL_ERROR", - "message": "Internal server error" - } + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." } - } - } - }, - "ServiceUnavailable": { - "description": "A required service is temporarily unavailable. When present, `Retry-After` gives the minimum seconds to wait; add jitter before retrying. Check operation-specific guidance before repeating a change after an uncertain response.", - "headers": { - "Retry-After": { - "$ref": "#/components/headers/Retry-After" - } - }, - "content": { - "application/json": { + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", "schema": { - "$ref": "#/components/schemas/V2Error" + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + } + ], + "responses": { + "200": { + "description": "Tag deletion acknowledgement.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } }, - "example": { - "error": { - "code": "SERVICE_UNAVAILABLE", - "message": "Service temporarily unavailable" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2DeleteKnowledgeTagResponse" + } } } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" } } } }, - "schemas": { - "V2ActionableForbiddenDetails": { - "type": "object", - "properties": { - "code": { - "$ref": "#/components/schemas/V2ForbiddenDetailCode" + "/api/v2/knowledge/{knowledgeBaseId}/tags/next-slot": { + "get": { + "operationId": "getNextKnowledgeTagSlot", + "summary": "Get next tag slot", + "description": "Get the next available slot and remaining capacity for a field type. This does not reserve a slot. Create tag selects a free slot when `tagSlot` is omitted. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.tags.read_next_slot", + "x-oauth-scope": "api:read", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], + "parameters": [ + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." + } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + }, + { + "name": "fieldType", + "in": "query", + "required": true, + "description": "Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3.", + "schema": { + "type": "string", + "enum": ["text", "number", "date", "boolean"], + "description": "Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3.", + "examples": ["text"] + } + } + ], + "responses": { + "200": { + "description": "Slot availability for the requested field type.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2NextKnowledgeTagSlotResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + } + }, + "/api/v2/knowledge/{knowledgeBaseId}/tags/usage": { + "get": { + "operationId": "listKnowledgeTagUsage", + "summary": "List tag usage", + "description": "Count the documents and chunks with a value for each defined tag. Returns one page; `nextCursor` is always null. Workspace API keys return `403`; use a personal API key or scoped OAuth token.\n\nOAuth scope: `api:read`.", + "x-sim-operation": "knowledge.tags.read_usage", + "x-oauth-scope": "api:read", + "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], + "parameters": [ + { + "name": "knowledgeBaseId", + "in": "path", + "required": true, + "description": "Unique knowledge base identifier.", + "schema": { + "type": "string", + "minLength": 1, + "description": "Unique knowledge base identifier." + } + }, + { + "name": "workspaceId", + "in": "query", + "required": true, + "description": "Workspace that owns the knowledge base.", + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace that owns the knowledge base." + } + } + ], + "responses": { + "200": { + "description": "Usage counts for every defined tag.", + "headers": { + "X-RateLimit-Limit": { + "$ref": "#/components/headers/X-RateLimit-Limit" + }, + "X-RateLimit-Remaining": { + "$ref": "#/components/headers/X-RateLimit-Remaining" + }, + "X-RateLimit-Reset": { + "$ref": "#/components/headers/X-RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2KnowledgeTagUsageListResponse" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "429": { + "$ref": "#/components/responses/RateLimited" + }, + "500": { + "$ref": "#/components/responses/InternalError" + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + } + } + } + } + }, + "components": { + "securitySchemes": { + "apiKey": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key", + "description": "Send a personal or workspace API key in `X-API-Key`. See [key types and access](https://docs.sim.ai/api-reference/authentication#key-types); operations that reject workspace keys say so in their description." + }, + "oauthBearer": { + "type": "oauth2", + "description": "Send a Sim OAuth access token in `Authorization: Bearer`. See [OAuth authentication and scopes](https://docs.sim.ai/api-reference/authentication#oauth-access-tokens).", + "flows": { + "authorizationCode": { + "authorizationUrl": "https://www.sim.ai/api/auth/oauth2/authorize", + "tokenUrl": "https://www.sim.ai/api/auth/oauth2/token", + "refreshUrl": "https://www.sim.ai/api/auth/oauth2/token", + "scopes": { + "api:read": "Read your workspaces, workflows, files, tables, and logs", + "api:write": "Read, create, change, run, and delete resources in your workspaces", + "offline_access": "Stay signed in without asking again" + } + } + } + } + }, + "headers": { + "Content-Type": { + "description": "MIME type of the file, defaulting to application/octet-stream when the stored type is unavailable.", + "schema": { + "type": "string", + "title": "Content type", + "description": "MIME type of the file, defaulting to application/octet-stream when the stored type is unavailable." + } + }, + "Content-Disposition": { + "description": "Attachment disposition containing sanitized and RFC 5987 encoded filenames.", + "schema": { + "type": "string", + "title": "Content disposition", + "description": "Attachment disposition containing sanitized and RFC 5987 encoded filenames." + } + }, + "Content-Length": { + "description": "File size in bytes.", + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)$", + "title": "Content length", + "description": "File size in bytes." + } + }, + "X-RateLimit-Limit": { + "description": "Maximum requests allowed in the current window.", + "schema": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "title": "Rate limit", + "description": "Maximum requests allowed in the current window." + } + }, + "X-RateLimit-Remaining": { + "description": "Requests remaining in the current window.", + "schema": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "title": "Rate limit remaining", + "description": "Requests remaining in the current window." + } + }, + "X-RateLimit-Reset": { + "description": "ISO 8601 timestamp when the current rate-limit window resets.", + "schema": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "title": "Rate limit reset", + "description": "ISO 8601 timestamp when the current rate-limit window resets." + } + }, + "Retry-After": { + "description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset.", + "schema": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "title": "Retry after", + "description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset." + } + }, + "X-Run-Id": { + "description": "Identifier assigned to the workflow run.", + "schema": { + "type": "string", + "minLength": 1, + "title": "Run identifier", + "description": "Identifier assigned to the workflow run." + } + } + }, + "responses": { + "BadRequest": { + "description": "The request is invalid. This includes a query parameter sent with no value (`?limit=`, `?search=`), which is rejected rather than read as zero, empty, or the parameter default — omit the parameter instead.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "BAD_REQUEST", + "message": "Invalid request" + } + } + } + } + }, + "Unauthorized": { + "description": "The API credential is missing or invalid.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "UNAUTHORIZED", + "message": "Authentication required" + } + } + } + } + }, + "UsageLimitExceeded": { + "description": "The workspace has exceeded its usage or billing limits.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "USAGE_LIMIT_EXCEEDED", + "message": "Usage limit exceeded. Please upgrade your plan to continue." + } + } + } + } + }, + "Forbidden": { + "description": "The caller lacks the rights this operation requires. When the cause is one a caller can act on, `error.details.code` names it. A resource in a workspace the caller cannot reach at all answers `404` instead, so absence and denial are indistinguishable.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "FORBIDDEN", + "message": "Insufficient workspace permissions", + "details": { + "code": "INSUFFICIENT_WORKSPACE_ROLE" + } + } + } + } + } + }, + "NotFound": { + "description": "The requested resource was not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "NOT_FOUND", + "message": "Not found" + } + } + } + } + }, + "Conflict": { + "description": "The request conflicts with current resource state.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "CONFLICT", + "message": "The request conflicts with current knowledge resource state" + } + } + } + } + }, + "PayloadTooLarge": { + "description": "The request, or a resource collection it must materialize, exceeds the allowed size: an oversized request body, a generated artifact past the download ceiling, or a workspace folder tree too large to load in full.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "PAYLOAD_TOO_LARGE", + "message": "Request body is too large" + } + } + } + } + }, + "UnsupportedMediaType": { + "description": "The request uses an unsupported media type.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "UNSUPPORTED_MEDIA_TYPE", + "message": "Request body must be sent as application/json" + } + } + } + } + }, + "RateLimited": { + "description": "The caller exceeded the request rate limit.", + "headers": { + "Retry-After": { + "$ref": "#/components/headers/Retry-After" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "RATE_LIMITED", + "message": "API rate limit exceeded", + "details": { + "retryAfter": "2026-01-01T00:00:30.000Z" + } + } + } + } + } + }, + "InternalError": { + "description": "An unexpected server error occurred.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "INTERNAL_ERROR", + "message": "Internal server error" + } + } + } + } + }, + "ServiceUnavailable": { + "description": "A required service is temporarily unavailable. When present, `Retry-After` gives the minimum seconds to wait; add jitter before retrying. Check operation-specific guidance before repeating a change after an uncertain response.", + "headers": { + "Retry-After": { + "$ref": "#/components/headers/Retry-After" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/V2Error" + }, + "example": { + "error": { + "code": "SERVICE_UNAVAILABLE", + "message": "Service temporarily unavailable" + } + } + } + } + } + }, + "schemas": { + "V2ActionableForbiddenDetails": { + "type": "object", + "properties": { + "code": { + "$ref": "#/components/schemas/V2ForbiddenDetailCode" + } + }, + "required": ["code"], + "additionalProperties": { + "description": "Additional context for this refusal." + }, + "title": "Actionable forbidden details", + "description": "Machine-readable cause and optional context for an actionable `403` response." + }, + "V2ForbiddenDetailCode": { + "type": "string", + "enum": [ + "INSUFFICIENT_WORKSPACE_ROLE", + "PERSONAL_API_KEYS_DISABLED", + "WORKSPACE_KEY_OPERATION_NOT_PERMITTED", + "PRINCIPAL_KIND_NOT_PERMITTED", + "ORGANIZATION_MEMBERSHIP_REQUIRED", + "ORGANIZATION_ADMIN_REQUIRED", + "ENTERPRISE_PLAN_REQUIRED", + "SSO_DISABLED", + "SSO_DOMAIN_NOT_VERIFIED", + "SSO_PROVIDER_LIMIT_REACHED", + "ORGANIZATION_PLAN_REQUIRED", + "AUDIT_LOGS_DISABLED", + "ACCESS_REQUESTS_DISABLED", + "ACCESS_REQUEST_ORGANIZATION_REQUIRED", + "SKILL_EDITOR_ACCESS_REQUIRED", + "SECRET_ADMIN_ACCESS_REQUIRED", + "WORKSPACE_RESOURCE_LIMIT_REACHED", + "PUBLIC_SHARING_NOT_ALLOWED", + "CREDENTIAL_ADMIN_ACCESS_REQUIRED", + "MCP_SERVER_URL_NOT_ALLOWED", + "WORKSPACE_PLAN_CAPABILITY_REQUIRED", + "CHAT_AUTH_MODE_NOT_PERMITTED", + "CONNECTOR_MANAGED_RESOURCE_READ_ONLY", + "PERMISSION_GROUP_CAPABILITY_BLOCKED", + "INTEGRATION_NOT_ALLOWED", + "INSUFFICIENT_SCOPE", + "SCIM_MANAGED_MEMBERSHIP" + ], + "title": "Forbidden detail code", + "description": "Stable cause code for an actionable `403` response." + }, + "V2Error": { + "type": "object", + "properties": { + "error": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Stable machine-readable error code." + }, + "message": { + "type": "string", + "description": "Human-readable explanation of the error." + }, + "details": { + "description": "Structured error context whose keys depend on the error. Actionable `403` responses use the `V2ActionableForbiddenDetails` shape; validation failures may return issue arrays instead.", + "anyOf": [ + { + "$ref": "#/components/schemas/V2ActionableForbiddenDetails" + }, + { + "description": "Other structured context defined by the specific error." + } + ] + } + }, + "required": ["code", "message"], + "additionalProperties": false, + "description": "Canonical error details." + } + }, + "required": ["error"], + "additionalProperties": false, + "title": "v2 error response", + "description": "Canonical error envelope returned by the public v2 API.", + "examples": [ + { + "error": { + "code": "BAD_REQUEST", + "message": "The request is invalid." + } + } + ] + }, + "FolderPathInput": { + "title": "Folder path input", + "description": "Folder path. A missing leading slash is normalized before validation. Segments are percent-encoded, so a folder shown as \"New folder\" is `/New%20folder`: everything outside `A-Z a-z 0-9 - _ . ~` is escaped as uppercase hex, and only that exact encoding is accepted. A trailing slash, an empty segment, and a literal `.` or `..` segment are rejected. At most 64 segments and 4096 encoded bytes.", + "maxLength": 4096, + "type": "string" + }, + "V2KnowledgeBase": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique knowledge base identifier.", + "examples": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"] + }, + "name": { + "type": "string", + "description": "Human-readable knowledge base name.", + "examples": ["Product Documentation"] + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Knowledge base description, or null when none is set.", + "examples": ["All product documentation and guides"] + }, + "tokenCount": { + "type": "number", + "description": "Total tokens across indexed documents.", + "examples": [48213] + }, + "embeddingModel": { + "type": "string", + "description": "Embedding model used to index documents.", + "examples": ["text-embedding-3-small"] + }, + "embeddingDimension": { + "type": "number", + "description": "Dimensionality of the embedding vectors.", + "examples": [1536] + }, + "chunkingConfig": { + "$ref": "#/components/schemas/V2KnowledgeChunkingConfig" + }, + "docCount": { + "description": "Number of documents in the knowledge base.", + "examples": [12], + "type": "number" + }, + "connectorTypes": { + "description": "External connector types that have synced documents into the knowledge base.", + "examples": [["notion", "google_drive"]], + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "type": "string", + "description": "ISO 8601 timestamp when the knowledge base was created.", + "format": "date-time", + "examples": ["2025-01-10T09:00:00Z"] + }, + "updatedAt": { + "type": "string", + "description": "ISO 8601 timestamp when the knowledge base was last modified.", + "format": "date-time", + "examples": ["2025-06-18T16:45:00Z"] + }, + "webUrl": { + "type": "string", + "format": "uri", + "description": "Canonical absolute URL for opening this resource in the Sim web application." + }, + "ownerEmail": { + "type": "string", + "format": "email", + "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "description": "Current email address of the knowledge base owner.", + "examples": ["owner@example.com"] + }, + "folderPath": { + "type": "string", + "title": "Folder path", + "description": "Canonical containing-folder path; `/` is the workspace root. Resolved against active folders only, so an archived knowledge base whose containing folder was archived with it reports `/`.", + "maxLength": 4096, + "examples": ["/Product"] + }, + "deletedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$" + }, + { + "type": "null" + } + ], + "description": "ISO 8601 archive timestamp, or null while active. Use List knowledge bases with `scope=archived` to find archived knowledge bases.", + "format": "date-time", + "examples": ["2026-01-16T09:00:00Z"] + } + }, + "required": [ + "id", + "name", + "description", + "tokenCount", + "embeddingModel", + "embeddingDimension", + "chunkingConfig", + "createdAt", + "updatedAt", + "webUrl", + "ownerEmail", + "folderPath", + "deletedAt" + ], + "additionalProperties": false, + "title": "Knowledge base", + "description": "A collection of documents indexed for vector and tag search." + }, + "V2KnowledgeChunkingConfig": { + "type": "object", + "properties": { + "maxSize": { + "type": "number", + "description": "Maximum chunk size in tokens.", + "examples": [1024] + }, + "minSize": { + "type": "number", + "description": "Minimum chunk size in characters.", + "examples": [100] + }, + "overlap": { + "type": "number", + "description": "Requested overlap in tokens between adjacent chunks.", + "examples": [200] + }, + "strategy": { + "description": "Chunking strategy applied during document processing.", + "type": "string", + "enum": ["auto", "text", "regex", "recursive", "sentence", "token"] + }, + "strategyOptions": { + "description": "Strategy-specific tuning options.", + "type": "object", + "properties": { + "pattern": { + "description": "Regular expression used by the regex chunking strategy.", + "type": "string", + "maxLength": 500 + }, + "separators": { + "description": "Ordered separators used to split content into chunks.", + "type": "array", + "items": { + "type": "string" + } + }, + "recipe": { + "description": "Content-aware recipe used by the automatic chunking strategy.", + "type": "string", + "enum": ["plain", "markdown", "code"] + }, + "strictBoundaries": { + "description": "Whether regex matches must form strict chunk boundaries.", + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "required": ["maxSize", "minSize", "overlap"], + "additionalProperties": { + "description": "Additional forward-compatible chunking configuration property." + }, + "title": "Knowledge chunking configuration", + "description": "How documents in a knowledge base are split into chunks before embedding." + }, + "V2KnowledgeBaseListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/V2KnowledgeBase" + }, + "description": "Items in the current page." + }, + "nextCursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there are no more pages. Do not construct a cursor yourself." + } + }, + "required": ["data", "nextCursor"], + "additionalProperties": false, + "title": "Knowledge base list response", + "description": "A cursor-paginated page of knowledge bases." + }, + "V2KnowledgeBaseResponse": { + "type": "object", + "properties": { + "data": { + "description": "Response data.", + "$ref": "#/components/schemas/V2KnowledgeBase" } }, - "required": ["code"], - "additionalProperties": { - "description": "Additional context for this refusal." - }, - "title": "Actionable forbidden details", - "description": "Machine-readable cause and optional context for an actionable `403` response." - }, - "V2ForbiddenDetailCode": { - "type": "string", - "enum": [ - "INSUFFICIENT_WORKSPACE_ROLE", - "PERSONAL_API_KEYS_DISABLED", - "WORKSPACE_KEY_OPERATION_NOT_PERMITTED", - "PRINCIPAL_KIND_NOT_PERMITTED", - "ORGANIZATION_MEMBERSHIP_REQUIRED", - "ORGANIZATION_ADMIN_REQUIRED", - "ENTERPRISE_PLAN_REQUIRED", - "SSO_DISABLED", - "SSO_DOMAIN_NOT_VERIFIED", - "SSO_PROVIDER_LIMIT_REACHED", - "ORGANIZATION_PLAN_REQUIRED", - "AUDIT_LOGS_DISABLED", - "ACCESS_REQUESTS_DISABLED", - "ACCESS_REQUEST_ORGANIZATION_REQUIRED", - "SKILL_EDITOR_ACCESS_REQUIRED", - "SECRET_ADMIN_ACCESS_REQUIRED", - "WORKSPACE_RESOURCE_LIMIT_REACHED", - "PUBLIC_SHARING_NOT_ALLOWED", - "CREDENTIAL_ADMIN_ACCESS_REQUIRED", - "MCP_SERVER_URL_NOT_ALLOWED", - "WORKSPACE_PLAN_CAPABILITY_REQUIRED", - "CHAT_AUTH_MODE_NOT_PERMITTED", - "CONNECTOR_MANAGED_RESOURCE_READ_ONLY", - "PERMISSION_GROUP_CAPABILITY_BLOCKED", - "INTEGRATION_NOT_ALLOWED", - "INSUFFICIENT_SCOPE", - "SCIM_MANAGED_MEMBERSHIP" - ], - "title": "Forbidden detail code", - "description": "Stable cause code for an actionable `403` response." + "required": ["data"], + "additionalProperties": false, + "title": "Knowledge base response", + "description": "A single knowledge base." }, - "V2Error": { + "V2KnowledgeChunkingConfigInput": { "type": "object", "properties": { - "error": { + "maxSize": { + "default": 1024, + "description": "Maximum chunk size in tokens.", + "examples": [1024], + "type": "number", + "minimum": 100, + "maximum": 4000 + }, + "minSize": { + "default": 100, + "description": "Minimum chunk size in characters.", + "examples": [100], + "type": "number", + "minimum": 1, + "maximum": 2000 + }, + "overlap": { + "default": 200, + "description": "Requested overlap in tokens between adjacent chunks.", + "examples": [200], + "type": "number", + "minimum": 0, + "maximum": 500 + }, + "strategy": { + "description": "Chunking strategy applied during document processing. `regex` additionally requires `strategyOptions.pattern`.", + "type": "string", + "enum": ["auto", "text", "regex", "recursive", "sentence", "token"] + }, + "strategyOptions": { + "description": "Strategy-specific tuning options. `strictBoundaries` is accepted only with `strategy: \"regex\"`.", "type": "object", "properties": { - "code": { + "pattern": { + "description": "Regular expression used by the regex chunking strategy.", "type": "string", - "description": "Stable machine-readable error code." + "maxLength": 500 }, - "message": { + "separators": { + "description": "Ordered separators used to split content into chunks.", + "maxItems": 32, + "type": "array", + "items": { + "type": "string", + "maxLength": 100 + } + }, + "recipe": { + "description": "Content-aware recipe used by the automatic chunking strategy.", "type": "string", - "description": "Human-readable explanation of the error." + "enum": ["plain", "markdown", "code"] }, - "details": { - "description": "Structured error context whose keys depend on the error. Actionable `403` responses use the `V2ActionableForbiddenDetails` shape; validation failures may return issue arrays instead.", - "anyOf": [ - { - "$ref": "#/components/schemas/V2ActionableForbiddenDetails" - }, - { - "description": "Other structured context defined by the specific error." - } - ] + "strictBoundaries": { + "description": "Whether regex matches must form strict chunk boundaries.", + "type": "boolean" } }, - "required": ["code", "message"], - "additionalProperties": false, - "description": "Canonical error details." + "additionalProperties": false } }, - "required": ["error"], "additionalProperties": false, - "title": "v2 error response", - "description": "Canonical error envelope returned by the public v2 API.", - "examples": [ - { - "error": { - "code": "BAD_REQUEST", - "message": "The request is invalid." - } - } - ] - }, - "FolderPathInput": { - "title": "Folder path input", - "description": "Folder path. A missing leading slash is normalized before validation. Segments are percent-encoded, so a folder shown as \"New folder\" is `/New%20folder`: everything outside `A-Z a-z 0-9 - _ . ~` is escaped as uppercase hex, and only that exact encoding is accepted. A trailing slash, an empty segment, and a literal `.` or `..` segment are rejected. At most 64 segments and 4096 encoded bytes.", - "maxLength": 4096, - "type": "string" + "title": "Knowledge chunking configuration input", + "description": "Chunking configuration applied when processing documents. On update this object is replaced wholesale rather than merged, so a caller preserving one key must read, modify, and write the whole object back." }, - "V2KnowledgeBase": { + "CreateKnowledgeBaseRequest": { "type": "object", "properties": { - "id": { + "workspaceId": { "type": "string", - "description": "Unique knowledge base identifier.", - "examples": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"] + "minLength": 1, + "maxLength": 128, + "description": "Workspace in which to create the knowledge base." }, "name": { "type": "string", + "minLength": 1, + "maxLength": 255, "description": "Human-readable knowledge base name.", "examples": ["Product Documentation"] }, "description": { + "description": "Optional knowledge base description.", + "examples": ["All product documentation and guides"], + "type": "string", + "maxLength": 10000 + }, + "chunkingConfig": { + "default": { + "maxSize": 1024, + "minSize": 100, + "overlap": 200 + }, + "description": "Chunking configuration; defaults are applied when omitted.", + "$ref": "#/components/schemas/V2KnowledgeChunkingConfigInput" + }, + "folderPath": { + "description": "Containing folder path; omission creates the knowledge base at the root.", + "$ref": "#/components/schemas/FolderPathInput" + } + }, + "required": ["workspaceId", "name"], + "additionalProperties": false, + "title": "Create knowledge base request", + "description": "Workspace, name, description, chunking configuration, and folder placement." + }, + "V2KnowledgeImportFailure": { + "type": "object", + "properties": { + "filename": { + "type": "string", + "description": "Filename of the document that was not imported." + }, + "message": { + "type": "string", + "description": "Why the document was not imported." + } + }, + "required": ["filename", "message"], + "additionalProperties": false, + "title": "Knowledge import failure", + "description": "One bundle document the import could not bring over." + }, + "V2KnowledgeImport": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique knowledge-base import identifier." + }, + "workspaceId": { + "type": "string", + "description": "Workspace that owns the import." + }, + "status": { + "type": "string", + "enum": ["uploading", "processing", "completed", "failed", "canceled", "expired"], + "description": "Current import lifecycle state." + }, + "knowledgeBaseId": { "anyOf": [ { "type": "string" @@ -5571,72 +6444,61 @@ "type": "null" } ], - "description": "Knowledge base description, or null when none is set.", - "examples": ["All product documentation and guides"] - }, - "tokenCount": { - "type": "number", - "description": "Total tokens across indexed documents.", - "examples": [48213] + "description": "Knowledge base the import created, or null until it exists." }, - "embeddingModel": { - "type": "string", - "description": "Embedding model used to index documents.", - "examples": ["text-embedding-3-small"] + "documentsTotal": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "description": "Documents the bundle carries; zero until its manifest has been read." }, - "embeddingDimension": { - "type": "number", - "description": "Dimensionality of the embedding vectors.", - "examples": [1536] + "documentsImported": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "description": "Documents created so far. A document whose vectors could not be reused is indexed afterwards, as an upload is, so it may still be processing in the knowledge base." }, - "chunkingConfig": { - "$ref": "#/components/schemas/V2KnowledgeChunkingConfig" + "documentsFailed": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "description": "Documents that could not be imported. Non-zero still allows `completed`." }, - "docCount": { - "description": "Number of documents in the knowledge base.", - "examples": [12], - "type": "number" + "vectorsReused": { + "type": "boolean", + "description": "Whether the bundle's vectors matched this deployment's embedding model and were stored without re-embedding." }, - "connectorTypes": { - "description": "External connector types that have synced documents into the knowledge base.", - "examples": [["notion", "google_drive"]], + "failures": { "type": "array", "items": { - "type": "string" - } - }, - "createdAt": { - "type": "string", - "description": "ISO 8601 timestamp when the knowledge base was created.", - "format": "date-time", - "examples": ["2025-01-10T09:00:00Z"] - }, - "updatedAt": { - "type": "string", - "description": "ISO 8601 timestamp when the knowledge base was last modified.", - "format": "date-time", - "examples": ["2025-06-18T16:45:00Z"] + "$ref": "#/components/schemas/V2KnowledgeImportFailure" + }, + "description": "Bounded sample of the documents that could not be imported." }, - "webUrl": { - "type": "string", - "format": "uri", - "description": "Canonical absolute URL for opening this resource in the Sim web application." + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Terminal failure reason, or null." }, - "ownerEmail": { + "createdAt": { "type": "string", - "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", - "description": "Current email address of the knowledge base owner.", - "examples": ["owner@example.com"] + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "description": "ISO 8601 creation timestamp." }, - "folderPath": { + "updatedAt": { "type": "string", - "title": "Folder path", - "description": "Canonical containing-folder path; `/` is the workspace root. Resolved against active folders only, so an archived knowledge base whose containing folder was archived with it reports `/`.", - "maxLength": 4096, - "examples": ["/Product"] + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "description": "ISO 8601 last-update timestamp." }, - "deletedAt": { + "completedAt": { "anyOf": [ { "type": "string", @@ -5647,236 +6509,329 @@ "type": "null" } ], - "description": "ISO 8601 archive timestamp, or null while active. Use List knowledge bases with `scope=archived` to find archived knowledge bases.", - "format": "date-time", - "examples": ["2026-01-16T09:00:00Z"] + "description": "ISO 8601 completion timestamp, or null." } }, "required": [ "id", - "name", - "description", - "tokenCount", - "embeddingModel", - "embeddingDimension", - "chunkingConfig", + "workspaceId", + "status", + "knowledgeBaseId", + "documentsTotal", + "documentsImported", + "documentsFailed", + "vectorsReused", + "failures", + "error", "createdAt", "updatedAt", - "webUrl", - "ownerEmail", - "folderPath", - "deletedAt" + "completedAt" ], "additionalProperties": false, - "title": "Knowledge base", - "description": "A collection of documents indexed for vector and tag search." + "title": "Knowledge base import", + "description": "Durable lifecycle resource for importing a knowledge base bundle." }, - "V2KnowledgeChunkingConfig": { + "V2PutUploadTransfer": { "type": "object", "properties": { - "maxSize": { - "type": "number", - "description": "Maximum chunk size in tokens.", - "examples": [1024] + "method": { + "type": "string", + "const": "put", + "description": "Upload strategy discriminator." }, - "minSize": { - "type": "number", - "description": "Minimum chunk size in characters.", - "examples": [100] + "url": { + "type": "string", + "format": "uri", + "description": "Signed URL to which the file bytes are uploaded. Upload bytes with `PUT` and exactly the supplied headers; never construct or modify the signed URL. Treat any `2xx` as success. Sim-hosted URLs return an empty `204` and v2 JSON errors. Object-storage URLs may return `200` or `201` and provider-specific errors, often XML." }, - "overlap": { - "type": "number", - "description": "Requested overlap in tokens between adjacent chunks.", - "examples": [200] + "headers": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "type": "string" + }, + "description": "Headers that must be included with the upload request." }, - "strategy": { - "description": "Chunking strategy applied during document processing.", + "expiresAt": { "type": "string", - "enum": ["auto", "text", "regex", "recursive", "sentence", "token"] + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "description": "ISO 8601 expiration time for this signed URL. This is the URL's own expiry and is normally earlier than the upload session's expiresAt: the session stays open for later part, status, completion, and abort requests, but the bytes must be uploaded before this time. Once it passes, the storage provider rejects the upload and a new upload session must be created." + } + }, + "required": ["method", "url", "headers", "expiresAt"], + "additionalProperties": false, + "title": "Direct upload transfer", + "description": "Instructions for uploading bytes to one signed URL." + }, + "V2MultipartUploadTransfer": { + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "multipart", + "description": "Upload strategy discriminator." }, - "strategyOptions": { - "description": "Strategy-specific tuning options.", - "type": "object", - "properties": { - "pattern": { - "description": "Regular expression used by the regex chunking strategy.", - "type": "string", - "maxLength": 500 - }, - "separators": { - "description": "Ordered separators used to split content into chunks.", - "type": "array", - "items": { - "type": "string" - } - }, - "recipe": { - "description": "Content-aware recipe used by the automatic chunking strategy.", - "type": "string", - "enum": ["plain", "markdown", "code"] + "partSize": { + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "description": "Required size of each non-final part in bytes." + }, + "partCount": { + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 640, + "description": "Total number of upload parts." + } + }, + "required": ["method", "partSize", "partCount"], + "additionalProperties": false, + "title": "Multipart upload transfer", + "description": "Instructions for splitting bytes into a multipart upload." + }, + "V2CreateKnowledgeImportData": { + "type": "object", + "properties": { + "session": { + "description": "Created import, waiting for its upload.", + "$ref": "#/components/schemas/V2KnowledgeImport" + }, + "uploadToken": { + "type": "string", + "minLength": 1, + "description": "Signed token for upload control requests." + }, + "transfer": { + "oneOf": [ + { + "$ref": "#/components/schemas/V2PutUploadTransfer" }, - "strictBoundaries": { - "description": "Whether regex matches must form strict chunk boundaries.", - "type": "boolean" + { + "$ref": "#/components/schemas/V2MultipartUploadTransfer" } - }, - "additionalProperties": false + ], + "description": "Signed bundle upload instructions." } }, - "required": ["maxSize", "minSize", "overlap"], - "additionalProperties": { - "description": "Additional forward-compatible chunking configuration property." + "required": ["session", "uploadToken", "transfer"], + "additionalProperties": false, + "title": "Create knowledge base import data", + "description": "Created import and the instructions for uploading its bundle." + }, + "V2CreateKnowledgeImportResponse": { + "type": "object", + "properties": { + "data": { + "description": "Response data.", + "$ref": "#/components/schemas/V2CreateKnowledgeImportData" + } }, - "title": "Knowledge chunking configuration", - "description": "How documents in a knowledge base are split into chunks before embedding." + "required": ["data"], + "additionalProperties": false, + "title": "Create knowledge base import response", + "description": "The import and the instructions for uploading its bundle." }, - "V2KnowledgeBaseListResponse": { + "V2KnowledgeImportSource": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "upload", + "description": "Upload-backed import discriminator." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Bundle filename, as produced by a knowledge base export." + }, + "contentType": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Bundle MIME type, normally application/zip." + }, + "size": { + "type": "integer", + "minimum": 1, + "maximum": 5368709120, + "description": "Exact bundle size in bytes; the maximum is 5 GiB." + } + }, + "required": ["type", "name", "contentType", "size"], + "additionalProperties": false, + "title": "Knowledge base import source", + "description": "Bundle archive uploaded through signed transfer instructions." + }, + "CreateKnowledgeImportRequest": { + "type": "object", + "properties": { + "workspaceId": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Workspace in which to create the knowledge base." + }, + "name": { + "description": "Name for the new knowledge base; defaults to the bundle's own name.", + "examples": ["Product Documentation"], + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "source": { + "$ref": "#/components/schemas/V2KnowledgeImportSource" + } + }, + "required": ["workspaceId", "source"], + "additionalProperties": false, + "title": "Create knowledge base import request", + "description": "Workspace, bundle archive, and an optional name for the new knowledge base.", + "examples": [ + { + "workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64", + "name": "Product Documentation", + "source": { + "type": "upload", + "name": "product-documentation.simkb.zip", + "contentType": "application/zip", + "size": 7340032 + } + } + ] + }, + "V2KnowledgeImportResponse": { + "type": "object", + "properties": { + "data": { + "description": "Response data.", + "$ref": "#/components/schemas/V2KnowledgeImport" + } + }, + "required": ["data"], + "additionalProperties": false, + "title": "Knowledge base import response", + "description": "A knowledge base import lifecycle resource." + }, + "V2CancelKnowledgeImportResponse": { "type": "object", "properties": { "data": { + "description": "Response data.", + "$ref": "#/components/schemas/V2KnowledgeImport" + } + }, + "required": ["data"], + "additionalProperties": false, + "title": "Cancel knowledge base import response", + "description": "The canceled knowledge base import." + }, + "V2UploadPartUrl": { + "type": "object", + "properties": { + "partNumber": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991, + "description": "Multipart part number." + }, + "url": { + "type": "string", + "format": "uri", + "description": "Signed URL for this upload part. Upload bytes with `PUT` and exactly the supplied headers; never construct or modify the signed URL. Treat any `2xx` as success. Sim-hosted URLs return an empty `204` and v2 JSON errors. Object-storage URLs may return `200` or `201` and provider-specific errors, often XML. Do not retain part `ETag` values; after every part succeeds, call the completion endpoint without a request body." + }, + "headers": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "type": "string" + }, + "description": "Headers that must be included with the part upload." + }, + "expiresAt": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "description": "ISO 8601 expiration time for the signed URL." + } + }, + "required": ["partNumber", "url", "headers", "expiresAt"], + "additionalProperties": false, + "title": "Upload part URL", + "description": "A signed URL and required headers for one multipart upload part." + }, + "V2PartUrlsData": { + "type": "object", + "properties": { + "parts": { + "maxItems": 100, "type": "array", "items": { - "$ref": "#/components/schemas/V2KnowledgeBase" + "$ref": "#/components/schemas/V2UploadPartUrl" }, - "description": "Items in the current page." - }, - "nextCursor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there are no more pages. Do not construct a cursor yourself." + "description": "Signed URLs for requested parts." } }, - "required": ["data", "nextCursor"], + "required": ["parts"], "additionalProperties": false, - "title": "Knowledge base list response", - "description": "A cursor-paginated page of knowledge bases." + "title": "Upload part URLs", + "description": "Signed transfer URLs for the requested multipart upload parts." }, - "V2KnowledgeBaseResponse": { + "V2CreateKnowledgeImportPartUrlsResponse": { "type": "object", "properties": { "data": { "description": "Response data.", - "$ref": "#/components/schemas/V2KnowledgeBase" + "$ref": "#/components/schemas/V2PartUrlsData" } }, "required": ["data"], "additionalProperties": false, - "title": "Knowledge base response", - "description": "A single knowledge base." + "title": "Create knowledge base import part URLs response", + "description": "Signed URLs and required headers for each requested upload part." }, - "V2KnowledgeChunkingConfigInput": { + "CreateKnowledgeImportPartUrlsRequest": { "type": "object", "properties": { - "maxSize": { - "default": 1024, - "description": "Maximum chunk size in tokens.", - "examples": [1024], - "type": "number", - "minimum": 100, - "maximum": 4000 - }, - "minSize": { - "default": 100, - "description": "Minimum chunk size in characters.", - "examples": [100], - "type": "number", - "minimum": 1, - "maximum": 2000 - }, - "overlap": { - "default": 200, - "description": "Requested overlap in tokens between adjacent chunks.", - "examples": [200], - "type": "number", - "minimum": 0, - "maximum": 500 - }, - "strategy": { - "description": "Chunking strategy applied during document processing. `regex` additionally requires `strategyOptions.pattern`.", - "type": "string", - "enum": ["auto", "text", "regex", "recursive", "sentence", "token"] - }, - "strategyOptions": { - "description": "Strategy-specific tuning options. `strictBoundaries` is accepted only with `strategy: \"regex\"`.", - "type": "object", - "properties": { - "pattern": { - "description": "Regular expression used by the regex chunking strategy.", - "type": "string", - "maxLength": 500 - }, - "separators": { - "description": "Ordered separators used to split content into chunks.", - "maxItems": 32, - "type": "array", - "items": { - "type": "string", - "maxLength": 100 - } - }, - "recipe": { - "description": "Content-aware recipe used by the automatic chunking strategy.", - "type": "string", - "enum": ["plain", "markdown", "code"] - }, - "strictBoundaries": { - "description": "Whether regex matches must form strict chunk boundaries.", - "type": "boolean" - } + "partNumbers": { + "minItems": 1, + "maxItems": 100, + "type": "array", + "items": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 }, - "additionalProperties": false + "description": "Multipart part numbers for which signed URLs should be created." } }, + "required": ["partNumbers"], "additionalProperties": false, - "title": "Knowledge chunking configuration input", - "description": "Chunking configuration applied when processing documents. On update this object is replaced wholesale rather than merged, so a caller preserving one key must read, modify, and write the whole object back." + "title": "Create knowledge base import part URLs request", + "description": "Multipart part numbers for which signed URLs should be created.", + "examples": [ + { + "partNumbers": [1, 2, 3] + } + ] }, - "CreateKnowledgeBaseRequest": { + "V2CompleteKnowledgeImportResponse": { "type": "object", "properties": { - "workspaceId": { - "type": "string", - "minLength": 1, - "maxLength": 128, - "description": "Workspace in which to create the knowledge base." - }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 255, - "description": "Human-readable knowledge base name.", - "examples": ["Product Documentation"] - }, - "description": { - "description": "Optional knowledge base description.", - "examples": ["All product documentation and guides"], - "type": "string", - "maxLength": 10000 - }, - "chunkingConfig": { - "default": { - "maxSize": 1024, - "minSize": 100, - "overlap": 200 - }, - "description": "Chunking configuration; defaults are applied when omitted.", - "$ref": "#/components/schemas/V2KnowledgeChunkingConfigInput" - }, - "folderPath": { - "description": "Containing folder path; omission creates the knowledge base at the root.", - "$ref": "#/components/schemas/FolderPathInput" + "data": { + "description": "Response data.", + "$ref": "#/components/schemas/V2KnowledgeImport" } }, - "required": ["workspaceId", "name"], + "required": ["data"], "additionalProperties": false, - "title": "Create knowledge base request", - "description": "Workspace, name, description, chunking configuration, and folder placement." + "title": "Complete knowledge base import response", + "description": "The import lifecycle resource once processing has started." }, "UpdateKnowledgeBaseRequest": { "type": "object", @@ -7746,67 +8701,6 @@ "description": "Provider transfer strategy for a knowledge document upload.", "title": "Knowledge upload transfer" }, - "V2PutUploadTransfer": { - "type": "object", - "properties": { - "method": { - "type": "string", - "const": "put", - "description": "Upload strategy discriminator." - }, - "url": { - "type": "string", - "format": "uri", - "description": "Signed URL to which the file bytes are uploaded. Upload bytes with `PUT` and exactly the supplied headers; never construct or modify the signed URL. Treat any `2xx` as success. Sim-hosted URLs return an empty `204` and v2 JSON errors. Object-storage URLs may return `200` or `201` and provider-specific errors, often XML." - }, - "headers": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string" - }, - "description": "Headers that must be included with the upload request." - }, - "expiresAt": { - "type": "string", - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", - "description": "ISO 8601 expiration time for this signed URL. This is the URL's own expiry and is normally earlier than the upload session's expiresAt: the session stays open for later part, status, completion, and abort requests, but the bytes must be uploaded before this time. Once it passes, the storage provider rejects the upload and a new upload session must be created." - } - }, - "required": ["method", "url", "headers", "expiresAt"], - "additionalProperties": false, - "title": "Direct upload transfer", - "description": "Instructions for uploading bytes to one signed URL." - }, - "V2MultipartUploadTransfer": { - "type": "object", - "properties": { - "method": { - "type": "string", - "const": "multipart", - "description": "Upload strategy discriminator." - }, - "partSize": { - "type": "integer", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "description": "Required size of each non-final part in bytes." - }, - "partCount": { - "type": "integer", - "exclusiveMinimum": 0, - "maximum": 640, - "description": "Total number of upload parts." - } - }, - "required": ["method", "partSize", "partCount"], - "additionalProperties": false, - "title": "Multipart upload transfer", - "description": "Instructions for splitting bytes into a multipart upload." - }, "V2CreateKnowledgeDocumentUploadData": { "type": "object", "properties": { @@ -7950,59 +8844,6 @@ "title": "Knowledge document upload response", "description": "Current state of a knowledge document upload session." }, - "V2UploadPartUrl": { - "type": "object", - "properties": { - "partNumber": { - "type": "integer", - "minimum": 1, - "maximum": 9007199254740991, - "description": "Multipart part number." - }, - "url": { - "type": "string", - "format": "uri", - "description": "Signed URL for this upload part. Upload bytes with `PUT` and exactly the supplied headers; never construct or modify the signed URL. Treat any `2xx` as success. Sim-hosted URLs return an empty `204` and v2 JSON errors. Object-storage URLs may return `200` or `201` and provider-specific errors, often XML. Do not retain part `ETag` values; after every part succeeds, call the completion endpoint without a request body." - }, - "headers": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "string" - }, - "description": "Headers that must be included with the part upload." - }, - "expiresAt": { - "type": "string", - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", - "description": "ISO 8601 expiration time for the signed URL." - } - }, - "required": ["partNumber", "url", "headers", "expiresAt"], - "additionalProperties": false, - "title": "Upload part URL", - "description": "A signed URL and required headers for one multipart upload part." - }, - "V2PartUrlsData": { - "type": "object", - "properties": { - "parts": { - "maxItems": 100, - "type": "array", - "items": { - "$ref": "#/components/schemas/V2UploadPartUrl" - }, - "description": "Signed URLs for requested parts." - } - }, - "required": ["parts"], - "additionalProperties": false, - "title": "Upload part URLs", - "description": "Signed transfer URLs for the requested multipart upload parts." - }, "V2KnowledgeDocumentUploadPartUrlsResponse": { "type": "object", "properties": { diff --git a/apps/sim/app/api/files/uploads/finalizers.ts b/apps/sim/app/api/files/uploads/finalizers.ts index 4ce5a6cb3cb..4f9eec1be35 100644 --- a/apps/sim/app/api/files/uploads/finalizers.ts +++ b/apps/sim/app/api/files/uploads/finalizers.ts @@ -124,6 +124,7 @@ export async function finalizeUploadPurpose({ case 'execution_attachment': return finalizeExecutionAttachment(session) case 'table_import': + case 'knowledge_import': case 'knowledge_document': throw new UploadSessionError( 'validation', @@ -154,6 +155,7 @@ export async function loadCompletedUploadPurpose( case 'mothership_attachment': case 'execution_attachment': case 'table_import': + case 'knowledge_import': case 'knowledge_document': throw new UploadSessionError( 'internal', diff --git a/apps/sim/app/api/table/[tableId]/delete-async/route.ts b/apps/sim/app/api/table/[tableId]/delete-async/route.ts index 96587b83d34..4ac28aa8772 100644 --- a/apps/sim/app/api/table/[tableId]/delete-async/route.ts +++ b/apps/sim/app/api/table/[tableId]/delete-async/route.ts @@ -4,8 +4,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { deleteTableRowsAsyncContract } from '@/lib/api/contracts/tables' import { parseRequest } from '@/lib/api/server' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' -import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' -import { runDetached } from '@/lib/core/utils/background' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' import { generateRequestId } from '@/lib/core/utils/request' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import type { Filter } from '@/lib/table' @@ -16,6 +15,7 @@ import { assertRowDelete } from '@/lib/table/mutation-locks' import { toLegacyFilter } from '@/lib/table/query-builder/converters' import type { TableDeleteJobPayload } from '@/lib/table/types' import { accessError, checkAccess, tableFilterError } from '@/app/api/table/utils' +import type { tableDeleteTask } from '@/background/table-delete' const logger = createLogger('TableDeleteAsync') @@ -104,41 +104,26 @@ export const POST = withRouteHandler(async (request: NextRequest, { params }: Ro ) } - if (isTriggerDevEnabled) { - // Trigger.dev runs the delete outside the web container (survives deploys) and retries — - // safe: the keyset + cutoff walk just deletes whatever remains. - try { - const [{ tableDeleteTask }, { tasks }, { resolveTriggerRegion }] = await Promise.all([ - import('@/background/table-delete'), - import('@trigger.dev/sdk'), - import('@/lib/core/async-jobs/region'), - ]) - await tasks.trigger( - 'table-delete', - { jobId, tableId, workspaceId, filter, excludeRowIds, cutoff: cutoff.toISOString() }, - { tags: [`tableId:${tableId}`, `jobId:${jobId}`], region: await resolveTriggerRegion() } - ) - } catch (error) { - // A failed dispatch must not leave a ghost `running` job holding the - // table's one-write-job slot until the stale-job janitor fires. - await releaseJobClaim(tableId, jobId).catch(() => {}) - throw error - } - } else { - runDetached('table-delete', () => - runTableDelete({ - jobId, - tableId, - workspaceId, - filter, - excludeRowIds, - cutoff, - }).catch(async (error) => { - // No retry machinery on the detached path — fail the job immediately. - await markTableDeleteFailed(tableId, jobId, error) - throw error - }) + // Trigger.dev may retry the delete — safe: the keyset + cutoff walk just deletes whatever remains. + try { + await dispatchBackgroundTask( + 'table-delete', + { jobId, tableId, workspaceId, filter, excludeRowIds, cutoff: cutoff.toISOString() }, + { + runInProcess: (payload) => + runTableDelete({ ...payload, cutoff }).catch(async (error) => { + // No retry machinery on the detached path — fail the job immediately. + await markTableDeleteFailed(tableId, jobId, error) + throw error + }), + trigger: { tags: [`tableId:${tableId}`, `jobId:${jobId}`] }, + } ) + } catch (error) { + // A failed dispatch must not leave a ghost `running` job holding the + // table's one-write-job slot until the stale-job janitor fires. + await releaseJobClaim(tableId, jobId).catch(() => {}) + throw error } logger.info(`[${requestId}] Async row delete started`, { diff --git a/apps/sim/app/api/v2/knowledge/imports/[importId]/complete/route.ts b/apps/sim/app/api/v2/knowledge/imports/[importId]/complete/route.ts new file mode 100644 index 00000000000..bf0d9a52e7a --- /dev/null +++ b/apps/sim/app/api/v2/knowledge/imports/[importId]/complete/route.ts @@ -0,0 +1,24 @@ +import { v2CompleteKnowledgeImportContract } from '@/lib/api/contracts/v2/knowledge' +import { defineV2JsonRoute, v2ApiKeyAuth, v2RateLimits } from '@/lib/api/server/routes' +import { v2KnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { completeKnowledgeImport } from '@/lib/knowledge/application/imports' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { presentV2KnowledgeImport } from '@/app/api/v2/knowledge/imports/presenters' + +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +export const POST = defineV2JsonRoute({ + contract: v2CompleteKnowledgeImportContract, + operation: knowledgeOperations.importComplete, + auth: v2ApiKeyAuth, + rateLimit: v2RateLimits.publicApi, + errorPolicy: v2KnowledgeErrorPolicies.concealImportAuthorization, + mapInput: ({ params, query, headers }) => ({ + importId: params.importId, + workspaceId: query.workspaceId, + uploadToken: headers['upload-token'], + }), + useCase: completeKnowledgeImport, + present: presentV2KnowledgeImport, +}) diff --git a/apps/sim/app/api/v2/knowledge/imports/[importId]/parts/route.ts b/apps/sim/app/api/v2/knowledge/imports/[importId]/parts/route.ts new file mode 100644 index 00000000000..1379f650804 --- /dev/null +++ b/apps/sim/app/api/v2/knowledge/imports/[importId]/parts/route.ts @@ -0,0 +1,24 @@ +import { v2CreateKnowledgeImportPartUrlsContract } from '@/lib/api/contracts/v2/knowledge' +import { defineV2JsonRoute, v2ApiKeyAuth, v2RateLimits } from '@/lib/api/server/routes' +import { v2KnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { createKnowledgeImportParts } from '@/lib/knowledge/application/imports' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' + +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +export const POST = defineV2JsonRoute({ + contract: v2CreateKnowledgeImportPartUrlsContract, + operation: knowledgeOperations.importParts, + auth: v2ApiKeyAuth, + rateLimit: v2RateLimits.publicApi, + errorPolicy: v2KnowledgeErrorPolicies.concealImportAuthorization, + mapInput: ({ params, query, headers, body }) => ({ + importId: params.importId, + workspaceId: query.workspaceId, + uploadToken: headers['upload-token'], + partNumbers: body.partNumbers, + }), + useCase: createKnowledgeImportParts, + present: (result) => ({ data: result }), +}) diff --git a/apps/sim/app/api/v2/knowledge/imports/[importId]/route.ts b/apps/sim/app/api/v2/knowledge/imports/[importId]/route.ts new file mode 100644 index 00000000000..c9d30560e8c --- /dev/null +++ b/apps/sim/app/api/v2/knowledge/imports/[importId]/route.ts @@ -0,0 +1,42 @@ +import { + v2CancelKnowledgeImportContract, + v2GetKnowledgeImportContract, +} from '@/lib/api/contracts/v2/knowledge' +import { defineV2JsonRoute, v2ApiKeyAuth, v2RateLimits } from '@/lib/api/server/routes' +import { v2KnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { cancelKnowledgeImport, readKnowledgeImport } from '@/lib/knowledge/application/imports' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { presentV2KnowledgeImport } from '@/app/api/v2/knowledge/imports/presenters' + +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +export const GET = defineV2JsonRoute({ + contract: v2GetKnowledgeImportContract, + operation: knowledgeOperations.importRead, + auth: v2ApiKeyAuth, + rateLimit: v2RateLimits.publicApi, + errorPolicy: v2KnowledgeErrorPolicies.concealImportAuthorization, + mapInput: ({ params, query, headers }) => ({ + importId: params.importId, + workspaceId: query.workspaceId, + uploadToken: headers['upload-token'], + }), + useCase: readKnowledgeImport, + present: presentV2KnowledgeImport, +}) + +export const DELETE = defineV2JsonRoute({ + contract: v2CancelKnowledgeImportContract, + operation: knowledgeOperations.importCancel, + auth: v2ApiKeyAuth, + rateLimit: v2RateLimits.publicApi, + errorPolicy: v2KnowledgeErrorPolicies.concealImportAuthorization, + mapInput: ({ params, query, headers }) => ({ + importId: params.importId, + workspaceId: query.workspaceId, + uploadToken: headers['upload-token'], + }), + useCase: cancelKnowledgeImport, + present: presentV2KnowledgeImport, +}) diff --git a/apps/sim/app/api/v2/knowledge/imports/presenters.ts b/apps/sim/app/api/v2/knowledge/imports/presenters.ts new file mode 100644 index 00000000000..5a05e4bd492 --- /dev/null +++ b/apps/sim/app/api/v2/knowledge/imports/presenters.ts @@ -0,0 +1,37 @@ +import type { + V2CreateKnowledgeImportData, + V2KnowledgeImport, +} from '@/lib/api/contracts/v2/knowledge' +import type { + CreateKnowledgeImportResult, + KnowledgeImportResource, +} from '@/lib/knowledge/application/imports' + +function toV2KnowledgeImport(resource: KnowledgeImportResource): V2KnowledgeImport { + return { + ...resource, + createdAt: resource.createdAt.toISOString(), + updatedAt: resource.updatedAt.toISOString(), + completedAt: resource.completedAt?.toISOString() ?? null, + } +} + +export function presentV2KnowledgeImport({ + import: resource, +}: { + import: KnowledgeImportResource +}) { + return { data: toV2KnowledgeImport(resource) } +} + +export function presentV2CreateKnowledgeImport(result: CreateKnowledgeImportResult): { + data: V2CreateKnowledgeImportData +} { + return { + data: { + session: toV2KnowledgeImport(result.import), + uploadToken: result.upload.uploadToken, + transfer: result.upload.transfer, + }, + } +} diff --git a/apps/sim/app/api/v2/knowledge/imports/route.ts b/apps/sim/app/api/v2/knowledge/imports/route.ts new file mode 100644 index 00000000000..dbf99def928 --- /dev/null +++ b/apps/sim/app/api/v2/knowledge/imports/route.ts @@ -0,0 +1,20 @@ +import { v2CreateKnowledgeImportContract } from '@/lib/api/contracts/v2/knowledge' +import { defineV2JsonRoute, v2ApiKeyAuth, v2RateLimits } from '@/lib/api/server/routes' +import { v2KnowledgeErrorPolicies } from '@/lib/knowledge/api/route-policies' +import { createKnowledgeImport } from '@/lib/knowledge/application/imports' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { presentV2CreateKnowledgeImport } from '@/app/api/v2/knowledge/imports/presenters' + +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +export const POST = defineV2JsonRoute({ + contract: v2CreateKnowledgeImportContract, + operation: knowledgeOperations.importCreate, + auth: v2ApiKeyAuth, + rateLimit: v2RateLimits.publicApi, + errorPolicy: v2KnowledgeErrorPolicies.usage, + mapInput: ({ body }) => ({ body }), + useCase: createKnowledgeImport, + present: presentV2CreateKnowledgeImport, +}) diff --git a/apps/sim/background/cleanup-stale-executions.test.ts b/apps/sim/background/cleanup-stale-executions.test.ts index 6f552046988..d06ed9b9d23 100644 --- a/apps/sim/background/cleanup-stale-executions.test.ts +++ b/apps/sim/background/cleanup-stale-executions.test.ts @@ -301,9 +301,9 @@ describe('stale execution cleanup deadline grace', () => { it('claims every cleanup page without overlapping concurrent workers', async () => { await runCleanupStaleExecutions() - // Nine batched arms: the connector sync-log retention pass is the newest. - expect(dbChainMockFns.transaction).toHaveBeenCalledTimes(9) - expect(dbChainMockFns.for).toHaveBeenCalledTimes(9) + // Eleven batched arms: the knowledge import stale and retention passes are the newest. + expect(dbChainMockFns.transaction).toHaveBeenCalledTimes(11) + expect(dbChainMockFns.for).toHaveBeenCalledTimes(11) for (const [strength, options] of dbChainMockFns.for.mock.calls) { expect(strength).toBe('update') expect(options).toEqual({ skipLocked: true }) @@ -372,7 +372,7 @@ describe('stale execution cleanup deadline grace', () => { expect(mockDeleteFile).toHaveBeenCalledTimes(1000) const limits = dbChainMockFns.limit.mock.calls.map(([limit]) => limit) - expect(limits.filter((limit) => limit === 100)).toHaveLength(20) + expect(limits.filter((limit) => limit === 100)).toHaveLength(22) expect(limits.filter((limit) => limit === 1000)).toHaveLength(30) expect(limits.filter((limit) => limit === 2000)).toHaveLength(12) diff --git a/apps/sim/background/cleanup-stale-executions.ts b/apps/sim/background/cleanup-stale-executions.ts index 198ca2eab97..1d2eb7ffb0f 100644 --- a/apps/sim/background/cleanup-stale-executions.ts +++ b/apps/sim/background/cleanup-stale-executions.ts @@ -1,6 +1,8 @@ import { db } from '@sim/db' import { asyncJobs, + document, + knowledgeBaseImport, knowledgeConnectorSyncLog, tableJobs, workflowDeploymentOperation, @@ -25,6 +27,7 @@ import { RESERVATION_TTL_BUFFER_MS, } from '@/lib/core/execution-limits' import type { DbTransaction } from '@/lib/db/types' +import { KNOWLEDGE_IMPORT_STORAGE_CONTEXT } from '@/lib/knowledge/transfer/import-jobs' import { elapsedDurationMsSql } from '@/lib/logs/execution/duration' import { STALE_SWEEPABLE_EXECUTION_STATUSES, @@ -55,6 +58,16 @@ const EXECUTION_DEADLINE_ERROR = getTimeoutErrorMessage() const TABLE_JOB_STALE_THRESHOLD_MINUTES = 95 /** Terminal table-jobs older than this are pruned; only the latest job per table is ever read. */ const TABLE_JOB_RETENTION_HOURS = 24 +/** + * A knowledge import heartbeats after every document, and its task runs at most + * 90 minutes, so a `running` import silent for longer than this lost its worker. + */ +const KNOWLEDGE_IMPORT_STALE_THRESHOLD_MINUTES = 95 +/** Settled knowledge imports stay readable this long, so a caller can still fetch the outcome. */ +const KNOWLEDGE_IMPORT_RETENTION_DAYS = 7 +/** Each stale import deletes its uploaded bundle, so these pages stay small. */ +const KNOWLEDGE_IMPORT_BATCH_SIZE = 100 +const KNOWLEDGE_IMPORT_MAX_ROWS_PER_RUN = 1000 /** * A table run dispatch whose holder has not made progress for this long is * treated as dead. Same rule as the table-job threshold above, measured from the @@ -148,6 +161,18 @@ async function runBatchedMutation({ return { affected, reachedLimit: affected >= maxRowsPerRun } } +/** Deletes import bundles one at a time; a bundle already gone is not an error. */ +async function deleteKnowledgeImportBundles(imports: { sourceKey: string }[]): Promise { + for (const { sourceKey } of imports) { + await deleteFile({ key: sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }).catch((err) => { + logger.warn('Failed to delete a knowledge import bundle', { + sourceKey, + error: toError(err).message, + }) + }) + } +} + /** Settles everything a dead worker left unfinished and prunes expired bookkeeping rows. */ export async function runCleanupStaleExecutions() { logger.info('Starting stale execution cleanup job') @@ -451,6 +476,107 @@ export async function runCleanupStaleExecutions() { }) } + /** + * Fail knowledge imports whose worker died, and delete the bundle that worker + * would have deleted in its `finally`. Documents it already imported stay in + * the base, as they would after a cancel; one it was indexing in-process has + * no queue behind it, so it is failed for the user to retry. Settled imports + * are pruned later, deleting any bundle a canceled or crashed worker left. + */ + let staleKnowledgeImportsMarkedFailed = 0 + try { + const staleKnowledgeImportThreshold = new Date( + now.getTime() - KNOWLEDGE_IMPORT_STALE_THRESHOLD_MINUTES * 60 * 1000 + ) + const staleKnowledgeImportPredicate = and( + eq(knowledgeBaseImport.status, 'running'), + lt(knowledgeBaseImport.updatedAt, staleKnowledgeImportThreshold) + ) + const staleKnowledgeImportResult = await runBatchedMutation({ + batchSize: KNOWLEDGE_IMPORT_BATCH_SIZE, + maxRowsPerRun: KNOWLEDGE_IMPORT_MAX_ROWS_PER_RUN, + claim: (tx, limit) => + tx + .select({ id: knowledgeBaseImport.id }) + .from(knowledgeBaseImport) + .where(staleKnowledgeImportPredicate) + .limit(limit) + .for('update', { skipLocked: true }), + mutation: (tx, candidateIds) => + tx + .update(knowledgeBaseImport) + .set({ + status: 'failed', + error: `Import stopped: no progress for more than ${KNOWLEDGE_IMPORT_STALE_THRESHOLD_MINUTES} minutes (worker timeout or crash)`, + completedAt: now, + updatedAt: now, + }) + .where(and(staleKnowledgeImportPredicate, inArray(knowledgeBaseImport.id, candidateIds))) + .returning({ + sourceKey: knowledgeBaseImport.sourceKey, + knowledgeBaseId: knowledgeBaseImport.knowledgeBaseId, + }), + onBatch: async (imports) => { + const knowledgeBaseIds = imports.flatMap(({ knowledgeBaseId }) => + knowledgeBaseId ? [knowledgeBaseId] : [] + ) + if (knowledgeBaseIds.length > 0) { + await db + .update(document) + .set({ + processingStatus: 'failed', + processingError: 'The import stopped before this document finished indexing', + processingCompletedAt: now, + }) + .where( + and( + inArray(document.knowledgeBaseId, knowledgeBaseIds), + eq(document.processingStatus, 'processing'), + isNull(document.processingQueueToken), + lt(document.processingStartedAt, staleKnowledgeImportThreshold) + ) + ) + } + await deleteKnowledgeImportBundles(imports) + }, + }) + staleKnowledgeImportsMarkedFailed = staleKnowledgeImportResult.affected + if (staleKnowledgeImportsMarkedFailed > 0) { + logger.info(`Marked ${staleKnowledgeImportsMarkedFailed} stale knowledge imports as failed`) + } + + const knowledgeImportRetention = new Date( + now.getTime() - KNOWLEDGE_IMPORT_RETENTION_DAYS * 24 * 60 * 60 * 1000 + ) + const settledKnowledgeImportPredicate = and( + inArray(knowledgeBaseImport.status, ['completed', 'failed', 'canceled']), + lt(knowledgeBaseImport.updatedAt, knowledgeImportRetention) + ) + await runBatchedMutation({ + batchSize: KNOWLEDGE_IMPORT_BATCH_SIZE, + maxRowsPerRun: KNOWLEDGE_IMPORT_MAX_ROWS_PER_RUN, + claim: (tx, limit) => + tx + .select({ id: knowledgeBaseImport.id }) + .from(knowledgeBaseImport) + .where(settledKnowledgeImportPredicate) + .limit(limit) + .for('update', { skipLocked: true }), + mutation: (tx, candidateIds) => + tx + .delete(knowledgeBaseImport) + .where( + and(settledKnowledgeImportPredicate, inArray(knowledgeBaseImport.id, candidateIds)) + ) + .returning({ sourceKey: knowledgeBaseImport.sourceKey }), + onBatch: deleteKnowledgeImportBundles, + }) + } catch (error) { + logger.error('Failed to clean up stale knowledge imports:', { + error: toError(error).message, + }) + } + // Clean up stale pending jobs (never started, e.g., due to server crash before startJob()) let stalePendingJobsMarkedFailed = 0 @@ -773,6 +899,10 @@ export async function runCleanupStaleExecutions() { tableJobs: { staleMarkedFailed: staleTableJobsMarkedFailed, }, + knowledgeImports: { + staleMarkedFailed: staleKnowledgeImportsMarkedFailed, + thresholdMinutes: KNOWLEDGE_IMPORT_STALE_THRESHOLD_MINUTES, + }, connectorSyncLogs: { pruned: connectorSyncLogsPruned, retentionDays: CONNECTOR_SYNC_LOG_RETENTION_DAYS, diff --git a/apps/sim/background/knowledge-import.ts b/apps/sim/background/knowledge-import.ts new file mode 100644 index 00000000000..7688b4d0b3f --- /dev/null +++ b/apps/sim/background/knowledge-import.ts @@ -0,0 +1,28 @@ +import { task } from '@trigger.dev/sdk' +import { + type KnowledgeImportPayload, + runKnowledgeImport, +} from '@/lib/knowledge/transfer/import-runner' + +/** + * Trigger.dev wrapper around `runKnowledgeImport`. The import's lifecycle lives + * in the `knowledge_base_import` state machine, so the task is a thin shell. + * + * `maxAttempts: 1` — a blind re-run would create a second knowledge base beside + * the first attempt's. A crashed import is marked failed by the runner's own + * catch, or by the stale-job janitor if the process died; the user re-imports. + * `medium-1x` because a document's original file, up to 100 MB, is held in + * memory while it is stored. + */ +export const knowledgeImportTask = task({ + id: 'knowledge-import', + machine: 'medium-1x', + retry: { maxAttempts: 1 }, + queue: { + name: 'knowledge-import', + concurrencyLimit: 10, + }, + run: async (payload: KnowledgeImportPayload) => { + await runKnowledgeImport(payload) + }, +}) diff --git a/apps/sim/lib/api/contracts/v2/knowledge.ts b/apps/sim/lib/api/contracts/v2/knowledge.ts index 185ec13cb60..2aab9f6129c 100644 --- a/apps/sim/lib/api/contracts/v2/knowledge.ts +++ b/apps/sim/lib/api/contracts/v2/knowledge.ts @@ -44,6 +44,7 @@ import { v2TimestampSchema, } from '@/lib/api/contracts/v2/shared' import { + v2OptionalUploadTokenHeadersSchema, v2PartUrlsBodySchema, v2PartUrlsDataSchema, v2UploadStatusSchema, @@ -63,7 +64,10 @@ import { KNOWLEDGE_DOCUMENT_UPLOAD_RECIPES, knowledgeDocumentUploadMetadataSchema, } from '@/lib/knowledge/upload-metadata' -import { MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE } from '@/lib/uploads/shared/types' +import { + MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE, + MAX_WORKSPACE_FILE_SIZE, +} from '@/lib/uploads/shared/types' /** * v2 knowledge contracts. @@ -803,6 +807,206 @@ export const v2ExportKnowledgeBaseContract = defineRouteContract({ response: { mode: 'binary' }, }) +const v2KnowledgeImportParamsSchema = z.object({ + importId: z.string().min(1).describe('Unique knowledge-base import identifier.'), +}) + +const v2KnowledgeImportWorkspaceQuerySchema = z + .object({ + workspaceId: workspaceIdSchema.describe('Workspace that owns the import.'), + }) + .strict() + +const v2KnowledgeImportOptionalUploadTokenHeadersSchema = v2OptionalUploadTokenHeadersSchema.extend( + { + 'upload-token': v2OptionalUploadTokenHeadersSchema.shape['upload-token'].describe( + 'Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.' + ), + } +) + +const v2KnowledgeImportSourceSchema = z + .object({ + type: z.literal('upload').describe('Upload-backed import discriminator.'), + name: z + .string() + .trim() + .min(1, 'name is required') + .max(255) + .describe('Bundle filename, as produced by a knowledge base export.'), + contentType: z + .string() + .trim() + .min(1, 'contentType is required') + .max(255) + .describe('Bundle MIME type, normally application/zip.'), + size: z + .number() + .int() + .min(1) + .max(MAX_WORKSPACE_FILE_SIZE) + .describe('Exact bundle size in bytes; the maximum is 5 GiB.'), + }) + .strict() + .meta({ + id: 'V2KnowledgeImportSource', + title: 'Knowledge base import source', + description: 'Bundle archive uploaded through signed transfer instructions.', + }) + +const v2CreateKnowledgeImportBodySchema = z + .object({ + workspaceId: workspaceIdSchema.describe('Workspace in which to create the knowledge base.'), + name: v1CreateKnowledgeBaseBodySchema.shape.name + .optional() + .describe("Name for the new knowledge base; defaults to the bundle's own name.") + .meta({ examples: ['Product Documentation'] }), + source: v2KnowledgeImportSourceSchema, + }) + .strict() +export type V2CreateKnowledgeImportBody = z.input + +/** + * `uploading` until the archive's upload completes, then `processing` while the + * base and its documents are created. There is no `queued`: the durable record + * is written as the runner is dispatched. + */ +const v2KnowledgeImportStatusSchema = z.enum([ + 'uploading', + 'processing', + 'completed', + 'failed', + 'canceled', + 'expired', +]) +export type V2KnowledgeImportStatus = z.output + +const v2KnowledgeImportFailureSchema = z + .object({ + filename: z.string().describe('Filename of the document that was not imported.'), + message: z.string().describe('Why the document was not imported.'), + }) + .strict() + .meta({ + id: 'V2KnowledgeImportFailure', + title: 'Knowledge import failure', + description: 'One bundle document the import could not bring over.', + }) + +const v2KnowledgeImportSchema = z + .object({ + id: z.string().describe('Unique knowledge-base import identifier.'), + workspaceId: z.string().describe('Workspace that owns the import.'), + status: v2KnowledgeImportStatusSchema.describe('Current import lifecycle state.'), + knowledgeBaseId: z + .string() + .nullable() + .describe('Knowledge base the import created, or null until it exists.'), + documentsTotal: z + .number() + .int() + .nonnegative() + .describe('Documents the bundle carries; zero until its manifest has been read.'), + documentsImported: z + .number() + .int() + .nonnegative() + .describe( + 'Documents created so far. A document whose vectors could not be reused is indexed afterwards, as an upload is, so it may still be processing in the knowledge base.' + ), + documentsFailed: z + .number() + .int() + .nonnegative() + .describe('Documents that could not be imported. Non-zero still allows `completed`.'), + vectorsReused: z + .boolean() + .describe( + "Whether the bundle's vectors matched this deployment's embedding model and were stored without re-embedding." + ), + failures: z + .array(v2KnowledgeImportFailureSchema) + .describe('Bounded sample of the documents that could not be imported.'), + error: z.string().nullable().describe('Terminal failure reason, or null.'), + createdAt: v2TimestampSchema.describe('ISO 8601 creation timestamp.'), + updatedAt: v2TimestampSchema.describe('ISO 8601 last-update timestamp.'), + completedAt: v2TimestampSchema.nullable().describe('ISO 8601 completion timestamp, or null.'), + }) + .meta({ + id: 'V2KnowledgeImport', + title: 'Knowledge base import', + description: 'Durable lifecycle resource for importing a knowledge base bundle.', + }) +export type V2KnowledgeImport = z.output + +const v2CreateKnowledgeImportDataSchema = z + .object({ + session: v2KnowledgeImportSchema.describe('Created import, waiting for its upload.'), + uploadToken: z.string().min(1).describe('Signed token for upload control requests.'), + transfer: v2UploadTransferSchema.describe('Signed bundle upload instructions.'), + }) + .strict() + .meta({ + id: 'V2CreateKnowledgeImportData', + title: 'Create knowledge base import data', + description: 'Created import and the instructions for uploading its bundle.', + }) +export type V2CreateKnowledgeImportData = z.output + +export const v2CreateKnowledgeImportContract = defineRouteContract({ + method: 'POST', + path: '/api/v2/knowledge/imports', + query: noInputSchema, + body: v2CreateKnowledgeImportBodySchema, + response: { + mode: 'json', + schema: v2DataResponse(v2CreateKnowledgeImportDataSchema), + status: 201, + }, +}) + +/** + * Reads an import in any of its states. The optional upload token makes the + * upload phase readable: the durable record is written only once the upload + * completes, so without it the id the 201 returned would 404 until then. + */ +export const v2GetKnowledgeImportContract = defineRouteContract({ + method: 'GET', + path: '/api/v2/knowledge/imports/[importId]', + params: v2KnowledgeImportParamsSchema, + query: v2KnowledgeImportWorkspaceQuerySchema, + headers: v2KnowledgeImportOptionalUploadTokenHeadersSchema, + response: { mode: 'json', schema: v2DataResponse(v2KnowledgeImportSchema) }, +}) + +export const v2CancelKnowledgeImportContract = defineRouteContract({ + method: 'DELETE', + path: '/api/v2/knowledge/imports/[importId]', + params: v2KnowledgeImportParamsSchema, + query: v2KnowledgeImportWorkspaceQuerySchema, + headers: v2KnowledgeImportOptionalUploadTokenHeadersSchema, + response: { mode: 'json', schema: v2DataResponse(v2KnowledgeImportSchema) }, +}) + +export const v2CreateKnowledgeImportPartUrlsContract = defineRouteContract({ + method: 'POST', + path: '/api/v2/knowledge/imports/[importId]/parts', + params: v2KnowledgeImportParamsSchema, + query: v2KnowledgeImportWorkspaceQuerySchema, + headers: v2UploadTokenHeadersSchema, + body: v2PartUrlsBodySchema, + response: { mode: 'json', schema: v2DataResponse(v2PartUrlsDataSchema) }, +}) + +export const v2CompleteKnowledgeImportContract = defineRouteContract({ + method: 'POST', + path: '/api/v2/knowledge/imports/[importId]/complete', + params: v2KnowledgeImportParamsSchema, + query: v2KnowledgeImportWorkspaceQuerySchema, + headers: v2UploadTokenHeadersSchema, + response: { mode: 'json', schema: v2DataResponse(v2KnowledgeImportSchema) }, +}) + /** * PATCH, not PUT: every mutable field is optional and a `superRefine` requires * at least one, so this is a partial update rather than a replacement. diff --git a/apps/sim/lib/api/contracts/v2/openapi/knowledge.ts b/apps/sim/lib/api/contracts/v2/openapi/knowledge.ts index 25ceaba8ac4..0b1b09e43c9 100644 --- a/apps/sim/lib/api/contracts/v2/openapi/knowledge.ts +++ b/apps/sim/lib/api/contracts/v2/openapi/knowledge.ts @@ -2,12 +2,16 @@ import { v2AbortKnowledgeDocumentUploadContract, v2AddWorkspaceFilesToKnowledgeBaseContract, v2BulkUpdateKnowledgeDocumentsContract, + v2CancelKnowledgeImportContract, v2CompleteKnowledgeDocumentUploadContract, + v2CompleteKnowledgeImportContract, v2CreateKnowledgeBaseContract, v2CreateKnowledgeConnectorContract, v2CreateKnowledgeDocumentUploadContract, v2CreateKnowledgeDocumentUploadPartUrlsContract, v2CreateKnowledgeFolderContract, + v2CreateKnowledgeImportContract, + v2CreateKnowledgeImportPartUrlsContract, v2DeleteKnowledgeBaseContract, v2DeleteKnowledgeConnectorContract, v2DeleteKnowledgeDocumentContract, @@ -16,6 +20,7 @@ import { v2GetKnowledgeBaseContract, v2GetKnowledgeConnectorContract, v2GetKnowledgeDocumentContract, + v2GetKnowledgeImportContract, v2ListKnowledgeBasesContract, v2ListKnowledgeConnectorDocumentsContract, v2ListKnowledgeConnectorsContract, @@ -67,6 +72,7 @@ import { MAX_KNOWLEDGE_BUNDLE_DOCUMENTS } from '@/lib/knowledge/constants' const WORKSPACE_ID = 'a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64' const KNOWLEDGE_BASE_ID = '7c9e6679-7425-40de-944b-e07fc1f90ae7' const KNOWLEDGE_CONNECTOR_ID = 'kc-9f8e7d6c' +const KNOWLEDGE_IMPORT_ID = '5e8a2c4f-1d7b-4396-a0e3-8f6b2d9c1a47' const KNOWLEDGE_CONNECTOR_EXAMPLE = { id: KNOWLEDGE_CONNECTOR_ID, @@ -232,6 +238,205 @@ const declaredRoutes = [ ), } ), + defineOpenApiRoute( + v2CreateKnowledgeImportContract, + knowledgeOperation({ + applicationOperation: knowledgeOperations.importCreate, + operationId: 'createKnowledgeImport', + summary: 'Create knowledge base import', + description: + 'Start importing a knowledge base bundle produced by an export. The response carries signed transfer instructions for the archive; once its bytes are uploaded, complete the import to create the knowledge base. Bundles must be `.zip` archives of at most 5 GiB.', + errors: [...WORKSPACE_ERRORS, 'NotFound', 'PayloadTooLarge', 'UsageLimitExceeded'], + success: { description: 'The created import and its upload instructions.' }, + }), + { + query: v2CreateKnowledgeImportContract.query, + body: documentedSchema( + v2CreateKnowledgeImportContract.body, + 'CreateKnowledgeImportRequest', + 'Create knowledge base import request', + 'Workspace, bundle archive, and an optional name for the new knowledge base.', + [ + { + workspaceId: WORKSPACE_ID, + name: 'Product Documentation', + source: { + type: 'upload', + name: 'product-documentation.simkb.zip', + contentType: 'application/zip', + size: 7340032, + }, + }, + ] + ), + response: documentedSchema( + v2CreateKnowledgeImportContract.response.schema, + 'V2CreateKnowledgeImportResponse', + 'Create knowledge base import response', + 'The import and the instructions for uploading its bundle.' + ), + } + ), + defineOpenApiRoute( + v2GetKnowledgeImportContract, + knowledgeOperation({ + applicationOperation: knowledgeOperations.importRead, + operationId: 'getKnowledgeImport', + summary: 'Get knowledge base import', + description: + "Get an import's progress and outcome. During `uploading`, the signed upload token is required; omitting it returns `404`.", + errors: RESOURCE_ERRORS, + success: { description: 'The requested knowledge base import.' }, + }), + { + params: documentedSchema( + v2GetKnowledgeImportContract.params, + 'GetKnowledgeImportParams', + 'Get knowledge base import path parameters', + 'Import selected for retrieval.', + [{ importId: KNOWLEDGE_IMPORT_ID }] + ), + query: documentedSchema( + v2GetKnowledgeImportContract.query, + 'GetKnowledgeImportQuery', + 'Get knowledge base import query', + 'Workspace scope for the import.' + ), + headers: documentedSchema( + v2GetKnowledgeImportContract.headers, + 'GetKnowledgeImportHeaders', + 'Get knowledge base import headers', + 'Optional signed upload control token for the import.' + ), + response: documentedSchema( + v2GetKnowledgeImportContract.response.schema, + 'V2KnowledgeImportResponse', + 'Knowledge base import response', + 'A knowledge base import lifecycle resource.' + ), + } + ), + defineOpenApiRoute( + v2CancelKnowledgeImportContract, + knowledgeOperation({ + applicationOperation: knowledgeOperations.importCancel, + operationId: 'cancelKnowledgeImport', + summary: 'Cancel knowledge base import', + description: + 'Cancel an import. During its upload the transfer is aborted; while processing, it stops after the document in flight and the documents already imported stay in the new knowledge base. Settled imports return `409`.', + errors: RESOURCE_CONFLICT_ERRORS, + success: { description: 'The canceled knowledge base import.' }, + }), + { + params: documentedSchema( + v2CancelKnowledgeImportContract.params, + 'CancelKnowledgeImportParams', + 'Cancel knowledge base import path parameters', + 'Import selected for cancellation.' + ), + query: documentedSchema( + v2CancelKnowledgeImportContract.query, + 'CancelKnowledgeImportQuery', + 'Cancel knowledge base import query', + 'Workspace scope for the import.' + ), + headers: documentedSchema( + v2CancelKnowledgeImportContract.headers, + 'CancelKnowledgeImportHeaders', + 'Cancel knowledge base import headers', + 'Optional signed upload control token for the import.' + ), + response: documentedSchema( + v2CancelKnowledgeImportContract.response.schema, + 'V2CancelKnowledgeImportResponse', + 'Cancel knowledge base import response', + 'The canceled knowledge base import.' + ), + } + ), + defineOpenApiRoute( + v2CreateKnowledgeImportPartUrlsContract, + knowledgeOperation({ + applicationOperation: knowledgeOperations.importParts, + operationId: 'createKnowledgeImportPartUrls', + summary: 'Create knowledge base import part URLs', + description: + 'Create signed URLs for multipart bundle upload parts. Requires the `uploading` state; other states return `409`.', + errors: RESOURCE_CONFLICT_ERRORS, + success: { description: 'The signed multipart upload URLs.' }, + }), + { + params: documentedSchema( + v2CreateKnowledgeImportPartUrlsContract.params, + 'CreateKnowledgeImportPartUrlsParams', + 'Create knowledge base import part URLs path parameters', + 'Import receiving uploaded parts.' + ), + query: documentedSchema( + v2CreateKnowledgeImportPartUrlsContract.query, + 'CreateKnowledgeImportPartUrlsQuery', + 'Create knowledge base import part URLs query', + 'Workspace scope for the import.' + ), + headers: documentedSchema( + v2CreateKnowledgeImportPartUrlsContract.headers, + 'CreateKnowledgeImportPartUrlsHeaders', + 'Create knowledge base import part URLs headers', + 'Signed upload control token for the import.' + ), + body: documentedSchema( + v2CreateKnowledgeImportPartUrlsContract.body, + 'CreateKnowledgeImportPartUrlsRequest', + 'Create knowledge base import part URLs request', + 'Multipart part numbers for which signed URLs should be created.', + [{ partNumbers: [1, 2, 3] }] + ), + response: documentedSchema( + v2CreateKnowledgeImportPartUrlsContract.response.schema, + 'V2CreateKnowledgeImportPartUrlsResponse', + 'Create knowledge base import part URLs response', + 'Signed URLs and required headers for each requested upload part.' + ), + } + ), + defineOpenApiRoute( + v2CompleteKnowledgeImportContract, + knowledgeOperation({ + applicationOperation: knowledgeOperations.importComplete, + operationId: 'completeKnowledgeImport', + summary: 'Complete knowledge base import upload', + description: + "Verify the uploaded bundle and start creating the knowledge base under the same import ID. Vectors are reused when the bundle was embedded with this deployment's model; otherwise documents are re-indexed. Completion records an audit event. Repeating it returns the running import.", + errors: [...RESOURCE_CONFLICT_ERRORS, 'UsageLimitExceeded'], + success: { description: 'The knowledge base import after its upload completed.' }, + }), + { + params: documentedSchema( + v2CompleteKnowledgeImportContract.params, + 'CompleteKnowledgeImportParams', + 'Complete knowledge base import path parameters', + 'Import whose upload should be completed.' + ), + query: documentedSchema( + v2CompleteKnowledgeImportContract.query, + 'CompleteKnowledgeImportQuery', + 'Complete knowledge base import query', + 'Workspace scope for the import.' + ), + headers: documentedSchema( + v2CompleteKnowledgeImportContract.headers, + 'CompleteKnowledgeImportHeaders', + 'Complete knowledge base import headers', + 'Signed upload control token for the import.' + ), + response: documentedSchema( + v2CompleteKnowledgeImportContract.response.schema, + 'V2CompleteKnowledgeImportResponse', + 'Complete knowledge base import response', + 'The import lifecycle resource once processing has started.' + ), + } + ), defineOpenApiRoute( v2UpdateKnowledgeBaseContract, knowledgeOperation({ diff --git a/apps/sim/lib/api/mcp/generated/v2-operations.ts b/apps/sim/lib/api/mcp/generated/v2-operations.ts index 4c274046247..f56b0e612f6 100644 --- a/apps/sim/lib/api/mcp/generated/v2-operations.ts +++ b/apps/sim/lib/api/mcp/generated/v2-operations.ts @@ -97,12 +97,16 @@ import { v2AbortKnowledgeDocumentUploadContract, v2AddWorkspaceFilesToKnowledgeBaseContract, v2BulkUpdateKnowledgeDocumentsContract, + v2CancelKnowledgeImportContract, v2CompleteKnowledgeDocumentUploadContract, + v2CompleteKnowledgeImportContract, v2CreateKnowledgeBaseContract, v2CreateKnowledgeConnectorContract, v2CreateKnowledgeDocumentUploadContract, v2CreateKnowledgeDocumentUploadPartUrlsContract, v2CreateKnowledgeFolderContract, + v2CreateKnowledgeImportContract, + v2CreateKnowledgeImportPartUrlsContract, v2DeleteKnowledgeBaseContract, v2DeleteKnowledgeConnectorContract, v2DeleteKnowledgeDocumentContract, @@ -110,6 +114,7 @@ import { v2GetKnowledgeBaseContract, v2GetKnowledgeConnectorContract, v2GetKnowledgeDocumentContract, + v2GetKnowledgeImportContract, v2ListKnowledgeBasesContract, v2ListKnowledgeConnectorDocumentsContract, v2ListKnowledgeConnectorsContract, @@ -512,6 +517,14 @@ export const V2_MCP_OPERATIONS = { handler: () => import('@/app/api/v2/tables/[tableId]/rows/bulk-update/route').then((route) => route.POST), }, + cancelKnowledgeImport: { + contract: v2CancelKnowledgeImportContract, + summary: 'Cancel knowledge base import', + description: + 'Cancel an import. During its upload the transfer is aborted; while processing, it stops after the document in flight and the documents already imported stay in the new knowledge base. Settled imports return `409`.\n\nOAuth scope: `api:write`.', + handler: () => + import('@/app/api/v2/knowledge/imports/[importId]/route').then((route) => route.DELETE), + }, cancelOrganizationAccessRequest: { contract: v2CancelOrganizationAccessRequestContract, summary: 'Cancel organization access request', @@ -611,6 +624,16 @@ export const V2_MCP_OPERATIONS = { '@/app/api/v2/knowledge/[knowledgeBaseId]/documents/uploads/[uploadId]/complete/route' ).then((route) => route.POST), }, + completeKnowledgeImport: { + contract: v2CompleteKnowledgeImportContract, + summary: 'Complete knowledge base import upload', + description: + "Verify the uploaded bundle and start creating the knowledge base under the same import ID. Vectors are reused when the bundle was embedded with this deployment's model; otherwise documents are re-indexed. Completion records an audit event. Repeating it returns the running import.\n\nOAuth scope: `api:write`.", + handler: () => + import('@/app/api/v2/knowledge/imports/[importId]/complete/route').then( + (route) => route.POST + ), + }, completeTableImport: { contract: v2CompleteTableImportContract, summary: 'Complete table import upload', @@ -718,6 +741,21 @@ export const V2_MCP_OPERATIONS = { 'Create a folder in the knowledge-base folder tree. Workspace folder trees exceeding 10,000 folders return `413`.\n\nOAuth scope: `api:write`.', handler: () => import('@/app/api/v2/knowledge/folders/route').then((route) => route.POST), }, + createKnowledgeImport: { + contract: v2CreateKnowledgeImportContract, + summary: 'Create knowledge base import', + description: + 'Start importing a knowledge base bundle produced by an export. The response carries signed transfer instructions for the archive; once its bytes are uploaded, complete the import to create the knowledge base. Bundles must be `.zip` archives of at most 5 GiB.\n\nOAuth scope: `api:write`.', + handler: () => import('@/app/api/v2/knowledge/imports/route').then((route) => route.POST), + }, + createKnowledgeImportPartUrls: { + contract: v2CreateKnowledgeImportPartUrlsContract, + summary: 'Create knowledge base import part URLs', + description: + 'Create signed URLs for multipart bundle upload parts. Requires the `uploading` state; other states return `409`.\n\nOAuth scope: `api:write`.', + handler: () => + import('@/app/api/v2/knowledge/imports/[importId]/parts/route').then((route) => route.POST), + }, createKnowledgeTag: { contract: v2CreateKnowledgeTagContract, summary: 'Create tag', @@ -1328,6 +1366,14 @@ export const V2_MCP_OPERATIONS = { (route) => route.GET ), }, + getKnowledgeImport: { + contract: v2GetKnowledgeImportContract, + summary: 'Get knowledge base import', + description: + "Get an import's progress and outcome. During `uploading`, the signed upload token is required; omitting it returns `404`.\n\nOAuth scope: `api:read`.", + handler: () => + import('@/app/api/v2/knowledge/imports/[importId]/route').then((route) => route.GET), + }, getLog: { contract: v2GetLogContract, summary: 'Get log', diff --git a/apps/sim/lib/api/server/routes/v2-route-table.generated.ts b/apps/sim/lib/api/server/routes/v2-route-table.generated.ts index 173f838e7fc..97242c2b333 100644 --- a/apps/sim/lib/api/server/routes/v2-route-table.generated.ts +++ b/apps/sim/lib/api/server/routes/v2-route-table.generated.ts @@ -274,6 +274,22 @@ export const V2_ROUTES: readonly V2RouteEntry[] = [ pattern: '/api/v2/knowledge/folders', load: () => import('@/app/api/v2/knowledge/folders/route'), }, + { + pattern: '/api/v2/knowledge/imports', + load: () => import('@/app/api/v2/knowledge/imports/route'), + }, + { + pattern: '/api/v2/knowledge/imports/{importId}', + load: () => import('@/app/api/v2/knowledge/imports/[importId]/route'), + }, + { + pattern: '/api/v2/knowledge/imports/{importId}/complete', + load: () => import('@/app/api/v2/knowledge/imports/[importId]/complete/route'), + }, + { + pattern: '/api/v2/knowledge/imports/{importId}/parts', + load: () => import('@/app/api/v2/knowledge/imports/[importId]/parts/route'), + }, { pattern: '/api/v2/knowledge/search', load: () => import('@/app/api/v2/knowledge/search/route'), diff --git a/apps/sim/lib/core/application/authorized-workspace-use-case.ts b/apps/sim/lib/core/application/authorized-workspace-use-case.ts index 233c51e9d74..618f0d2fc62 100644 --- a/apps/sim/lib/core/application/authorized-workspace-use-case.ts +++ b/apps/sim/lib/core/application/authorized-workspace-use-case.ts @@ -1,6 +1,12 @@ -import { type AuditActionType, type AuditResourceTypeValue, recordAudit } from '@sim/audit' +import { + type AuditActionType, + type AuditResourceTypeValue, + recordAudit, + recordAuditOnce, +} from '@sim/audit' import type { Principal, PrincipalAuditAttribution } from '@sim/auth/principal' import { resolvePrincipalAuditAttribution } from '@sim/auth/principal' +import { createLogger } from '@sim/logger' import { runDeclaredContentOperation } from '@/lib/core/application/content-delivery' import type { ApplicationOperation, OperationUseCase } from '@/lib/core/application/operation' import { @@ -18,6 +24,8 @@ import { runWithOutboundOrganization } from '@/lib/core/network/context.server' import type { OrchestrationRequestContext } from '@/lib/core/orchestration/types' import type { ResourcePolicyBinding } from '@/lib/resource-policies/registry' +const logger = createLogger('WorkspaceUseCaseAudit') + export interface WorkspaceUseCaseAuditEntry { /** Canonical affected workspace; null keeps an organization event outside the authorization workspace. */ workspaceId?: string | null @@ -27,6 +35,11 @@ export interface WorkspaceUseCaseAuditEntry { resourceName?: string description?: string metadata?: Record + /** + * Records the entry at most once for this key, for an operation a caller may + * retry after losing its response: each retry projects the same entry again. + */ + idempotencyKey?: string } export interface AuthorizedWorkspaceUseCaseContext< @@ -106,8 +119,8 @@ export function recordProjectedUseCaseAuditEntries( organizationId?: string ): void { const attribution: PrincipalAuditAttribution = resolvePrincipalAuditAttribution(principal) - for (const entry of entries) { - recordAudit({ + for (const { idempotencyKey, ...entry } of entries) { + const params = { workspaceId: entry.workspaceId === undefined ? workspaceId : entry.workspaceId, actorId: attribution.actorId, actorName: attribution.actorName, @@ -123,6 +136,13 @@ export function recordProjectedUseCaseAuditEntries( actor: attribution.actor, }, request, + } + if (!idempotencyKey) { + recordAudit(params) + continue + } + recordAuditOnce(idempotencyKey, params).catch((error) => { + logger.error('Failed to record audit log', { error, action: params.action }) }) } } diff --git a/apps/sim/lib/core/async-jobs/background-task.ts b/apps/sim/lib/core/async-jobs/background-task.ts new file mode 100644 index 00000000000..9ffa0882eca --- /dev/null +++ b/apps/sim/lib/core/async-jobs/background-task.ts @@ -0,0 +1,32 @@ +import type { AnyTask, TaskIdentifier, TaskPayload, TriggerOptions } from '@trigger.dev/sdk' +import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' +import { runDetached } from '@/lib/core/utils/background' + +/** + * Starts one run of a background task: on Trigger.dev, in the region the + * deployment routes to, when Trigger.dev is enabled; otherwise detached in this + * process through the runner the task wraps. A caller names its task by type + * alone (`import type`), and the SDK loads only on the Trigger.dev path, so + * neither enters the caller's static import graph. + */ +export async function dispatchBackgroundTask( + id: TaskIdentifier, + payload: TaskPayload, + options: { + runInProcess: (payload: TaskPayload) => Promise + trigger?: Omit + } +): Promise { + if (!isTriggerDevEnabled) { + runDetached(id, () => options.runInProcess(payload)) + return + } + const [{ tasks }, { resolveTriggerRegion }] = await Promise.all([ + import('@trigger.dev/sdk'), + import('@/lib/core/async-jobs/region'), + ]) + await tasks.trigger(id, payload, { + ...options.trigger, + region: await resolveTriggerRegion(), + }) +} diff --git a/apps/sim/lib/execution/remote-sandbox/image-registry.ts b/apps/sim/lib/execution/remote-sandbox/image-registry.ts index bfbadb008ee..99815a31c0b 100644 --- a/apps/sim/lib/execution/remote-sandbox/image-registry.ts +++ b/apps/sim/lib/execution/remote-sandbox/image-registry.ts @@ -6,12 +6,11 @@ import { sleep } from '@sim/utils/helpers' import { generateId } from '@sim/utils/id' import { backoffWithJitter } from '@sim/utils/retry' import { and, eq, inArray, lt, notInArray, or, type SQL, sql } from 'drizzle-orm' -import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' import { recordSandboxCliBuildFailure, recordSandboxImageCleanupFailure, } from '@/lib/core/execution-limits/metrics' -import { runDetached } from '@/lib/core/utils/background' import { buildTimeoutError, providerBuildError, @@ -28,6 +27,7 @@ import { type SandboxImageStatus, type SandboxProviderId, } from '@/lib/execution/remote-sandbox/types' +import type { sandboxImageBuildTask } from '@/background/sandbox-image-build' const logger = createLogger('SandboxImageRegistry') @@ -284,28 +284,20 @@ async function enqueueSandboxImageBuild( payload: SandboxImageBuildPayload, attemptAt: Date ): Promise { - if (!isTriggerDevEnabled) { - runDetached('sandbox-image-build', () => runSandboxImageBuild(payload)) - return - } - // Dynamically imported so Trigger.dev stays out of the web bundle's static graph. - const [{ sandboxImageBuildTask }, { tasks }, { resolveTriggerRegion }] = await Promise.all([ - import('@/background/sandbox-image-build'), - import('@trigger.dev/sdk'), - import('@/lib/core/async-jobs/region'), - ]) - await tasks.trigger(SANDBOX_IMAGE_BUILD_TASK_ID, payload, { - // Keyed by the claim, not by the spec alone. Concurrent saves are already - // collapsed by the conditional update above — only one caller gets a row back, - // so only one reaches here. A spec-only key would instead suppress the *next* - // legitimate attempt: Trigger.dev returns the finished run rather than starting - // one, leaving the row `pending` with no worker and unclaimable until it goes - // stale. That is half an hour of a save-to-retry doing nothing. - idempotencyKey: sandboxBuildIdempotencyKey(payload.provider, payload.specHash, attemptAt), - // Still short, so even a duplicate delivery of one attempt cannot linger. - idempotencyKeyTTL: '5m', - tags: [`sandboxSpec:${payload.specHash}`], - region: await resolveTriggerRegion(), + await dispatchBackgroundTask(SANDBOX_IMAGE_BUILD_TASK_ID, payload, { + runInProcess: runSandboxImageBuild, + trigger: { + // Keyed by the claim, not by the spec alone. Concurrent saves are already + // collapsed by the conditional update above — only one caller gets a row back, + // so only one reaches here. A spec-only key would instead suppress the *next* + // legitimate attempt: Trigger.dev returns the finished run rather than starting + // one, leaving the row `pending` with no worker and unclaimable until it goes + // stale. That is half an hour of a save-to-retry doing nothing. + idempotencyKey: sandboxBuildIdempotencyKey(payload.provider, payload.specHash, attemptAt), + // Still short, so even a duplicate delivery of one attempt cannot linger. + idempotencyKeyTTL: '5m', + tags: [`sandboxSpec:${payload.specHash}`], + }, }) } diff --git a/apps/sim/lib/knowledge/__integration__/bundle-import.integration.ts b/apps/sim/lib/knowledge/__integration__/bundle-import.integration.ts new file mode 100644 index 00000000000..20d62af4932 --- /dev/null +++ b/apps/sim/lib/knowledge/__integration__/bundle-import.integration.ts @@ -0,0 +1,771 @@ +/** A real export, imported back through the runner, against PostgreSQL and local storage. */ +import { mkdtempSync } from 'node:fs' +import { rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import path from 'node:path' +import { db } from '@sim/db' +import { + auditLog, + document, + embedding, + knowledgeBase, + knowledgeBaseImport, + knowledgeBaseTagDefinitions, + organization, + outboxEvent, + uploadSession, + user, + workspace, +} from '@sim/db/schema' +import { deleteWorkspaceFixture } from '@sim/db/testing/workspace-fixtures' +import { sha256Hex } from '@sim/security/hash' +import { generateId } from '@sim/utils/id' +import { and, asc, eq, inArray, sql } from 'drizzle-orm' +import JSZip from 'jszip' +import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest' + +const fixture = vi.hoisted(() => ({ + root: '', + embedded: 0, + target: { model: 'text-embedding-3-small', dimensions: 1536 as const }, +})) +vi.mock('@/lib/uploads/core/setup.server', () => ({ + get UPLOAD_DIR_SERVER() { + return fixture.root + }, +})) +vi.mock('@/lib/embeddings', async () => ({ + ...(await import('@/lib/embeddings/client')), + assertKnowledgeEmbeddingCapacity: async () => {}, + embedKnowledge: async (texts: string[]) => { + fixture.embedded += texts.length + return { + embeddings: texts.map(() => [0, 0, 1, ...Array(1533).fill(0)]), + totalTokens: texts.length, + billableTokens: 0, + isBYOK: true, + modelName: fixture.target.model, + pricingId: fixture.target.model, + } + }, +})) +vi.mock('@/lib/knowledge/embeddings', async (importOriginal) => ({ + ...(await importOriginal()), + getConfiguredKbEmbedding: async () => fixture.target, +})) + +import { resolveBillingAttribution } from '@/lib/billing/core/attribution' +import { + createKnowledgeAclFixtureIds, + seedKnowledgeAclFixture, +} from '@/lib/knowledge/__integration__/seed-source-access-fixture' +import { exportKnowledgeBase } from '@/lib/knowledge/application/exports' +import { + completeKnowledgeImport, + createKnowledgeImport, + readKnowledgeImport, +} from '@/lib/knowledge/application/imports' +import { KNOWLEDGE_DOCUMENT_PROCESSING_OUTBOX_EVENT } from '@/lib/knowledge/documents/processing-events' +import { KNOWLEDGE_STORAGE_CLEANUP_EVENT } from '@/lib/knowledge/documents/storage-cleanup-event' +import { buildKnowledgeBundleArchive } from '@/lib/knowledge/transfer/export-archive' +import { + findKnowledgeImport, + insertKnowledgeImport, + KNOWLEDGE_IMPORT_STORAGE_CONTEXT, + stopKnowledgeImport, +} from '@/lib/knowledge/transfer/import-jobs' +import { runKnowledgeImport } from '@/lib/knowledge/transfer/import-runner' +import { embeddingVectorColumn, embeddingVectorValues } from '@/lib/knowledge/vector-columns' +import { downloadFile, uploadFile } from '@/lib/uploads/core/storage-service' +import { writeLocalPutObject } from '@/lib/uploads/upload-session/provider' +import { uploadSessionObjectMetadata } from '@/lib/uploads/upload-session/service' +import { runCleanupStaleExecutions } from '@/background/cleanup-stale-executions' + +const ids = createKnowledgeAclFixtureIds() +const session = { kind: 'session' as const, userId: ids.aliceId, sessionId: generateId() } +const FIRST_VECTOR = [1, ...Array(1535).fill(0)] +const SECOND_VECTOR = [0, 1, ...Array(1534).fill(0)] + +async function seedSourceDocument(options: { + filename: string + chunks: { content: string; vector: number[]; enabled: boolean }[] + enabled: boolean + inlineFile: boolean +}) { + const text = options.chunks.map((chunk) => chunk.content).join('\n') + const id = generateId() + await db.insert(document).values({ + id, + knowledgeBaseId: ids.knowledgeBaseId, + filename: options.filename, + fileUrl: options.inlineFile + ? `data:text/plain;base64,${Buffer.from(text).toString('base64')}` + : '', + fileSize: options.inlineFile ? Buffer.byteLength(text) : 0, + mimeType: 'text/plain', + processingStatus: 'completed', + chunkCount: options.chunks.length, + tokenCount: options.chunks.length * 4, + characterCount: text.length, + enabled: options.enabled, + tag1: 'public', + acl: ['ws'], + aclRequirements: [], + aclVerifiedAt: new Date(), + }) + await db.insert(embedding).values( + options.chunks.map((chunk, chunkIndex) => ({ + id: generateId(), + documentId: id, + knowledgeBaseId: ids.knowledgeBaseId, + chunkIndex, + ...embeddingVectorValues(1536, chunk.vector), + chunkHash: sha256Hex(chunk.content), + content: chunk.content, + contentLength: chunk.content.length, + tokenCount: 4, + startOffset: 0, + endOffset: chunk.content.length, + enabled: chunk.enabled, + tag1: 'public', + })) + ) +} + +async function exportedBundleBytes(): Promise { + const bundle = await exportKnowledgeBase.execute({ + principal: session, + input: { + knowledgeBaseId: ids.knowledgeBaseId, + assertedWorkspaceId: ids.workspaceId, + vectors: true, + }, + }) + const buffers: Buffer[] = [] + for await (const chunk of buildKnowledgeBundleArchive(bundle)) buffers.push(Buffer.from(chunk)) + return Buffer.concat(buffers) +} + +/** Exports the fixture base and stages the archive where a completed import upload leaves it. */ +async function stageExportedBundle(importId: string): Promise { + return stageBundleBytes(importId, await exportedBundleBytes()) +} + +async function stageBundleBytes(importId: string, bytes: Buffer): Promise { + const sourceKey = `knowledge-import/${ids.workspaceId}/${importId}/bundle.simkb.zip` + await uploadFile({ + file: bytes, + fileName: 'bundle.simkb.zip', + contentType: 'application/zip', + context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT, + customKey: sourceKey, + preserveKey: true, + persistMetadata: false, + }) + await insertKnowledgeImport({ + id: importId, + workspaceId: ids.workspaceId, + userId: ids.aliceId, + sourceKey, + }) + return sourceKey +} + +async function runImport(importId: string, sourceKey: string, name: string) { + await runKnowledgeImport(await importPayload(importId, sourceKey, name)) + const record = await findKnowledgeImport({ importId, assertedWorkspaceId: ids.workspaceId }) + if (!record) throw new Error('Import record disappeared') + return record +} + +async function importPayload(importId: string, sourceKey: string, name: string) { + return { + importId, + workspaceId: ids.workspaceId, + userId: ids.aliceId, + name, + sourceKey, + billingAttribution: await resolveBillingAttribution({ + actorUserId: ids.aliceId, + workspaceId: ids.workspaceId, + }), + } +} + +async function importedDocuments(knowledgeBaseId: string) { + return db + .select({ + id: document.id, + filename: document.filename, + fileUrl: document.fileUrl, + mimeType: document.mimeType, + enabled: document.enabled, + processingStatus: document.processingStatus, + chunkCount: document.chunkCount, + tag1: document.tag1, + }) + .from(document) + .where(eq(document.knowledgeBaseId, knowledgeBaseId)) + .orderBy(asc(document.filename)) +} + +async function importedChunks(documentId: string) { + return db + .select({ + content: embedding.content, + enabled: embedding.enabled, + tag1: embedding.tag1, + vector: embeddingVectorColumn(1536), + }) + .from(embedding) + .where(eq(embedding.documentId, documentId)) + .orderBy(asc(embedding.chunkIndex)) +} + +beforeAll(async () => { + fixture.root = mkdtempSync(path.join(tmpdir(), 'sim-knowledge-import-')) + await seedKnowledgeAclFixture(ids) + await seedSourceDocument({ + filename: 'handbook.txt', + inlineFile: true, + enabled: true, + chunks: [ + { content: 'Refunds are issued within 14 days.', vector: FIRST_VECTOR, enabled: true }, + { content: 'Archived policy text.', vector: SECOND_VECTOR, enabled: false }, + ], + }) + await seedSourceDocument({ + filename: 'notes.txt', + inlineFile: false, + enabled: false, + chunks: [ + { content: 'Chunk text with no original file.', vector: SECOND_VECTOR, enabled: true }, + ], + }) +}) +afterEach(() => { + fixture.embedded = 0 + fixture.target = { model: 'text-embedding-3-small', dimensions: 1536 } +}) +afterAll(async () => { + const workspaceBases = sql`SELECT ${knowledgeBase.id} FROM ${knowledgeBase} WHERE ${knowledgeBase.workspaceId} = ${ids.workspaceId}` + await db + .delete(outboxEvent) + .where( + sql`${outboxEvent.payload}::jsonb ->> 'knowledgeBaseId' IN (${workspaceBases}) OR ${outboxEvent.payload}::jsonb ->> 'documentId' IN (SELECT ${document.id} FROM ${document} WHERE ${document.knowledgeBaseId} IN (${workspaceBases}))` + ) + await db.delete(auditLog).where(eq(auditLog.workspaceId, ids.workspaceId)) + await db.delete(knowledgeBase).where(eq(knowledgeBase.workspaceId, ids.workspaceId)) + await deleteWorkspaceFixture(db, eq(workspace.id, ids.workspaceId)) + await db.delete(organization).where(eq(organization.id, ids.organizationId)) + await db.delete(user).where(inArray(user.id, [ids.aliceId, ids.bobId])) + await rm(fixture.root, { recursive: true, force: true }) + await db.$client.end() +}) + +describe('knowledge base bundle import', () => { + it('recreates an exported base and indexes it from the bundle when the embedding model matches', async () => { + const importId = generateId() + const sourceKey = await stageExportedBundle(importId) + + const record = await runImport(importId, sourceKey, 'Imported fixture') + + expect(record).toMatchObject({ + status: 'completed', + documentsTotal: 2, + documentsImported: 2, + documentsFailed: 0, + vectorsReused: true, + failures: [], + error: null, + }) + const knowledgeBaseId = record.knowledgeBaseId + if (!knowledgeBaseId) throw new Error('Import did not link its knowledge base') + const [created] = await db + .select() + .from(knowledgeBase) + .where(eq(knowledgeBase.id, knowledgeBaseId)) + expect(created).toMatchObject({ + name: 'Imported fixture', + workspaceId: ids.workspaceId, + userId: ids.aliceId, + embeddingModel: 'text-embedding-3-small', + chunkingConfig: { maxSize: 1024, minSize: 1, overlap: 20 }, + }) + expect( + await db + .select({ + tagSlot: knowledgeBaseTagDefinitions.tagSlot, + displayName: knowledgeBaseTagDefinitions.displayName, + }) + .from(knowledgeBaseTagDefinitions) + .where(eq(knowledgeBaseTagDefinitions.knowledgeBaseId, knowledgeBaseId)) + ).toEqual([{ tagSlot: 'tag1', displayName: 'Fixture' }]) + + const [handbook, notes] = await importedDocuments(knowledgeBaseId) + expect(handbook).toMatchObject({ + filename: 'handbook.txt', + enabled: true, + processingStatus: 'completed', + chunkCount: 2, + tag1: 'public', + }) + expect(handbook.fileUrl).toMatch(/^\/api\/files\/serve\/kb\/.+\?context=knowledge-base$/) + expect( + await db + .select({ status: outboxEvent.status }) + .from(outboxEvent) + .where( + and( + eq(outboxEvent.eventType, KNOWLEDGE_STORAGE_CLEANUP_EVENT), + sql`${outboxEvent.payload}::jsonb ->> 'documentId' = ${handbook.id}` + ) + ) + ).toEqual([{ status: 'completed' }]) + expect(notes).toMatchObject({ + filename: 'notes.txt', + mimeType: 'text/plain', + enabled: false, + processingStatus: 'completed', + chunkCount: 1, + }) + expect( + ( + await downloadFile({ + key: decodeURIComponent(notes.fileUrl.split('?')[0].replace('/api/files/serve/', '')), + context: 'knowledge-base', + }) + ).toString() + ).toBe('Chunk text with no original file.') + expect(await importedChunks(handbook.id)).toEqual([ + { + content: 'Refunds are issued within 14 days.', + enabled: true, + tag1: 'public', + vector: FIRST_VECTOR, + }, + { content: 'Archived policy text.', enabled: false, tag1: 'public', vector: SECOND_VECTOR }, + ]) + expect(fixture.embedded).toBe(0) + await expect( + downloadFile({ key: sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }) + ).rejects.toThrow() + }) + + it('queues documents with a file for processing and re-embeds chunk-only ones when the model differs', async () => { + fixture.target = { model: 'text-embedding-3-large', dimensions: 1536 } + const importId = generateId() + const sourceKey = await stageExportedBundle(importId) + + const record = await runImport(importId, sourceKey, 'Re-embedded fixture') + + expect(record).toMatchObject({ + status: 'completed', + documentsImported: 2, + documentsFailed: 0, + vectorsReused: false, + }) + const knowledgeBaseId = record.knowledgeBaseId + if (!knowledgeBaseId) throw new Error('Import did not link its knowledge base') + const [handbook, notes] = await importedDocuments(knowledgeBaseId) + expect(handbook.processingStatus).toBe('pending') + expect(await importedChunks(handbook.id)).toEqual([]) + const queued = await db + .select({ id: outboxEvent.id }) + .from(outboxEvent) + .where( + and( + eq(outboxEvent.eventType, KNOWLEDGE_DOCUMENT_PROCESSING_OUTBOX_EVENT), + sql`${outboxEvent.payload}::jsonb ->> 'documentId' = ${handbook.id}` + ) + ) + expect(queued).toHaveLength(1) + expect(notes.processingStatus).toBe('completed') + expect(fixture.embedded).toBe(1) + expect(await importedChunks(notes.id)).toEqual([ + { + content: 'Chunk text with no original file.', + enabled: true, + tag1: 'public', + vector: [0, 0, 1, ...Array(1533).fill(0)], + }, + ]) + }) + + it('fails an archive that is not a bundle without creating a knowledge base', async () => { + const importId = generateId() + const sourceKey = await stageBundleBytes(importId, Buffer.from('not a zip archive')) + + const record = await runImport(importId, sourceKey, 'Never created') + + expect(record).toMatchObject({ + status: 'failed', + knowledgeBaseId: null, + error: 'Invalid knowledge base bundle: not a zip archive', + }) + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Never created')) + ).toEqual([]) + await expect( + downloadFile({ key: sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }) + ).rejects.toThrow() + }) + + it('fails a bundle with a damaged chunk entry before creating anything', async () => { + const zip = new JSZip() + zip.file('chunks/doc-1.ndjson', '{"index": 0, "content": "half a line"\n') + zip.file( + 'manifest.json', + JSON.stringify({ + version: 1, + exportedAt: '2026-10-01T00:00:00.000Z', + embedding: { model: 'text-embedding-3-small', dimension: 1536, vectorsIncluded: false }, + knowledgeBase: { + name: 'Damaged fixture', + description: null, + chunkingConfig: { maxSize: 1024, minSize: 1, overlap: 20 }, + }, + tags: [], + documents: [ + { + id: 'doc-1', + filename: 'notes.txt', + mimeType: 'text/plain', + fileSize: 0, + enabled: true, + tags: {}, + file: null, + chunks: 'chunks/doc-1.ndjson', + chunkCount: 1, + tokenCount: 1, + characterCount: 11, + }, + ], + }) + ) + const importId = generateId() + const sourceKey = await stageBundleBytes( + importId, + await zip.generateAsync({ type: 'nodebuffer' }) + ) + + const record = await runImport(importId, sourceKey, 'Damaged fixture') + + expect(record).toMatchObject({ status: 'failed', knowledgeBaseId: null, documentsTotal: 0 }) + expect(record.error).toContain('chunks/doc-1.ndjson line 1 is not valid JSON') + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Damaged fixture')) + ).toEqual([]) + }) + + it('creates no base for an import canceled before its worker reached it', async () => { + const importId = generateId() + const sourceKey = await stageExportedBundle(importId) + const staged = await findKnowledgeImport({ importId }) + if (!staged) throw new Error('Import was not staged') + await stopKnowledgeImport(staged) + + const record = await runImport(importId, sourceKey, 'Canceled fixture') + + expect(record).toMatchObject({ status: 'canceled', knowledgeBaseId: null }) + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Canceled fixture')) + ).toEqual([]) + await expect( + downloadFile({ key: sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }) + ).rejects.toThrow() + }) + + it('lets exactly one of two concurrent workers run an import', async () => { + const importId = generateId() + const sourceKey = await stageExportedBundle(importId) + const payload = await importPayload(importId, sourceKey, 'Claimed fixture') + + await Promise.all([runKnowledgeImport(payload), runKnowledgeImport(payload)]) + + expect(await findKnowledgeImport({ importId })).toMatchObject({ + status: 'completed', + knowledgeBaseId: importId, + documentsImported: 2, + documentsFailed: 0, + }) + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Claimed fixture')) + ).toEqual([{ id: importId }]) + }) + + it('fails without a partial base when the name is already taken', async () => { + const importId = generateId() + const sourceKey = await stageExportedBundle(importId) + + const record = await runImport(importId, sourceKey, 'Search fixture') + + expect(record.status).toBe('failed') + expect(record.knowledgeBaseId).toBeNull() + expect(record.error).toContain('A knowledge base named "Search fixture" already exists') + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where( + and( + eq(knowledgeBase.workspaceId, ids.workspaceId), + eq(knowledgeBase.name, 'Search fixture') + ) + ) + ).toEqual([{ id: ids.knowledgeBaseId }]) + await expect( + downloadFile({ key: sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }) + ).rejects.toThrow() + }) +}) + +describe('knowledge base import requests', () => { + const request = { headers: new Headers({ origin: 'http://localhost:3000' }) } + + it('creates an import, completes its upload once, and runs it to a new base', async () => { + const bytes = await exportedBundleBytes() + const created = await createKnowledgeImport.execute({ + principal: session, + input: { + body: { + workspaceId: ids.workspaceId, + name: 'Requested import', + source: { + type: 'upload', + name: 'fixture.simkb.zip', + contentType: 'application/zip', + size: bytes.length, + }, + }, + }, + request, + }) + expect(created.import).toMatchObject({ status: 'uploading', knowledgeBaseId: null }) + await writeLocalPutObject({ + uploadId: created.upload.id, + key: created.upload.finalKey, + body: new Blob([new Uint8Array(bytes)]).stream(), + expectedSize: bytes.length, + contentType: created.upload.contentType, + metadata: uploadSessionObjectMetadata(created.upload), + }) + const input = { + importId: created.import.id, + workspaceId: ids.workspaceId, + uploadToken: created.upload.uploadToken, + } + + const completed = await completeKnowledgeImport.execute({ principal: session, input, request }) + const repeated = await completeKnowledgeImport.execute({ principal: session, input, request }) + + expect(completed.import.id).toBe(created.import.id) + expect(repeated.import.id).toBe(created.import.id) + await expect + .poll( + async () => + (await readKnowledgeImport.execute({ principal: session, input })).import.status, + { interval: 50, timeout: 10_000 } + ) + .toBe('completed') + const { import: finished } = await readKnowledgeImport.execute({ principal: session, input }) + expect(finished).toMatchObject({ + documentsImported: 2, + documentsFailed: 0, + vectorsReused: true, + }) + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Requested import')) + ).toEqual([{ id: finished.knowledgeBaseId }]) + await expect + .poll(async () => + db + .select({ resourceId: auditLog.resourceId }) + .from(auditLog) + .where( + and( + eq(auditLog.workspaceId, ids.workspaceId), + eq(auditLog.action, 'knowledge_base.import_started') + ) + ) + ) + .toEqual([{ resourceId: finished.knowledgeBaseId }]) + }) + + it('starts an import whose first dispatch was lost when its completion is retried', async () => { + const bytes = await exportedBundleBytes() + const created = await createKnowledgeImport.execute({ + principal: session, + input: { + body: { + workspaceId: ids.workspaceId, + name: 'Redispatched import', + source: { + type: 'upload', + name: 'fixture.simkb.zip', + contentType: 'application/zip', + size: bytes.length, + }, + }, + }, + request, + }) + await writeLocalPutObject({ + uploadId: created.upload.id, + key: created.upload.finalKey, + body: new Blob([new Uint8Array(bytes)]).stream(), + expectedSize: bytes.length, + contentType: created.upload.contentType, + metadata: uploadSessionObjectMetadata(created.upload), + }) + // The record a completion wrote before the request died, with no worker behind it. + await insertKnowledgeImport({ + id: created.upload.id, + workspaceId: ids.workspaceId, + userId: ids.aliceId, + sourceKey: created.upload.storageKey, + }) + const input = { + importId: created.import.id, + workspaceId: ids.workspaceId, + uploadToken: created.upload.uploadToken, + } + + await completeKnowledgeImport.execute({ principal: session, input, request }) + + await expect + .poll( + async () => + (await readKnowledgeImport.execute({ principal: session, input })).import.status, + { interval: 50, timeout: 10_000 } + ) + .toBe('completed') + expect( + await db + .select({ id: knowledgeBase.id }) + .from(knowledgeBase) + .where(eq(knowledgeBase.name, 'Redispatched import')) + ).toEqual([{ id: created.import.id }]) + await expect + .poll(async () => + db + .select({ resourceId: auditLog.resourceId }) + .from(auditLog) + .where( + and( + eq(auditLog.workspaceId, ids.workspaceId), + eq(auditLog.resourceId, created.import.id) + ) + ) + ) + .toEqual([{ resourceId: created.import.id }]) + }) + + it('refuses a bundle that is not a zip archive before creating an upload', async () => { + const importUploads = () => + db + .select({ id: uploadSession.id }) + .from(uploadSession) + .where( + and( + eq(uploadSession.workspaceId, ids.workspaceId), + eq(uploadSession.purpose, 'knowledge_import') + ) + ) + const before = await importUploads() + await expect( + createKnowledgeImport.execute({ + principal: session, + input: { + body: { + workspaceId: ids.workspaceId, + source: { + type: 'upload', + name: 'fixture.tar', + contentType: 'application/x-tar', + size: 10, + }, + }, + }, + request, + }) + ).rejects.toThrow('A knowledge base bundle must be a .zip archive') + expect(await importUploads()).toEqual(before) + }) +}) + +describe('stale knowledge import cleanup', () => { + async function seedProcessingDocument(processingQueueToken: string | null) { + const id = generateId() + await db.insert(document).values({ + id, + knowledgeBaseId: ids.knowledgeBaseId, + filename: 'stranded.txt', + fileUrl: '', + fileSize: 0, + mimeType: 'text/plain', + processingStatus: 'processing', + processingStartedAt: new Date(Date.now() - 2 * 60 * 60 * 1000), + processingQueueToken, + }) + return id + } + + async function processingStatus(documentId: string) { + const [row] = await db + .select({ status: document.processingStatus }) + .from(document) + .where(eq(document.id, documentId)) + return row?.status + } + + it('fails an import whose worker went silent, its stranded documents, and its bundle, and prunes settled imports with theirs', async () => { + const staleId = generateId() + const staleBundle = await stageBundleBytes(staleId, Buffer.from('bundle bytes')) + const settledId = generateId() + const settledBundle = await stageBundleBytes(settledId, Buffer.from('bundle bytes')) + const stranded = await seedProcessingDocument(null) + const queued = await seedProcessingDocument('queue-token') + const longAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) + await db + .update(knowledgeBaseImport) + .set({ + knowledgeBaseId: ids.knowledgeBaseId, + updatedAt: new Date(Date.now() - 2 * 60 * 60 * 1000), + }) + .where(eq(knowledgeBaseImport.id, staleId)) + await db + .update(knowledgeBaseImport) + .set({ status: 'canceled', updatedAt: longAgo, completedAt: longAgo }) + .where(eq(knowledgeBaseImport.id, settledId)) + + await runCleanupStaleExecutions() + + const stale = await findKnowledgeImport({ importId: staleId }) + expect(stale).toMatchObject({ status: 'failed' }) + expect(stale?.error).toContain('no progress') + expect(await processingStatus(stranded)).toBe('failed') + expect(await processingStatus(queued)).toBe('processing') + expect(await findKnowledgeImport({ importId: settledId })).toBeNull() + for (const key of [staleBundle, settledBundle]) { + await expect( + downloadFile({ key, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }) + ).rejects.toThrow() + } + }) +}) diff --git a/apps/sim/lib/knowledge/api/route-policies.ts b/apps/sim/lib/knowledge/api/route-policies.ts index 80102c19bec..858d1c9076c 100644 --- a/apps/sim/lib/knowledge/api/route-policies.ts +++ b/apps/sim/lib/knowledge/api/route-policies.ts @@ -208,4 +208,8 @@ export const v2KnowledgeErrorPolicies = { notFoundMessage: 'Knowledge base not found', render: v2KnowledgeDocumentUploadErrorPolicy.render, }), + concealImportAuthorization: createV2ResourceConcealmentPolicy({ + notFoundMessage: 'Knowledge base import not found', + render: v2KnowledgeUsageErrorPolicy.render, + }), } as const diff --git a/apps/sim/lib/knowledge/application/billing.ts b/apps/sim/lib/knowledge/application/billing.ts index 3feb40b0ca4..cf4597ba712 100644 --- a/apps/sim/lib/knowledge/application/billing.ts +++ b/apps/sim/lib/knowledge/application/billing.ts @@ -71,3 +71,20 @@ export async function resolveKnowledgeUsageAdmission( const usage = await checkAttributedUsageLimits(billingAttribution) return { billingAttribution, usage, userId } } + +/** {@link resolveKnowledgeUsageAdmission}, refusing once the caller's usage limit is reached. */ +export async function assertKnowledgeUsageAdmitted( + principal: Principal, + context: KnowledgeResourceContext +) { + const { billingAttribution, usage, userId } = await resolveKnowledgeUsageAdmission( + principal, + context + ) + if (usage.isExceeded) { + throw new KnowledgeUsageLimitExceededError( + usage.message || 'Usage limit exceeded. Please upgrade your plan to continue.' + ) + } + return { billingAttribution, userId } +} diff --git a/apps/sim/lib/knowledge/application/imports.ts b/apps/sim/lib/knowledge/application/imports.ts new file mode 100644 index 00000000000..10c0c954925 --- /dev/null +++ b/apps/sim/lib/knowledge/application/imports.ts @@ -0,0 +1,459 @@ +import { AuditAction, AuditResourceType } from '@sim/audit' +import type { Principal } from '@sim/auth/principal' +import { createLogger } from '@sim/logger' +import { getErrorMessage } from '@sim/utils/errors' +import { generateId } from '@sim/utils/id' +import { isRecordLike } from '@sim/utils/object' +import type { + V2CreateKnowledgeImportBody, + V2KnowledgeImportStatus, +} from '@/lib/api/contracts/v2/knowledge' +import { + authorizeWorkspaceOperation, + capabilityGovernedPrincipalUserId, +} from '@/lib/core/application' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' +import { asOrchestrationError, OrchestrationError } from '@/lib/core/orchestration/types' +import { knowledgeDelegationPolicy } from '@/lib/knowledge/application/authorization' +import { defineAuthorizedKnowledgeUseCase } from '@/lib/knowledge/application/authorized-knowledge-use-case' +import { assertKnowledgeUsageAdmitted } from '@/lib/knowledge/application/billing' +import { + type KnowledgeWorkspaceContext, + resolveKnowledgeWorkspaceContext, +} from '@/lib/knowledge/application/contexts' +import { knowledgeOperations } from '@/lib/knowledge/application/operations' +import { + findKnowledgeImport, + getKnowledgeImport, + insertKnowledgeImport, + KNOWLEDGE_IMPORT_STORAGE_CONTEXT, + type KnowledgeImportFailure, + type KnowledgeImportRecord, + stopKnowledgeImport, +} from '@/lib/knowledge/transfer/import-jobs' +import { + type KnowledgeImportPayload, + runKnowledgeImport, +} from '@/lib/knowledge/transfer/import-runner' +import { assertWorkspaceCapability } from '@/lib/permission-groups/capability-assertions' +import { requestOrigin } from '@/lib/uploads/upload-session/application' +import { + abortUploadSession, + assertUploadSessionAuthBinding, + type CreatedUploadSession, + completeUploadSession, + createUploadPartUrls, + createUploadSession, + getOwnedUploadSession, + importStatusForUploadSession, + type UploadSessionRecord, +} from '@/lib/uploads/upload-session/service' +import type { knowledgeImportTask } from '@/background/knowledge-import' + +const logger = createLogger('KnowledgeImportApplication') + +/** Upload-session metadata key holding what the import was created with. */ +const IMPORT_METADATA_KEY = 'knowledgeImport' + +/** An import in either half of its life: its upload, then its durable record. */ +export interface KnowledgeImportResource { + id: string + workspaceId: string + status: V2KnowledgeImportStatus + knowledgeBaseId: string | null + documentsTotal: number + documentsImported: number + documentsFailed: number + vectorsReused: boolean + failures: KnowledgeImportFailure[] + error: string | null + createdAt: Date + updatedAt: Date + completedAt: Date | null +} + +interface CreateKnowledgeImportInput { + body: V2CreateKnowledgeImportBody +} + +interface KnowledgeImportInput { + importId: string + workspaceId: string + uploadToken?: string +} + +interface KnowledgeImportUploadInput extends KnowledgeImportInput { + uploadToken: string +} + +interface CreateKnowledgeImportPartsInput extends KnowledgeImportUploadInput { + partNumbers: number[] +} + +export interface CreateKnowledgeImportResult { + import: KnowledgeImportResource + upload: CreatedUploadSession +} + +interface KnowledgeImportResult { + import: KnowledgeImportResource +} + +interface KnowledgeImportRecordContext extends KnowledgeWorkspaceContext { + record: KnowledgeImportRecord +} + +interface KnowledgeImportUploadContext extends KnowledgeWorkspaceContext { + upload: UploadSessionRecord +} + +type KnowledgeImportContext = KnowledgeImportRecordContext | KnowledgeImportUploadContext + +function fromRecord(record: KnowledgeImportRecord): KnowledgeImportResource { + return { + id: record.id, + workspaceId: record.workspaceId, + status: record.status === 'running' ? 'processing' : record.status, + knowledgeBaseId: record.knowledgeBaseId, + documentsTotal: record.documentsTotal, + documentsImported: record.documentsImported, + documentsFailed: record.documentsFailed, + vectorsReused: record.vectorsReused, + failures: record.failures, + error: record.error, + createdAt: record.createdAt, + updatedAt: record.updatedAt, + completedAt: record.completedAt, + } +} + +function fromUpload(upload: UploadSessionRecord, workspaceId: string): KnowledgeImportResource { + return { + id: upload.id, + workspaceId, + status: importStatusForUploadSession(upload.status), + knowledgeBaseId: null, + documentsTotal: 0, + documentsImported: 0, + documentsFailed: 0, + vectorsReused: false, + failures: [], + error: null, + createdAt: upload.createdAt, + updatedAt: upload.updatedAt, + completedAt: upload.completedAt, + } +} + +/** The name override the import was created with, read back from its upload session. */ +function importedName(upload: UploadSessionRecord): string | undefined { + const stored = upload.metadata[IMPORT_METADATA_KEY] + if (!isRecordLike(stored) || typeof stored.name !== 'string') return undefined + return stored.name +} + +/** + * permission-group-enforced: knowledge.upload — an import creates a base, which + * the operations' `knowledge.create` governs, but it also fills that base with + * caller-supplied documents, which `knowledge.upload` governs everywhere else. + * An operation names one capability, so the second is asserted here. Keyed to + * the governed subject, which names nobody for an actorless run or an executor + * delegation; a copilot delegation stays governed. + */ +async function assertImportedDocumentsAllowed( + principal: Principal, + workspaceId: string +): Promise { + const actingUserId = capabilityGovernedPrincipalUserId(principal) + if (actingUserId) await assertWorkspaceCapability(actingUserId, workspaceId, 'knowledge.upload') +} + +async function resolveUploadContext( + principal: Principal, + input: KnowledgeImportUploadInput +): Promise { + const upload = await getOwnedUploadSession({ + uploadId: input.importId, + workspaceId: input.workspaceId, + purpose: 'knowledge_import', + uploadToken: input.uploadToken, + principal, + }) + if (upload.storageContext !== KNOWLEDGE_IMPORT_STORAGE_CONTEXT || !upload.workspaceId) { + throw new OrchestrationError('not_found', 'Knowledge base import not found') + } + return { + ...(await resolveKnowledgeWorkspaceContext({ workspaceId: upload.workspaceId })), + upload, + } +} + +async function resolveImportContext( + principal: Principal, + input: KnowledgeImportInput +): Promise { + if (input.uploadToken) { + return resolveUploadContext(principal, { ...input, uploadToken: input.uploadToken }) + } + const record = await getKnowledgeImport({ + importId: input.importId, + assertedWorkspaceId: input.workspaceId, + }) + return { + ...(await resolveKnowledgeWorkspaceContext({ workspaceId: record.workspaceId })), + record, + } +} + +/** + * The durable record once the runner has been dispatched, which a caller still + * holding the upload token must see in place of its finished upload. + */ +function findStartedImport(context: KnowledgeImportUploadContext) { + return findKnowledgeImport({ + importId: context.upload.id, + assertedWorkspaceId: context.workspaceId, + }) +} + +/** What the runner needs, with usage admitted for the caller completing the upload. */ +async function importPayload( + principal: Principal, + context: KnowledgeImportUploadContext +): Promise { + const { billingAttribution, userId } = await assertKnowledgeUsageAdmitted(principal, context) + const { upload } = context + const name = importedName(upload) + return { + importId: upload.id, + workspaceId: context.workspaceId, + userId, + ...(name ? { name } : {}), + sourceKey: upload.storageKey, + billingAttribution, + } +} + +/** + * Writes the durable record while the upload is being completed, before it + * counts as complete. From then on the stale-import janitor owns the bundle, so + * neither a crash nor a refusal after this point can strand it; a refusal + * before it leaves the session unfinished, which its abort and expiry discard. + * Returns the runner's payload, or `null` when a repeated completion finds the + * record already written. + */ +async function recordKnowledgeImport( + principal: Principal, + context: KnowledgeImportUploadContext +): Promise { + const payload = await importPayload(principal, context) + const inserted = await insertKnowledgeImport({ + id: payload.importId, + workspaceId: payload.workspaceId, + userId: payload.userId, + sourceKey: payload.sourceKey, + }) + return inserted ? payload : null +} + +function startKnowledgeImport(payload: KnowledgeImportPayload): Promise { + return dispatchBackgroundTask('knowledge-import', payload, { + runInProcess: runKnowledgeImport, + trigger: { tags: [`workspaceId:${payload.workspaceId}`, `importId:${payload.importId}`] }, + }) +} + +/** + * Dispatches again an import whose record no worker has claimed: its first + * dispatch failed or was lost with the request that wrote the record, or is + * still queued. Either way a second run is safe, since only one worker can + * claim it. A dispatch never settles the import itself, since another one may + * already be on its way; one that never runs is failed by the stale-import + * janitor, which also deletes its bundle. + */ +async function redispatchUnclaimedImport( + principal: Principal, + context: KnowledgeImportUploadContext, + record: KnowledgeImportRecord +): Promise { + if (record.status !== 'running' || record.startedAt) return + // A group that withdrew uploads since the record was written stops it here too. + await assertImportedDocumentsAllowed(principal, context.workspaceId) + try { + await startKnowledgeImport(await importPayload(principal, context)) + } catch (error) { + logger.warn('Could not dispatch an unclaimed knowledge import again', { + importId: record.id, + error: getErrorMessage(error, 'Unknown error'), + }) + } +} + +export const createKnowledgeImport = defineAuthorizedKnowledgeUseCase({ + operation: knowledgeOperations.importCreate, + resolveContext: ({ input }: { input: CreateKnowledgeImportInput }) => + resolveKnowledgeWorkspaceContext({ workspaceId: input.body.workspaceId }), + async execute({ principal, input, context, request }): Promise { + if (!request) throw new Error('Knowledge import creation requires a request context') + await assertImportedDocumentsAllowed(principal, context.workspaceId) + const { source, name } = input.body + if (!source.name.toLowerCase().endsWith('.zip')) { + throw new OrchestrationError('validation', 'A knowledge base bundle must be a .zip archive') + } + // Refused before the bundle moves, so a full plan never uploads gigabytes to be turned away. + const { userId } = await assertKnowledgeUsageAdmitted(principal, context) + const upload = await createUploadSession({ + id: generateId(), + workspaceId: context.workspaceId, + userId, + principal, + purpose: 'knowledge_import', + fileName: source.name, + contentType: source.contentType, + fileSize: source.size, + metadata: { [IMPORT_METADATA_KEY]: name ? { name } : {} }, + localOrigin: requestOrigin(request), + }) + logger.info('Created knowledge import', { + importId: upload.id, + workspaceId: context.workspaceId, + principalKind: principal.kind, + }) + return { import: fromUpload(upload, context.workspaceId), upload } + }, +}) + +/** + * Reads an import in any state. A caller holding the upload token is resolved + * against the session, but the durable record wins once it exists: the session + * stays `completed` after the runner starts, and reporting `uploading` for an + * import that is already processing would strand a poller. + */ +export const readKnowledgeImport = defineAuthorizedKnowledgeUseCase({ + operation: knowledgeOperations.importRead, + resolveContext: ({ principal, input }: { principal: Principal; input: KnowledgeImportInput }) => + resolveImportContext(principal, input), + async execute({ context }): Promise { + if ('record' in context) return { import: fromRecord(context.record) } + const started = await findStartedImport(context) + return { + import: started ? fromRecord(started) : fromUpload(context.upload, context.workspaceId), + } + }, +}) + +export const createKnowledgeImportParts = defineAuthorizedKnowledgeUseCase({ + operation: knowledgeOperations.importParts, + resolveContext: ({ + principal, + input, + }: { + principal: Principal + input: CreateKnowledgeImportPartsInput + }) => resolveUploadContext(principal, input), + async execute({ principal, input, context, request }) { + if (!request) throw new Error('Knowledge import part issuance requires a request context') + // Repeated so a group that withdraws uploads mid-transfer stops the bytes, not just the import. + await assertImportedDocumentsAllowed(principal, context.workspaceId) + return { + parts: await createUploadPartUrls({ + session: context.upload, + partNumbers: input.partNumbers, + localOrigin: requestOrigin(request), + }), + } + }, +}) + +export const completeKnowledgeImport = defineAuthorizedKnowledgeUseCase({ + operation: knowledgeOperations.importComplete, + resolveContext: ({ + principal, + input, + }: { + principal: Principal + input: KnowledgeImportUploadInput + }) => resolveUploadContext(principal, input), + async execute({ principal, context }): Promise { + const existing = await findStartedImport(context) + if (existing) { + await redispatchUnclaimedImport(principal, context, existing) + return { import: fromRecord(existing) } + } + let started: KnowledgeImportPayload | null + try { + const completed = await completeUploadSession({ + session: context.upload, + finalize: async (claimed) => { + assertUploadSessionAuthBinding(claimed, principal) + await authorizeWorkspaceOperation( + principal, + knowledgeOperations.importComplete, + context, + { delegation: knowledgeDelegationPolicy } + ) + // Repeated because creation and completion are separate requests; see the helper. + await assertImportedDocumentsAllowed(principal, context.workspaceId) + return { value: await recordKnowledgeImport(principal, { ...context, upload: claimed }) } + }, + }) + started = completed.value + } catch (error) { + // A concurrent completion holds the session; report the import it started, if any. + const raced = + asOrchestrationError(error)?.code === 'conflict' ? await findStartedImport(context) : null + if (raced) return { import: fromRecord(raced) } + throw error + } + if (started) { + await startKnowledgeImport(started) + logger.info('Started knowledge import', { + importId: started.importId, + workspaceId: context.workspaceId, + principalKind: principal.kind, + }) + } + const record = await getKnowledgeImport({ + importId: context.upload.id, + assertedWorkspaceId: context.workspaceId, + }) + return { import: fromRecord(record) } + }, + /** + * What the caller did is start the import: the base exists only once the + * runner creates it, under the import's id. Keyed by the import, so the + * completion that started it and any retry of it record one event between them. + */ + projectAudit: ({ context, result }) => ({ + action: AuditAction.KNOWLEDGE_BASE_IMPORT_STARTED, + resourceType: AuditResourceType.KNOWLEDGE_BASE, + resourceId: result.import.id, + resourceName: importedName(context.upload) ?? context.upload.fileName, + description: `Started importing a knowledge base from bundle "${context.upload.fileName}"`, + metadata: { workspaceId: context.workspaceId, importId: result.import.id }, + idempotencyKey: `knowledge-import:${result.import.id}`, + }), +}) + +/** + * Stops an import. During its upload that aborts the transfer; once the + * runner is going it stops after the document in flight, and the documents + * already imported stay in the new base. + */ +export const cancelKnowledgeImport = defineAuthorizedKnowledgeUseCase({ + operation: knowledgeOperations.importCancel, + resolveContext: ({ principal, input }: { principal: Principal; input: KnowledgeImportInput }) => + resolveImportContext(principal, input), + async execute({ principal, context }): Promise { + if ('record' in context) + return { import: fromRecord(await stopKnowledgeImport(context.record)) } + const started = await findStartedImport(context) + if (started) return { import: fromRecord(await stopKnowledgeImport(started)) } + assertUploadSessionAuthBinding(context.upload, principal) + const aborted = await abortUploadSession(context.upload) + // A completion finalizing alongside this abort may have written the record first. + const late = await findStartedImport(context) + if (late) return { import: fromRecord(await stopKnowledgeImport(late)) } + return { import: fromUpload(aborted, context.workspaceId) } + }, +}) diff --git a/apps/sim/lib/knowledge/application/operations.ts b/apps/sim/lib/knowledge/application/operations.ts index b3f3cc58ad6..d15f9f60fca 100644 --- a/apps/sim/lib/knowledge/application/operations.ts +++ b/apps/sim/lib/knowledge/application/operations.ts @@ -309,8 +309,8 @@ export const knowledgeOperations = { }) ), /** - * The only operation that brings a knowledge base into existence, so it is the - * only one `knowledge.create` governs — a group may be allowed to query, + * Brings a knowledge base into existence, which `knowledge.create` governs here + * and on the bundle-import steps alone — a group may be allowed to query, * populate and organize the bases it already has without opening new ones. */ create: defineKnowledgeOperation( @@ -953,6 +953,67 @@ export const knowledgeOperations = { ...ALL_PRINCIPAL_POLICY, }) ), + /** + * A bundle import is one new knowledge base, split across requests because + * the archive is uploaded before it is read. Every step carries + * `knowledge.create` for the reason the upload steps share `knowledge.upload`: + * a group denied new bases must find no open step, cancel included. + */ + importCreate: defineKnowledgeOperation( + defineWorkspaceOperation({ + id: 'knowledge.imports.create', + oauthScope: 'api:write', + minimumRole: 'write', + workspaceApiKey: 'allow', + capability: 'knowledge.create', + contentDelivery: 'none', + ...ALL_PRINCIPAL_POLICY, + }) + ), + importParts: defineKnowledgeOperation( + defineWorkspaceOperation({ + id: 'knowledge.imports.parts', + oauthScope: 'api:write', + minimumRole: 'write', + workspaceApiKey: 'allow', + capability: 'knowledge.create', + contentDelivery: 'none', + ...ALL_PRINCIPAL_POLICY, + }) + ), + importComplete: defineKnowledgeOperation( + defineWorkspaceOperation({ + id: 'knowledge.imports.complete', + oauthScope: 'api:write', + minimumRole: 'write', + workspaceApiKey: 'allow', + capability: 'knowledge.create', + contentDelivery: 'none', + ...ALL_PRINCIPAL_POLICY, + }) + ), + importCancel: defineKnowledgeOperation( + defineWorkspaceOperation({ + id: 'knowledge.imports.cancel', + oauthScope: 'api:write', + minimumRole: 'write', + workspaceApiKey: 'allow', + capability: 'knowledge.create', + contentDelivery: 'none', + ...ALL_PRINCIPAL_POLICY, + }) + ), + importRead: defineKnowledgeOperation( + defineWorkspaceOperation({ + id: 'knowledge.imports.read', + oauthScope: 'api:read', + minimumRole: 'read', + workspaceApiKey: 'allow', + capability: 'knowledge.use', + contentDelivery: 'none', + ...ALL_PRINCIPAL_POLICY, + }) + ), } as const /** diff --git a/apps/sim/lib/knowledge/constants.ts b/apps/sim/lib/knowledge/constants.ts index 08444d02a23..dea484f1f76 100644 --- a/apps/sim/lib/knowledge/constants.ts +++ b/apps/sim/lib/knowledge/constants.ts @@ -211,3 +211,10 @@ export const MAX_KNOWLEDGE_BUNDLE_DOCUMENTS = 2_000 * because the processor's largest chunking config emits chunks past 10k. */ export const MAX_KNOWLEDGE_BUNDLE_CHUNK_CONTENT_LENGTH = 100_000 +/** Bytes an imported `manifest.json` may hold before it is read into memory. */ +export const MAX_KNOWLEDGE_BUNDLE_MANIFEST_BYTES = 64 * 1024 * 1024 +/** + * Bytes one imported document's chunk entry may hold, vectors included. The + * entry is read whole, as a parsed file's chunks are held whole while indexing. + */ +export const MAX_KNOWLEDGE_BUNDLE_CHUNKS_ENTRY_BYTES = 256 * 1024 * 1024 diff --git a/apps/sim/lib/knowledge/documents/service.ts b/apps/sim/lib/knowledge/documents/service.ts index a60e2b43d94..e67cef63585 100644 --- a/apps/sim/lib/knowledge/documents/service.ts +++ b/apps/sim/lib/knowledge/documents/service.ts @@ -1442,6 +1442,44 @@ export interface DocumentProcessingExecutionContext { readonly deadlineAt?: number } +/** + * Chunks a knowledge-base bundle already holds for a document. A pass given one + * indexes these chunks instead of parsing the document's file, and stores + * `vectors` instead of calling the embedding provider when the bundle was + * embedded with this base's model. + */ +export interface PreparedDocumentIndex { + readonly chunks: readonly { + readonly text: string + readonly startOffset: number + readonly endOffset: number + readonly enabled: boolean + }[] + /** One per chunk, in this base's embedding dimension. */ + readonly vectors?: readonly number[][] + /** Characters in the document's source text; chunks overlap, so their lengths do not sum to it. */ + readonly characterCount: number +} + +/** + * The processor's result shape for chunks that were never parsed here. Token + * counts are left to the pass, which estimates every chunk against this + * base's model whichever way the chunks arrived. + */ +function preparedProcessingResult(prepared: PreparedDocumentIndex) { + return { + chunks: prepared.chunks.map((chunk) => ({ + text: chunk.text, + metadata: { startIndex: chunk.startOffset, endIndex: chunk.endOffset }, + })), + metadata: { + chunkCount: prepared.chunks.length, + tokenCount: null, + characterCount: prepared.characterCount, + }, + } +} + export interface DocumentProcessingAttemptContext extends DocumentProcessingExecutionContext { /** True only when this invocation follows a successful queue-budget charge. */ readonly chargedAtDispatch: boolean @@ -1468,6 +1506,8 @@ export interface DocumentProcessingAttemptContext extends DocumentProcessingExec readonly scheduleDatabaseRetry?: (error: unknown) => Date | null /** Signals that this invocation owns the persisted processing generation. */ readonly onClaimed?: () => void + /** Index these chunks instead of parsing the document's file. */ + readonly preparedIndex?: PreparedDocumentIndex } /** @@ -1957,34 +1997,39 @@ export async function processDocumentAsync( (processing = runWithKnowledgeModelInputProvenance( documentSecretContext.registry, async () => { - await assertKnowledgeEmbeddingCapacity({ - ...kbEmbedding, - workspaceId: ctx.workspaceId, - signal, - }) - const processed = await processDocument( - persistedDocData.fileUrl, - persistedDocData.filename, - persistedDocData.mimeType, - kbConfig.maxSize, - kbConfig.overlap, - kbConfig.minSize, - { - ...sourceFileAccessFor(ctx.connectorId, documentActorUserId), + const prepared = attemptContext?.preparedIndex + if (!prepared?.vectors) { + await assertKnowledgeEmbeddingCapacity({ + ...kbEmbedding, + workspaceId: ctx.workspaceId, signal, - processingDeadlineAt, - imageExtraction: imageExtractionPolicyFor(ctx.connectorType), - onVisionUsage: (usage) => { - visionCharges.push(recordVisionUsage(usage)) - }, - ...(indexingPassId - ? { ocrCheckpoint: { knowledgeBaseId, documentId, indexingPassId } } - : {}), - }, - ctx.workspaceId, - rawConfig?.strategy, - rawConfig?.strategyOptions - ) + }) + } + const processed = prepared + ? preparedProcessingResult(prepared) + : await processDocument( + persistedDocData.fileUrl, + persistedDocData.filename, + persistedDocData.mimeType, + kbConfig.maxSize, + kbConfig.overlap, + kbConfig.minSize, + { + ...sourceFileAccessFor(ctx.connectorId, documentActorUserId), + signal, + processingDeadlineAt, + imageExtraction: imageExtractionPolicyFor(ctx.connectorType), + onVisionUsage: (usage) => { + visionCharges.push(recordVisionUsage(usage)) + }, + ...(indexingPassId + ? { ocrCheckpoint: { knowledgeBaseId, documentId, indexingPassId } } + : {}), + }, + ctx.workspaceId, + rawConfig?.strategy, + rawConfig?.strategyOptions + ) signal.throwIfAborted() assertDocumentChunkCountWithinLimit(processed.chunks.length) @@ -2016,7 +2061,9 @@ export async function processDocumentAsync( ? sha256Hex(JSON.stringify(chunkTexts.map((text) => sha256Hex(text)))) : undefined - if (chunkTexts.length > 0) { + if (prepared?.vectors) { + embeddings.push(...prepared.vectors) + } else if (chunkTexts.length > 0) { const batchSize = LARGE_DOC_CONFIG.MAX_EMBEDDING_BATCH const totalBatches = Math.ceil(chunkTexts.length / batchSize) @@ -2169,6 +2216,7 @@ export async function processDocumentAsync( embeddingModel: kbEmbeddingModel, startOffset: chunk.metadata.startIndex, endOffset: chunk.metadata.endIndex, + enabled: prepared?.chunks[chunkIndex].enabled ?? true, tag1: documentTags.tag1, tag2: documentTags.tag2, tag3: documentTags.tag3, @@ -2249,7 +2297,9 @@ export async function processDocumentAsync( .update(document) .set({ chunkCount: processed.metadata.chunkCount, - tokenCount: processed.metadata.tokenCount, + tokenCount: + processed.metadata.tokenCount ?? + chunkTokenCounts.reduce((sum, count) => sum + count, 0), characterCount: processed.metadata.characterCount, processingStatus: 'completed', processingCompletedAt: now, @@ -3237,6 +3287,8 @@ export async function createSingleDocument( options?: { expectedWorkspaceId?: string uploadedArtifact?: { cleanupEventId: string; metadataId: string; contentUpdatedAt: Date } + /** Whether the document starts out searchable; defaults to `true`. */ + enabled?: boolean processing?: { processingOptions: ProcessingOptions billingAttribution: BillingAttributionSnapshot @@ -3318,7 +3370,7 @@ export async function createSingleDocument( tokenCount: 0, characterCount: 0, processingStatus: 'pending' as const, - enabled: true, + enabled: options?.enabled ?? true, uploadedAt: now, uploadedBy, ...processedTags, diff --git a/apps/sim/lib/knowledge/service.ts b/apps/sim/lib/knowledge/service.ts index 1d15fd27556..37e86ebf637 100644 --- a/apps/sim/lib/knowledge/service.ts +++ b/apps/sim/lib/knowledge/service.ts @@ -430,16 +430,17 @@ export async function createKnowledgeBase( } /** - * Persists a knowledge base for an already-authorized application use case. - * Callers outside the application layer must use {@link createKnowledgeBase}. + * Persists a knowledge base for an already-authorized application use case, or + * for the background runner one dispatches. Other callers must use + * {@link createKnowledgeBase}. `id` is for a caller that minted the id earlier. */ export async function createAuthorizedKnowledgeBase( - data: Omit & ResourceOwner, + data: Omit & ResourceOwner & { id?: string }, requestId: string ): Promise { const scope = resourceScopeFromOwner(data) const owner = resourceScopeColumns(scope) - const kbId = generateId() + const kbId = data.id ?? generateId() const now = new Date() await assertKnowledgeBaseFolder(data.folderId, owner.workspaceId) diff --git a/apps/sim/lib/knowledge/transfer/bundle.ts b/apps/sim/lib/knowledge/transfer/bundle.ts index cbe66b9d61d..33a8faff334 100644 --- a/apps/sim/lib/knowledge/transfer/bundle.ts +++ b/apps/sim/lib/knowledge/transfer/bundle.ts @@ -280,3 +280,22 @@ export function toManifestDocument( export function encodeVectorBase64(vector: readonly number[]): string { return Buffer.from(Float32Array.from(vector).buffer).toString('base64') } + +/** + * Reads a vector written by {@link encodeVectorBase64}, or `null` when it does not + * hold exactly `dimension` finite coordinates. + */ +export function decodeVectorBase64(encoded: string, dimension: number): number[] | null { + const byteLength = dimension * Float32Array.BYTES_PER_ELEMENT + // Checked before decoding, so an oversized field is refused without allocating it. + if (encoded.length !== Math.ceil(byteLength / 3) * 4) return null + const bytes = Buffer.from(encoded, 'base64') + if (bytes.byteLength !== byteLength) return null + const vector = new Array(dimension) + for (let index = 0; index < dimension; index++) { + const value = bytes.readFloatLE(index * Float32Array.BYTES_PER_ELEMENT) + if (!Number.isFinite(value)) return null + vector[index] = value + } + return vector +} diff --git a/apps/sim/lib/knowledge/transfer/import-archive.test.ts b/apps/sim/lib/knowledge/transfer/import-archive.test.ts new file mode 100644 index 00000000000..373a391f79c --- /dev/null +++ b/apps/sim/lib/knowledge/transfer/import-archive.test.ts @@ -0,0 +1,220 @@ +import { createWriteStream } from 'node:fs' +import { mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { pipeline } from 'node:stream/promises' +import { ZipArchive } from 'archiver' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { encodeVectorBase64 } from '@/lib/knowledge/transfer/bundle' +import { openKnowledgeBundle } from '@/lib/knowledge/transfer/import-archive' + +const DOCUMENT_ID = 'doc-1' +const VECTOR = [0.25, -0.5, ...Array(1534).fill(0)] + +let directory: string + +beforeEach(async () => { + directory = await mkdtemp(join(tmpdir(), 'knowledge-import-archive-')) +}) +afterEach(async () => { + await rm(directory, { recursive: true, force: true }) +}) + +function manifest(overrides: Record = {}, document: Record = {}) { + return { + version: 1, + exportedAt: '2026-10-01T00:00:00.000Z', + embedding: { model: 'text-embedding-3-small', dimension: 1536, vectorsIncluded: true }, + knowledgeBase: { + name: 'Support docs', + description: null, + chunkingConfig: { maxSize: 1024, minSize: 100, overlap: 200 }, + }, + tags: [], + documents: [ + { + id: DOCUMENT_ID, + filename: 'handbook.txt', + mimeType: 'text/plain', + fileSize: 5, + enabled: true, + tags: {}, + file: `files/${DOCUMENT_ID}/handbook.txt`, + chunks: `chunks/${DOCUMENT_ID}.ndjson`, + chunkCount: 2, + tokenCount: 4, + characterCount: 10, + ...document, + }, + ], + ...overrides, + } +} + +const CHUNKS = { chunks: `chunks/${DOCUMENT_ID}.ndjson`, chunkCount: 2, characterCount: 10 } + +function chunkLine(index: number, extra: Record = {}): string { + return JSON.stringify({ + index, + content: `chunk ${index}`, + tokenCount: 2, + startOffset: index * 10, + endOffset: index * 10 + 7, + enabled: index === 0, + vector: encodeVectorBase64(VECTOR), + ...extra, + }) +} + +/** Writes entries in order with archiver, which, unlike a map, can repeat a name. */ +async function zipOf(entries: [string, string][]): Promise { + const path = join(directory, 'bundle.zip') + const archive = new ZipArchive() + const written = pipeline(archive, createWriteStream(path)) + for (const [name, content] of entries) archive.append(content, { name }) + await archive.finalize() + await written + return path +} + +function validEntries( + lines = [chunkLine(0), chunkLine(1)], + bundleManifest = manifest() +): [string, string][] { + return [ + [`files/${DOCUMENT_ID}/handbook.txt`, 'hello'], + [`chunks/${DOCUMENT_ID}.ndjson`, `${lines.join('\n')}\n`], + ['manifest.json', JSON.stringify(bundleManifest)], + ] +} + +describe('openKnowledgeBundle', () => { + it('reads the manifest, original file, chunks, and vectors of a well-formed bundle', async () => { + const reader = await openKnowledgeBundle(await zipOf(validEntries())) + try { + expect(reader.manifest.knowledgeBase.name).toBe('Support docs') + expect((await reader.readFile(`files/${DOCUMENT_ID}/handbook.txt`)).toString()).toBe('hello') + const withVectors = await reader.readChunks(CHUNKS, true) + expect(withVectors.chunks).toEqual([ + { text: 'chunk 0', startOffset: 0, endOffset: 7, enabled: true }, + { text: 'chunk 1', startOffset: 10, endOffset: 17, enabled: false }, + ]) + expect(withVectors.vectors).toEqual([VECTOR, VECTOR]) + expect((await reader.readChunks(CHUNKS, false)).vectors).toBeUndefined() + } finally { + reader.close() + } + }) + + it.each<[string, () => Promise, string]>([ + [ + 'a file that is not a zip archive', + async () => { + const path = join(directory, 'bundle.zip') + await writeFile(path, 'not a zip') + return path + }, + 'not a zip archive', + ], + [ + 'an archive without a manifest', + () => zipOf(validEntries().slice(0, 2)), + 'missing entry manifest.json', + ], + [ + 'a manifest that is not JSON', + () => zipOf([...validEntries().slice(0, 2), ['manifest.json', '{']]), + 'manifest.json is not valid JSON', + ], + [ + 'an unsupported bundle version', + () => zipOf(validEntries(undefined, manifest({ version: 2 }))), + 'manifest version', + ], + [ + 'a document listed twice', + () => { + const [listed] = manifest().documents + return zipOf(validEntries(undefined, manifest({ documents: [listed, listed] }))) + }, + 'duplicate document id doc-1', + ], + [ + 'a manifest naming an entry the archive lacks', + () => { + const [file, , manifestEntry] = validEntries() + return zipOf([file, manifestEntry]) + }, + 'missing entry chunks/doc-1.ndjson', + ], + [ + 'an archive with more entries than any bundle holds', + () => + zipOf(Array.from({ length: 4002 }, (_, index): [string, string] => [`extra/${index}`, ''])), + 'more than 4001 entries', + ], + [ + 'an archive that repeats an entry name', + () => zipOf([...validEntries(), ['manifest.json', JSON.stringify(manifest())]]), + 'duplicate entry manifest.json', + ], + ])('refuses %s before reading any document', async (_fixture, build, message) => { + await expect(openKnowledgeBundle(await build())).rejects.toThrow( + expect.objectContaining({ code: 'validation', message: expect.stringContaining(message) }) + ) + }) + + it.each([ + ['a line that is not JSON', [chunkLine(0), '{'], 'line 2 is not valid JSON'], + ['a line outside the chunk schema', [chunkLine(0), chunkLine(1, { content: '' })], 'line 2'], + ['chunks out of index order', [chunkLine(1), chunkLine(0)], 'chunks are out of order'], + [ + 'a chunk that ends before it starts', + [chunkLine(0), chunkLine(1, { startOffset: 20, endOffset: 10 })], + 'chunk 1 ends before it starts', + ], + ['fewer chunks than the manifest lists', [chunkLine(0)], 'holds 1 chunks'], + [ + 'a chunk without a vector', + [chunkLine(0), chunkLine(1, { vector: undefined })], + 'chunk 1 has no valid vector', + ], + [ + 'a vector of the wrong dimension', + [chunkLine(0), chunkLine(1, { vector: encodeVectorBase64([1, 2, 3]) })], + 'chunk 1 has no valid vector', + ], + ])('refuses a chunk entry with %s', async (_fixture, lines, message) => { + const reader = await openKnowledgeBundle(await zipOf(validEntries(lines))) + try { + await expect(reader.readChunks(CHUNKS, true)).rejects.toThrow( + expect.objectContaining({ code: 'validation', message: expect.stringContaining(message) }) + ) + } finally { + reader.close() + } + }) + + it('refuses a damaged chunk entry when validated, before any document is read', async () => { + const reader = await openKnowledgeBundle(await zipOf(validEntries([chunkLine(0), '{']))) + try { + await expect(reader.validateChunks(false)).rejects.toThrow( + expect.objectContaining({ code: 'validation', message: expect.stringContaining('line 2') }) + ) + } finally { + reader.close() + } + }) + + it('accepts chunks without vectors when they will be re-embedded', async () => { + const lines = [chunkLine(0, { vector: undefined }), chunkLine(1, { vector: undefined })] + const reader = await openKnowledgeBundle(await zipOf(validEntries(lines))) + try { + const { chunks, vectors } = await reader.readChunks(CHUNKS, false) + expect(chunks).toHaveLength(2) + expect(vectors).toBeUndefined() + } finally { + reader.close() + } + }) +}) diff --git a/apps/sim/lib/knowledge/transfer/import-archive.ts b/apps/sim/lib/knowledge/transfer/import-archive.ts new file mode 100644 index 00000000000..2a3900edbf7 --- /dev/null +++ b/apps/sim/lib/knowledge/transfer/import-archive.ts @@ -0,0 +1,243 @@ +/** + * Read side of a knowledge-base bundle import. The archive is opened from a + * local file so each entry is inflated on demand rather than the whole bundle + * held in memory, and nothing in it is trusted: the manifest is validated + * against the format, every entry it names must exist within its ceiling, and + * each chunk line is validated as it is read. yauzl enforces each entry's + * declared size while inflating, so a forged header cannot expand past the + * ceiling it was checked against. + */ + +import { createInterface } from 'node:readline' +import { type Entry, openPromise, type ZipFile } from 'yauzl' +import { OrchestrationError } from '@/lib/core/orchestration/types' +import { + MAX_KNOWLEDGE_BUNDLE_CHUNKS_ENTRY_BYTES, + MAX_KNOWLEDGE_BUNDLE_DOCUMENTS, + MAX_KNOWLEDGE_BUNDLE_MANIFEST_BYTES, +} from '@/lib/knowledge/constants' +import type { PreparedDocumentIndex } from '@/lib/knowledge/documents/service' +import { + decodeVectorBase64, + KNOWLEDGE_BUNDLE_MANIFEST_ENTRY, + type KnowledgeBundleDocument, + type KnowledgeBundleManifest, + knowledgeBundleChunkLineSchema, + knowledgeBundleManifestSchema, +} from '@/lib/knowledge/transfer/bundle' +import { MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE } from '@/lib/uploads/shared/types' + +/** A file and a chunk entry per document, plus the manifest. */ +const MAX_BUNDLE_ENTRIES = 2 * MAX_KNOWLEDGE_BUNDLE_DOCUMENTS + 1 + +export interface KnowledgeBundleReader { + readonly manifest: KnowledgeBundleManifest + /** A document's original file, by the entry its manifest names. */ + readFile(entry: string): Promise + /** + * Reads every chunk entry through once, so a damaged entry refuses the whole + * bundle before the import writes anything. `vectors` as for {@link readChunks}. + */ + validateChunks(vectors: boolean): Promise + /** + * A document's chunks in index order, ready to index. With `vectors`, every + * line must carry a vector of the manifest's dimension; without, none is decoded. + */ + readChunks( + document: Pick & { chunks: string }, + vectors: boolean + ): Promise + close(): void +} + +function bundleError(message: string): OrchestrationError { + return new OrchestrationError('validation', `Invalid knowledge base bundle: ${message}`) +} + +async function indexEntries(zip: ZipFile): Promise> { + if (zip.entryCount > MAX_BUNDLE_ENTRIES) { + throw bundleError(`more than ${MAX_BUNDLE_ENTRIES} entries`) + } + const entries = new Map() + await new Promise((resolve, reject) => { + zip.on('entry', (entry: Entry) => { + if (entries.has(entry.fileName)) { + reject(bundleError(`duplicate entry ${entry.fileName}`)) + return + } + entries.set(entry.fileName, entry) + zip.readEntry() + }) + zip.once('end', resolve) + zip.once('error', reject) + zip.readEntry() + }) + return entries +} + +/** Inflates an entry into a buffer of its declared size, so a large file is held once. */ +async function readEntry(zip: ZipFile, entry: Entry): Promise { + const bytes = Buffer.allocUnsafe(entry.uncompressedSize) + let offset = 0 + for await (const chunk of await zip.openReadStreamPromise(entry)) { + if (offset + chunk.length > bytes.length) { + throw bundleError(`entry ${entry.fileName} is larger than it declares`) + } + offset += (chunk as Buffer).copy(bytes, offset) + } + return bytes +} + +function requireEntry(entries: Map, name: string, maxBytes: number): Entry { + const entry = entries.get(name) + if (!entry) throw bundleError(`missing entry ${name}`) + if (entry.isEncrypted()) throw bundleError(`entry ${name} is encrypted`) + if (entry.uncompressedSize > maxBytes) { + throw bundleError(`entry ${name} exceeds ${maxBytes} bytes`) + } + return entry +} + +function parseManifest(bytes: Buffer): KnowledgeBundleManifest { + let raw: unknown + try { + raw = JSON.parse(bytes.toString('utf8')) + } catch { + throw bundleError('manifest.json is not valid JSON') + } + const result = knowledgeBundleManifestSchema.safeParse(raw) + if (!result.success) { + const [issue] = result.error.issues + throw bundleError(`manifest ${issue.path.join('.')} ${issue.message}`) + } + const ids = new Set() + for (const document of result.data.documents) { + if (ids.has(document.id)) throw bundleError(`duplicate document id ${document.id}`) + ids.add(document.id) + } + return result.data +} + +/** + * Opens a bundle archive and validates its manifest and the entries it names + * before any document is read, so a malformed bundle is refused before the + * import writes anything. + */ +export async function openKnowledgeBundle(path: string): Promise { + let zip: ZipFile + try { + zip = await openPromise(path, { lazyEntries: true, autoClose: false }) + } catch { + throw bundleError('not a zip archive') + } + try { + const entries = await indexEntries(zip) + const manifest = parseManifest( + await readEntry( + zip, + requireEntry(entries, KNOWLEDGE_BUNDLE_MANIFEST_ENTRY, MAX_KNOWLEDGE_BUNDLE_MANIFEST_BYTES) + ) + ) + const validated = new Map() + for (const document of manifest.documents) { + if (document.file) { + validated.set( + document.file, + requireEntry(entries, document.file, MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE) + ) + } + if (document.chunks) { + validated.set( + document.chunks, + requireEntry(entries, document.chunks, MAX_KNOWLEDGE_BUNDLE_CHUNKS_ENTRY_BYTES) + ) + } + } + const entryFor = (name: string) => { + const entry = validated.get(name) + if (!entry) throw new Error(`Bundle entry ${name} is not named by its manifest`) + return entry + } + + /** Streams one chunk entry, validating each line and handing it on in index order. */ + const scanChunks = async ( + name: string, + chunkCount: number, + vectors: boolean, + onChunk: (chunk: PreparedDocumentIndex['chunks'][number], vector: number[] | null) => void + ) => { + const stream = await zip.openReadStreamPromise(entryFor(name)) + let lines = 0 + let previousIndex = -1 + for await (const line of createInterface({ + input: stream, + crlfDelay: Number.POSITIVE_INFINITY, + })) { + if (line.length === 0) continue + lines++ + let raw: unknown + try { + raw = JSON.parse(line) + } catch { + throw bundleError(`${name} line ${lines} is not valid JSON`) + } + const parsed = knowledgeBundleChunkLineSchema.safeParse(raw) + if (!parsed.success) { + const [issue] = parsed.error.issues + throw bundleError(`${name} line ${lines} ${issue.path.join('.')} ${issue.message}`) + } + const chunk = parsed.data + if (chunk.index <= previousIndex) throw bundleError(`${name} chunks are out of order`) + if (chunk.endOffset < chunk.startOffset) { + throw bundleError(`${name} chunk ${chunk.index} ends before it starts`) + } + previousIndex = chunk.index + let vector: number[] | null = null + if (vectors) { + vector = chunk.vector + ? decodeVectorBase64(chunk.vector, manifest.embedding.dimension) + : null + if (!vector) throw bundleError(`${name} chunk ${chunk.index} has no valid vector`) + } + onChunk( + { + text: chunk.content, + startOffset: chunk.startOffset, + endOffset: chunk.endOffset, + enabled: chunk.enabled, + }, + vector + ) + } + if (lines !== chunkCount) { + throw bundleError(`${name} holds ${lines} chunks, but the manifest lists ${chunkCount}`) + } + } + + return { + manifest, + readFile: (name) => readEntry(zip, entryFor(name)), + async validateChunks(vectors) { + for (const document of manifest.documents) { + if (document.chunks) { + await scanChunks(document.chunks, document.chunkCount, vectors, () => {}) + } + } + }, + async readChunks(document, vectors) { + const chunks: PreparedDocumentIndex['chunks'][number][] = [] + const decoded: number[][] = [] + await scanChunks(document.chunks, document.chunkCount, vectors, (chunk, vector) => { + chunks.push(chunk) + if (vector) decoded.push(vector) + }) + const { characterCount } = document + return vectors ? { chunks, vectors: decoded, characterCount } : { chunks, characterCount } + }, + close: () => zip.close(), + } + } catch (error) { + zip.close() + throw error + } +} diff --git a/apps/sim/lib/knowledge/transfer/import-jobs.ts b/apps/sim/lib/knowledge/transfer/import-jobs.ts new file mode 100644 index 00000000000..232c3dc1612 --- /dev/null +++ b/apps/sim/lib/knowledge/transfer/import-jobs.ts @@ -0,0 +1,157 @@ +/** + * The `knowledge_base_import` state machine: `running` → `completed` | `failed` + * | `canceled`. Every write after creation is guarded on `running`, so a cancel + * or the stale-job janitor always wins over a runner that is still finishing a + * document: the runner's next write matches nothing, and it stops. + */ + +import { db } from '@sim/db' +import { knowledgeBaseImport } from '@sim/db/schema' +import { truncate } from '@sim/utils/string' +import { and, eq, isNull } from 'drizzle-orm' +import { OrchestrationError } from '@/lib/core/orchestration/types' + +/** Where an import's uploaded bundle is stored until the import settles. */ +export const KNOWLEDGE_IMPORT_STORAGE_CONTEXT = 'knowledge-import' + +export type KnowledgeImportRecord = typeof knowledgeBaseImport.$inferSelect + +/** A document the import could not bring over, and why. */ +export type KnowledgeImportFailure = KnowledgeImportRecord['failures'][number] + +/** How many document failures an import keeps; the count beyond it is still exact. */ +export const MAX_KNOWLEDGE_IMPORT_FAILURE_SAMPLES = 10 +const MAX_ERROR_LENGTH = 2000 + +function whileRunning(importId: string) { + return and(eq(knowledgeBaseImport.id, importId), eq(knowledgeBaseImport.status, 'running')) +} + +/** + * Records an import whose archive has finished uploading. Returns `null` when + * the id is already recorded, so a repeated completion never dispatches twice. + */ +export async function insertKnowledgeImport(values: { + id: string + workspaceId: string + userId: string + sourceKey: string +}): Promise { + const [inserted] = await db + .insert(knowledgeBaseImport) + .values(values) + .onConflictDoNothing({ target: knowledgeBaseImport.id }) + .returning() + return inserted ?? null +} + +export async function findKnowledgeImport(params: { + importId: string + assertedWorkspaceId?: string +}): Promise { + const [row] = await db + .select() + .from(knowledgeBaseImport) + .where( + and( + eq(knowledgeBaseImport.id, params.importId), + params.assertedWorkspaceId === undefined + ? undefined + : eq(knowledgeBaseImport.workspaceId, params.assertedWorkspaceId) + ) + ) + .limit(1) + return row ?? null +} + +export async function getKnowledgeImport(params: { + importId: string + assertedWorkspaceId?: string +}): Promise { + const record = await findKnowledgeImport(params) + if (!record) throw new OrchestrationError('not_found', 'Knowledge base import not found') + return record +} + +/** + * Claims a running import for one worker. Returns `false` when another worker + * already claimed it, or it settled, so a duplicate dispatch exits untouched. + */ +export async function claimKnowledgeImport(importId: string): Promise { + const now = new Date() + const claimed = await db + .update(knowledgeBaseImport) + .set({ startedAt: now, updatedAt: now }) + .where(and(whileRunning(importId), isNull(knowledgeBaseImport.startedAt))) + .returning({ id: knowledgeBaseImport.id }) + return claimed.length > 0 +} + +/** + * Records the runner's progress, which doubles as its heartbeat. Returns + * `false` once the import is no longer running, which tells the runner to stop. + */ +export async function updateRunningKnowledgeImport( + importId: string, + values: Partial< + Pick< + KnowledgeImportRecord, + | 'knowledgeBaseId' + | 'documentsTotal' + | 'documentsImported' + | 'documentsFailed' + | 'vectorsReused' + | 'failures' + > + > +): Promise { + const updated = await db + .update(knowledgeBaseImport) + .set({ ...values, updatedAt: new Date() }) + .where(whileRunning(importId)) + .returning({ id: knowledgeBaseImport.id }) + return updated.length > 0 +} + +/** Settles a running import. A no-op once it has already settled. */ +export async function finishKnowledgeImport( + importId: string, + outcome: { status: 'completed' } | { status: 'failed'; error: string } +): Promise { + const now = new Date() + await db + .update(knowledgeBaseImport) + .set({ + status: outcome.status, + error: outcome.status === 'failed' ? truncate(outcome.error, MAX_ERROR_LENGTH) : null, + completedAt: now, + updatedAt: now, + }) + .where(whileRunning(importId)) +} + +/** + * Stops a running import. The runner sees the change at its next progress + * write; the documents it already brought over stay in the base. + */ +export async function stopKnowledgeImport( + record: KnowledgeImportRecord +): Promise { + if (record.status === 'canceled') return record + if (record.status !== 'running') { + throw new OrchestrationError('conflict', `Knowledge base import is ${record.status}`) + } + const now = new Date() + const [canceled] = await db + .update(knowledgeBaseImport) + .set({ status: 'canceled', completedAt: now, updatedAt: now }) + .where(and(whileRunning(record.id), eq(knowledgeBaseImport.workspaceId, record.workspaceId))) + .returning() + if (canceled) return canceled + const current = await getKnowledgeImport({ + importId: record.id, + assertedWorkspaceId: record.workspaceId, + }) + if (current.status === 'canceled') return current + throw new OrchestrationError('conflict', `Knowledge base import is ${current.status}`) +} diff --git a/apps/sim/lib/knowledge/transfer/import-runner.ts b/apps/sim/lib/knowledge/transfer/import-runner.ts new file mode 100644 index 00000000000..6c8e707a108 --- /dev/null +++ b/apps/sim/lib/knowledge/transfer/import-runner.ts @@ -0,0 +1,405 @@ +import { createWriteStream } from 'node:fs' +import { mkdtemp, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { pipeline } from 'node:stream/promises' +import { createLogger } from '@sim/logger' +import { getErrorMessage } from '@sim/utils/errors' +import { generateId } from '@sim/utils/id' +import type { BillingAttributionSnapshot } from '@/lib/billing/core/attribution' +import { asOrchestrationError, OrchestrationError } from '@/lib/core/orchestration/types' +import { mapWithConcurrency } from '@/lib/core/utils/concurrency' +import { generateRequestId } from '@/lib/core/utils/request' +import { createWorkspaceDocumentProcessingBillingContext } from '@/lib/knowledge/documents/processing-payload' +import { + createSingleDocument, + type PreparedDocumentIndex, + processDocumentAsync, +} from '@/lib/knowledge/documents/service' +import { uploadKnowledgeArtifact } from '@/lib/knowledge/documents/storage-upload' +import { getConfiguredKbEmbedding, type KbEmbeddingTarget } from '@/lib/knowledge/embeddings' +import { createAuthorizedKnowledgeBase, deleteKnowledgeBase } from '@/lib/knowledge/service' +import { createTagDefinition } from '@/lib/knowledge/tags/service' +import { validateTagValue, validateTagValueLength } from '@/lib/knowledge/tags/utils' +import type { + KnowledgeBundleDocument, + KnowledgeBundleManifest, +} from '@/lib/knowledge/transfer/bundle' +import { + type KnowledgeBundleReader, + openKnowledgeBundle, +} from '@/lib/knowledge/transfer/import-archive' +import { + claimKnowledgeImport, + findKnowledgeImport, + finishKnowledgeImport, + KNOWLEDGE_IMPORT_STORAGE_CONTEXT, + type KnowledgeImportFailure, + MAX_KNOWLEDGE_IMPORT_FAILURE_SAMPLES, + updateRunningKnowledgeImport, +} from '@/lib/knowledge/transfer/import-jobs' +import { generateKnowledgeBaseFileKey } from '@/lib/uploads/contexts/knowledge-base/file-manager' +import { deleteFile, downloadFileStream } from '@/lib/uploads/core/storage-service' +import { + EMPTY_KNOWLEDGE_DOCUMENT_MESSAGE, + MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE, +} from '@/lib/uploads/shared/types' +import { getFileExtension } from '@/lib/uploads/utils/file' +import { isSupportedExtension, validateFileType } from '@/lib/uploads/utils/validation' + +const logger = createLogger('KnowledgeImportRunner') + +/** + * Documents imported at once, so one document's storage upload and indexing + * overlap another's while at most two 100 MB originals are held in memory. + */ +const DOCUMENT_CONCURRENCY = 2 + +/** + * What a worker needs to run an import. The base it creates takes the import's + * id, so every dispatch of one import names the same base, and the import's + * audit names it before it exists. + */ +export interface KnowledgeImportPayload { + importId: string + workspaceId: string + /** The person the base and its documents are attributed to. */ + userId: string + /** Overrides the bundle's own knowledge base name. */ + name?: string + /** Storage key of the uploaded bundle, deleted once the import settles. */ + sourceKey: string + billingAttribution: BillingAttributionSnapshot +} + +/** + * Whether the bundle's vectors can be stored as they are. A vector is only + * meaningful to the model that produced it, so anything else is re-embedded. + */ +function canReuseVectors(manifest: KnowledgeBundleManifest, target: KbEmbeddingTarget): boolean { + return ( + manifest.embedding.vectorsIncluded && + manifest.embedding.model === target.model && + manifest.embedding.dimension === target.dimensions + ) +} + +/** + * The bundle's tag values in the shape document creation reads, refused here + * with a caller-facing reason when one would not be accepted. Dates travel as + * ISO timestamps but are stored as calendar days. + */ +function documentTagsData( + document: KnowledgeBundleDocument, + manifest: KnowledgeBundleManifest +): string | undefined { + const tags = manifest.tags.flatMap((tag) => { + const wire = document.tags[tag.slot] + if (wire === undefined) return [] + const value = tag.fieldType === 'date' ? wire.slice(0, 10) : wire + const invalid = + validateTagValueLength(tag.displayName, value) ?? + validateTagValue(tag.displayName, value, tag.fieldType) + if (invalid) throw new OrchestrationError('validation', invalid) + return [{ tagName: tag.displayName, fieldType: tag.fieldType, value }] + }) + return tags.length > 0 ? JSON.stringify(tags) : undefined +} + +/** A failure's own message when it is caller-fixable, or `null` when its text is internal. */ +function callerMessage(error: unknown): string | null { + const classified = asOrchestrationError(error) + return classified && classified.code !== 'internal' ? classified.message : null +} + +/** + * The name a document rebuilt from its chunk text is stored under. Parsing + * goes by extension first, so a name claiming another format gains `.txt` + * and a reprocess reads the text it holds. + */ +function textFilename(filename: string): string { + const extension = getFileExtension(filename) + return isSupportedExtension(extension) && extension !== 'txt' ? `${filename}.txt` : filename +} + +interface ImportDocumentContext { + payload: KnowledgeImportPayload + reader: KnowledgeBundleReader + knowledgeBaseId: string + reuseVectors: boolean +} + +/** + * Brings one document over. Its original file is stored the way an upload + * stores one; a document the bundle carries only as chunks is stored as the + * plain text those chunks hold, so it can still be reprocessed later. Chunks + * are indexed in place when their vectors can be reused or there is no + * original to parse; otherwise the file is queued for ordinary processing, + * exactly as an upload is. + */ +async function importDocument( + context: ImportDocumentContext, + document: KnowledgeBundleDocument +): Promise { + const { payload, reader, knowledgeBaseId, reuseVectors } = context + const requestId = generateRequestId() + const documentId = generateId() + const documentTags = documentTagsData(document, reader.manifest) + + const prepared: PreparedDocumentIndex | null = + document.chunks !== null && (reuseVectors || !document.file) + ? await reader.readChunks( + { + chunks: document.chunks, + chunkCount: document.chunkCount, + characterCount: document.characterCount, + }, + reuseVectors + ) + : null + + let source: { bytes: Buffer; filename: string; mimeType: string } + if (document.file) { + const fileTypeError = validateFileType(document.filename, document.mimeType) + if (fileTypeError) throw new OrchestrationError('validation', fileTypeError.message) + source = { + bytes: await reader.readFile(document.file), + filename: document.filename, + mimeType: document.mimeType, + } + } else if (prepared) { + const bytes = Buffer.from(prepared.chunks.map((chunk) => chunk.text).join('\n\n')) + if (bytes.byteLength === 0) { + throw new OrchestrationError('validation', EMPTY_KNOWLEDGE_DOCUMENT_MESSAGE) + } + if (bytes.byteLength > MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE) { + throw new OrchestrationError( + 'payload_too_large', + 'Document text exceeds the 100MB knowledge document limit' + ) + } + source = { bytes, filename: textFilename(document.filename), mimeType: 'text/plain' } + } else { + throw new Error(`Bundle document ${document.id} has neither a file nor chunks`) + } + + const uploadedArtifact = await uploadKnowledgeArtifact({ + documentId, + key: generateKnowledgeBaseFileKey(source.filename), + owner: { workspaceId: payload.workspaceId, userId: payload.userId }, + artifact: { bytes: source.bytes, fileName: source.filename, mimeType: source.mimeType }, + }) + const docData = { + filename: source.filename, + fileUrl: `${uploadedArtifact.path}?context=knowledge-base`, + fileSize: source.bytes.byteLength, + mimeType: source.mimeType, + } + await createSingleDocument( + { ...docData, documentTagsData: documentTags }, + knowledgeBaseId, + requestId, + payload.userId, + documentId, + undefined, + { + expectedWorkspaceId: payload.workspaceId, + enabled: document.enabled, + uploadedArtifact, + ...(prepared + ? {} + : { + processing: { + processingOptions: {}, + billingAttribution: payload.billingAttribution, + }, + }), + } + ) + + if (prepared) { + await processDocumentAsync( + knowledgeBaseId, + documentId, + docData, + {}, + createWorkspaceDocumentProcessingBillingContext(payload.billingAttribution), + undefined, + { chargedAtDispatch: false, preparedIndex: prepared } + ) + } +} + +/** + * Creates the base the bundle describes, with its tag definitions, and + * imports every document in manifest order. A document that cannot be + * imported is recorded and skipped; anything that stops the base itself from + * being created fails the whole import. + */ +async function importBundle( + payload: KnowledgeImportPayload, + reader: KnowledgeBundleReader +): Promise { + const { manifest } = reader + const target = await getConfiguredKbEmbedding() + const reuseVectors = canReuseVectors(manifest, target) + const requestId = generateRequestId() + await reader.validateChunks(reuseVectors) + + // A cancel that landed while the bundle was downloading or being validated stops it here. + if (!(await updateRunningKnowledgeImport(payload.importId, {}))) return + const knowledgeBase = await createAuthorizedKnowledgeBase( + { + id: payload.importId, + name: payload.name ?? manifest.knowledgeBase.name, + description: manifest.knowledgeBase.description ?? undefined, + workspaceId: payload.workspaceId, + folderId: null, + userId: payload.userId, + embeddingModel: target.model, + embeddingDimension: target.dimensions, + chunkingConfig: manifest.knowledgeBase.chunkingConfig, + }, + requestId + ) + const attached = await updateRunningKnowledgeImport(payload.importId, { + knowledgeBaseId: knowledgeBase.id, + documentsTotal: manifest.documents.length, + vectorsReused: reuseVectors, + }) + if (!attached) { + // Canceled between the check above and now: the base is still empty, so it goes too. + await deleteKnowledgeBase(knowledgeBase.id, requestId) + return + } + + try { + for (const tag of manifest.tags) { + await createTagDefinition( + { + knowledgeBaseId: knowledgeBase.id, + tagSlot: tag.slot, + displayName: tag.displayName, + fieldType: tag.fieldType, + }, + requestId + ) + } + } catch (error) { + // No document has landed yet, so a base without its tags is removed rather than kept half-built. + await deleteKnowledgeBase(knowledgeBase.id, requestId) + throw error + } + + const context: ImportDocumentContext = { + payload, + reader, + knowledgeBaseId: knowledgeBase.id, + reuseVectors, + } + let documentsImported = 0 + let documentsFailed = 0 + const failures: KnowledgeImportFailure[] = [] + // Chained so concurrent documents report in order; each write reads the counts as they stand. + let reported = Promise.resolve(true) + const report = () => { + reported = reported.then( + (running) => + running && + updateRunningKnowledgeImport(payload.importId, { + documentsImported, + documentsFailed, + failures: [...failures], + }) + ) + return reported + } + let stopped = false + await mapWithConcurrency(manifest.documents, DOCUMENT_CONCURRENCY, async (document) => { + if (stopped) return + try { + await importDocument(context, document) + documentsImported++ + } catch (error) { + documentsFailed++ + if (failures.length < MAX_KNOWLEDGE_IMPORT_FAILURE_SAMPLES) { + failures.push({ + filename: document.filename, + message: callerMessage(error) ?? 'This document could not be imported', + }) + } + logger.warn('Knowledge import skipped a document', { + importId: payload.importId, + knowledgeBaseId: knowledgeBase.id, + bundleDocumentId: document.id, + error: getErrorMessage(error, 'Unknown error'), + }) + } + if (!(await report())) stopped = true + }) + if (stopped || !(await reported)) return + await finishKnowledgeImport(payload.importId, { status: 'completed' }) + logger.info('Knowledge import completed', { + importId: payload.importId, + knowledgeBaseId: knowledgeBase.id, + documentsImported, + documentsFailed, + vectorsReused: reuseVectors, + }) +} + +/** + * Runs one import to a settled state. The worker claims the import first, so a + * second dispatch of it leaves the first worker's bundle alone. The bundle is + * copied to local disk so its entries can be read by offset, and both copies + * are removed however the import ends. + */ +export async function runKnowledgeImport(payload: KnowledgeImportPayload): Promise { + if (!(await claimKnowledgeImport(payload.importId))) { + // Settled before any worker claimed it, so no worker is reading the bundle. + const record = await findKnowledgeImport({ importId: payload.importId }) + if (record && !record.startedAt) await deleteBundle(payload) + return + } + const directory = await mkdtemp(join(tmpdir(), 'knowledge-import-')) + let reader: KnowledgeBundleReader | undefined + try { + const path = join(directory, 'bundle.zip') + await pipeline( + await downloadFileStream({ + key: payload.sourceKey, + context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT, + }), + createWriteStream(path) + ) + reader = await openKnowledgeBundle(path) + await importBundle(payload, reader) + } catch (error) { + const message = callerMessage(error) + if (!message) logger.error('Knowledge import failed', { importId: payload.importId, error }) + await finishKnowledgeImport(payload.importId, { + status: 'failed', + error: message ?? 'Knowledge base import failed', + }).catch((finishError: unknown) => { + logger.error('Failed to record a knowledge import failure', { + importId: payload.importId, + error: getErrorMessage(finishError, 'Unknown error'), + }) + }) + } finally { + reader?.close() + await rm(directory, { recursive: true, force: true }) + await deleteBundle(payload) + } +} + +async function deleteBundle(payload: KnowledgeImportPayload): Promise { + await deleteFile({ key: payload.sourceKey, context: KNOWLEDGE_IMPORT_STORAGE_CONTEXT }).catch( + (error: unknown) => { + logger.warn('Failed to delete an imported knowledge bundle', { + importId: payload.importId, + error: getErrorMessage(error, 'Unknown error'), + }) + } + ) +} diff --git a/apps/sim/lib/mothership/tools/cli-tool-display.ts b/apps/sim/lib/mothership/tools/cli-tool-display.ts index 4b7aca0c4e7..d7d50fcaca6 100644 --- a/apps/sim/lib/mothership/tools/cli-tool-display.ts +++ b/apps/sim/lib/mothership/tools/cli-tool-display.ts @@ -78,6 +78,9 @@ export const CLI_TOOL_TITLES: Record = { cli_knowledge_folders_move: 'Moving knowledge folder', cli_knowledge_from_workspace_files_create: 'Creating knowledge base', cli_knowledge_get: 'Reading knowledge base', + cli_knowledge_import: 'Importing knowledge base', + cli_knowledge_imports_cancel: 'Cancelling knowledge base import', + cli_knowledge_imports_get: 'Reading knowledge base import', cli_knowledge_list: 'Listing knowledge bases', cli_knowledge_ls: 'Listing knowledge bases', cli_knowledge_mkdir: 'Creating knowledge base', diff --git a/apps/sim/lib/table/backfill-runner.ts b/apps/sim/lib/table/backfill-runner.ts index 0ddd65d8e09..ad93dc810f7 100644 --- a/apps/sim/lib/table/backfill-runner.ts +++ b/apps/sim/lib/table/backfill-runner.ts @@ -5,8 +5,7 @@ import { getErrorMessage } from '@sim/utils/errors' import { generateId } from '@sim/utils/id' import { getValueAtPath, isRecordLike } from '@sim/utils/object' import { and, asc, count, eq, gt, inArray } from 'drizzle-orm' -import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' -import { runDetached } from '@/lib/core/utils/background' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' import { MATERIALIZE_CONCURRENCY, mapWithConcurrency } from '@/lib/core/utils/concurrency' import { type FunctionalExecutionDataSource, @@ -29,6 +28,7 @@ import type { TableDefinition, WorkflowGroupOutput, } from '@/lib/table/types' +import type { tableBackfillTask } from '@/background/table-backfill' import { isResolvedSecretTraceProvenanceV1, RESOLVED_SECRET_TRACE_CHECKPOINT_VERSION, @@ -421,29 +421,20 @@ export async function maybeBackfillGroupOutputs(opts: { actorUserId, capabilityGovernedUserId, } - if (isTriggerDevEnabled) { - try { - const [{ tableBackfillTask }, { tasks }, { resolveTriggerRegion }] = await Promise.all([ - import('@/background/table-backfill'), - import('@trigger.dev/sdk'), - import('@/lib/core/async-jobs/region'), - ]) - await tasks.trigger('table-backfill', payload, { - tags: [`tableId:${table.id}`, `jobId:${jobId}`], - region: await resolveTriggerRegion(), - }) - } catch (error) { - // Release the claim so a ghost `running` job doesn't block imports/deletes. - // Swallowed (warn only): a failed backfill never fails the schema change — - // the data stays backfillable. - const { releaseJobClaim } = await import('@/lib/table/jobs/service') - await releaseJobClaim(table.id, jobId).catch(() => {}) - logger.warn( - `[${requestId}] Backfill dispatch failed for table ${table.id} group ${groupId}; skipping`, - { error: getErrorMessage(error) } - ) - } - } else { - runDetached('table-backfill', () => runTableBackfill(payload)) + try { + await dispatchBackgroundTask('table-backfill', payload, { + runInProcess: runTableBackfill, + trigger: { tags: [`tableId:${table.id}`, `jobId:${jobId}`] }, + }) + } catch (error) { + // Release the claim so a ghost `running` job doesn't block imports/deletes. + // Swallowed (warn only): a failed backfill never fails the schema change — + // the data stays backfillable. + const { releaseJobClaim } = await import('@/lib/table/jobs/service') + await releaseJobClaim(table.id, jobId).catch(() => {}) + logger.warn( + `[${requestId}] Backfill dispatch failed for table ${table.id} group ${groupId}; skipping`, + { error: getErrorMessage(error) } + ) } } diff --git a/apps/sim/lib/table/orchestration/export-resource.ts b/apps/sim/lib/table/orchestration/export-resource.ts index 6f8410d5c1a..928f09f2135 100644 --- a/apps/sim/lib/table/orchestration/export-resource.ts +++ b/apps/sim/lib/table/orchestration/export-resource.ts @@ -4,13 +4,13 @@ import { getErrorMessage } from '@sim/utils/errors' import { generateId } from '@sim/utils/id' import { and, eq } from 'drizzle-orm' import type { V2TableExport, V2TableExportStatus } from '@/lib/api/contracts/v2/tables' -import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' import { OrchestrationError } from '@/lib/core/orchestration/types' -import { runDetached } from '@/lib/core/utils/background' import { TABLE_LIMITS } from '@/lib/table/constants' import { runTableExport, type TableExportPayload } from '@/lib/table/export-runner' import { markTableJobRunningInWorkspace } from '@/lib/table/jobs/service' import type { TableDefinition, TableExportJobPayload } from '@/lib/table/types' +import type { tableExportTask } from '@/background/table-export' export type TableExportRecord = typeof tableJobs.$inferSelect @@ -42,19 +42,10 @@ export async function createTableExportResource(params: { await runTableExport(runnerPayload) } else { try { - if (isTriggerDevEnabled) { - const [{ tableExportTask }, { tasks }, { resolveTriggerRegion }] = await Promise.all([ - import('@/background/table-export'), - import('@trigger.dev/sdk'), - import('@/lib/core/async-jobs/region'), - ]) - await tasks.trigger('table-export', runnerPayload, { - tags: [`tableId:${params.table.id}`, `jobId:${exportId}`], - region: await resolveTriggerRegion(), - }) - } else { - runDetached('table-export', () => runTableExport(runnerPayload)) - } + await dispatchBackgroundTask('table-export', runnerPayload, { + runInProcess: runTableExport, + trigger: { tags: [`tableId:${params.table.id}`, `jobId:${exportId}`] }, + }) } catch (error) { await markExportFailed({ tableId: params.table.id, diff --git a/apps/sim/lib/table/orchestration/import-resource.ts b/apps/sim/lib/table/orchestration/import-resource.ts index ac7468efb7a..d01e427d7d8 100644 --- a/apps/sim/lib/table/orchestration/import-resource.ts +++ b/apps/sim/lib/table/orchestration/import-resource.ts @@ -17,9 +17,8 @@ import { v2TableImportSourceSchema, v2TableImportTargetSchema, } from '@/lib/api/contracts/v2/tables' -import { isTriggerDevEnabled } from '@/lib/core/config/env-flags' +import { dispatchBackgroundTask } from '@/lib/core/async-jobs/background-task' import { OrchestrationError } from '@/lib/core/orchestration/types' -import { runDetached } from '@/lib/core/utils/background' import { generateRequestId } from '@/lib/core/utils/request' import { findActiveFolder } from '@/lib/folders/queries' import { getWorkspaceTableLimits } from '@/lib/table/billing' @@ -43,9 +42,11 @@ import { type CreatedUploadSession, createUploadSession, getOwnedUploadSession, + importStatusForUploadSession, type UploadSessionRecord, } from '@/lib/uploads/upload-session/service' import { getUserSettings } from '@/lib/users/queries' +import type { tableImportTask } from '@/background/table-import' const logger = createLogger('TableImportResource') @@ -411,19 +412,10 @@ async function startTableImport(params: StartTableImportParams): Promise('table-import', payload, { - tags: [`tableId:${tableId}`, `jobId:${params.id}`], - region: await resolveTriggerRegion(), - }) - } else { - runDetached('table-import', () => runTableImport(payload)) - } + await dispatchBackgroundTask('table-import', payload, { + runInProcess: runTableImport, + trigger: { tags: [`tableId:${tableId}`, `jobId:${params.id}`] }, + }) return getTableImportResource({ importId: params.id, assertedWorkspaceId: params.workspaceId, @@ -477,7 +469,7 @@ function resourceFromUpload( target: body.target, options: importOptions(body), tableId: body.target.type === 'existing' ? body.target.tableId : null, - status: uploadStatus(upload), + status: importStatusForUploadSession(upload.status), rowsProcessed: 0, rowsRejected: 0, cellsRejected: 0, @@ -650,23 +642,6 @@ async function requireWorkspaceSource( return resolved } -function uploadStatus(upload: UploadSessionRecord): TableImportStatus { - switch (upload.status) { - case 'uploading': - case 'completing': - case 'finalizing': - case 'completed': - return 'uploading' - case 'aborting': - case 'aborted': - return 'canceled' - case 'failed': - return 'failed' - case 'expired': - return 'expired' - } -} - async function markImportFailed(params: { tableId: string workspaceId: string diff --git a/apps/sim/lib/uploads/config.ts b/apps/sim/lib/uploads/config.ts index c2f01f76033..e1f5e8b2c1d 100644 --- a/apps/sim/lib/uploads/config.ts +++ b/apps/sim/lib/uploads/config.ts @@ -224,6 +224,7 @@ function getS3Config(context: StorageContext): StorageConfig { case 'test': case 'changelog': case 'table-import': + case 'knowledge-import': case 'organization-logos': return { bucket: S3_CONFIG.bucket, @@ -291,6 +292,7 @@ function getBlobConfig(context: StorageContext): StorageConfig { case 'test': case 'changelog': case 'table-import': + case 'knowledge-import': case 'organization-logos': return { accountName: BLOB_CONFIG.accountName, @@ -355,6 +357,7 @@ function getGcsConfig(context: StorageContext): StorageConfig { case 'test': case 'changelog': case 'table-import': + case 'knowledge-import': case 'organization-logos': return { bucket: GCS_CONFIG.bucket } case 'profile-pictures': diff --git a/apps/sim/lib/uploads/shared/types.ts b/apps/sim/lib/uploads/shared/types.ts index 02502593d30..097718ffccd 100644 --- a/apps/sim/lib/uploads/shared/types.ts +++ b/apps/sim/lib/uploads/shared/types.ts @@ -73,6 +73,7 @@ export type StorageContext = | 'test' | 'changelog' | 'table-import' + | 'knowledge-import' | 'profile-pictures' | 'og-images' | 'logs' diff --git a/apps/sim/lib/uploads/upload-session/service.test.ts b/apps/sim/lib/uploads/upload-session/service.test.ts index 1420925a282..eb09c6594a1 100644 --- a/apps/sim/lib/uploads/upload-session/service.test.ts +++ b/apps/sim/lib/uploads/upload-session/service.test.ts @@ -334,6 +334,7 @@ describe('upload sessions', () => { it.each([ ['knowledge_document', { knowledgeBaseId: 'kb-1' }], ['table_import', {}], + ['knowledge_import', {}], ['profile_picture', {}], ['workspace_logo', {}], ['execution_attachment', { workflowId: 'workflow-1', executionId: 'execution-1' }], @@ -560,6 +561,7 @@ describe('upload sessions', () => { it.each([ ['workspace_file', 'sim:workspace-files'], ['knowledge_document', 'sim:knowledge'], + ['knowledge_import', 'sim:knowledge'], ['table_import', 'sim:tables'], ] as const)( 'binds %s Copilot uploads to the actual subject/chat/workspace across refreshed calls', diff --git a/apps/sim/lib/uploads/upload-session/service.ts b/apps/sim/lib/uploads/upload-session/service.ts index cdc758c58a7..ad73dc99b32 100644 --- a/apps/sim/lib/uploads/upload-session/service.ts +++ b/apps/sim/lib/uploads/upload-session/service.ts @@ -226,6 +226,7 @@ export type CreateUploadSessionParams = CreateUploadSessionBaseParams & secretProvenance?: WorkspaceFileUploadSource } | { purpose: 'table_import'; workspaceId: string; principal?: Principal } + | { purpose: 'knowledge_import'; workspaceId: string; principal: Principal } | { purpose: 'knowledge_document' workspaceId: string @@ -408,7 +409,11 @@ export async function createUploadSession( ) } } - if (params.purpose === 'workspace_file' || params.purpose === 'knowledge_document') { + if ( + params.purpose === 'workspace_file' || + params.purpose === 'knowledge_document' || + params.purpose === 'knowledge_import' + ) { if (!workspaceId) throw new Error(`${params.purpose} upload is missing workspaceId`) if (!params.principal) { throw new Error(`${params.purpose} upload requires an authenticated principal`) @@ -750,7 +755,9 @@ export function assertUploadSessionAuthBinding( if (!isPrincipalBoundUploadPurpose(session.purpose)) return const candidate = session.metadata.authBinding if (candidate === undefined) { - if (session.purpose === 'table_import') throw uploadNotFound() + if (session.purpose === 'table_import' || session.purpose === 'knowledge_import') { + throw uploadNotFound() + } assertLegacyUploadSessionOwner(session, principal) return } @@ -1278,6 +1285,29 @@ export function expectedUploadPartSize(session: UploadSessionRecord, partNumber: return session.fileSize - session.partSize * (session.partCount - 1) } +/** + * How an import resource built on an upload session reads while it is still + * that session: everything short of a settled outcome is still `uploading`. + */ +export function importStatusForUploadSession( + status: UploadSessionStatus +): 'uploading' | 'canceled' | 'failed' | 'expired' { + switch (status) { + case 'uploading': + case 'completing': + case 'finalizing': + case 'completed': + return 'uploading' + case 'aborting': + case 'aborted': + return 'canceled' + case 'failed': + return 'failed' + case 'expired': + return 'expired' + } +} + export function uploadSessionObjectMetadata( session: Pick< UploadSessionRecord, @@ -1582,7 +1612,7 @@ function requiresStorageQuota(purpose: UploadSessionPurpose): boolean { function copilotUploadAudience(purpose: UploadSessionPurpose): string | undefined { if (purpose === 'workspace_file') return WORKSPACE_FILES_DELEGATION_AUDIENCE - if (purpose === 'knowledge_document') return 'sim:knowledge' + if (purpose === 'knowledge_document' || purpose === 'knowledge_import') return 'sim:knowledge' if (purpose === 'table_import') return 'sim:tables' return undefined } @@ -1593,6 +1623,7 @@ function isPrincipalBoundUploadPurpose(purpose: UploadSessionPurpose): boolean { purpose === 'project_file' || purpose === 'knowledge_document' || purpose === 'table_import' || + purpose === 'knowledge_import' || purpose === 'mothership_attachment' || purpose === 'organization_logo' ) @@ -1618,6 +1649,11 @@ function resolveUploadStorage( storageContext: 'table-import', finalKey: `table-import/${params.workspaceId}/${id}/${buildStorageKeySegment('', params.fileName)}`, } + case 'knowledge_import': + return { + storageContext: 'knowledge-import', + finalKey: `knowledge-import/${params.workspaceId}/${id}/${buildStorageKeySegment('', params.fileName)}`, + } case 'knowledge_document': return { storageContext: 'knowledge-base', @@ -1669,6 +1705,7 @@ function isStorageContext(value: string): value is StorageContext { 'workspace', 'project', 'table-import', + 'knowledge-import', 'knowledge-base', 'profile-pictures', 'workspace-logos', diff --git a/apps/sim/lib/uploads/upload-session/types.ts b/apps/sim/lib/uploads/upload-session/types.ts index 24e823d3c90..0c7404fb464 100644 --- a/apps/sim/lib/uploads/upload-session/types.ts +++ b/apps/sim/lib/uploads/upload-session/types.ts @@ -5,6 +5,7 @@ export type UploadSessionPurpose = | 'workspace_file' | 'project_file' | 'table_import' + | 'knowledge_import' | 'knowledge_document' | 'profile_picture' | 'workspace_logo' diff --git a/apps/sim/lib/users/storage-sweep.test.ts b/apps/sim/lib/users/storage-sweep.test.ts index 7d25cc24c89..b8bca298f88 100644 --- a/apps/sim/lib/users/storage-sweep.test.ts +++ b/apps/sim/lib/users/storage-sweep.test.ts @@ -122,6 +122,7 @@ const DOOMED_KEYS = [ 'table-snapshots/wsdoomed1/table-1/v1-hash.csv', 'copilot-doc-compiled/wsdoomed1/hash.pdf', 'workspace-logos/wsdoomed1/logo.png', + 'knowledge-import/wsdoomed1/import-1/bundle.simkb.zip', ] const NEIGHBOR_KEYS = [ diff --git a/apps/sim/lib/users/storage-sweep.ts b/apps/sim/lib/users/storage-sweep.ts index 04b57f8aa80..650a4bbc52a 100644 --- a/apps/sim/lib/users/storage-sweep.ts +++ b/apps/sim/lib/users/storage-sweep.ts @@ -82,6 +82,7 @@ const OBJECT_CONTEXTS: ReadonlySet = new Set([ 'knowledge-base', 'execution', 'table-import', + 'knowledge-import', 'workspace-logos', ]) diff --git a/apps/sim/lib/users/workspace-storage.ts b/apps/sim/lib/users/workspace-storage.ts index 0c4d54c2af2..76d776c30fd 100644 --- a/apps/sim/lib/users/workspace-storage.ts +++ b/apps/sim/lib/users/workspace-storage.ts @@ -18,6 +18,7 @@ export const WORKSPACE_STORAGE_FAMILIES = [ { root: 'table-snapshots', context: 'execution' }, { root: 'copilot-doc-compiled', context: 'copilot' }, { root: 'workspace-logos', context: 'workspace-logos' }, + { root: 'knowledge-import', context: 'knowledge-import' }, ] as const satisfies readonly { root: string; context: StorageContext }[] const WORKSPACE_KEYED_ROOTS: ReadonlySet = new Set( diff --git a/apps/sim/package.json b/apps/sim/package.json index 8c1ecd2e8ff..dcee870e274 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -277,6 +277,7 @@ "word-extractor": "1.0.4", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "y-protocols": "1.0.7", + "yauzl": "3.4.0", "yjs": "13.6.33", "zod": "4.3.6", "zustand": "^5.0.15" @@ -307,6 +308,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "@types/ssh2": "^1.15.6", + "@types/yauzl": "3.4.0", "@vitejs/plugin-react": "^6.1.2", "@vitest/coverage-v8": "^5.0.4", "@vitest/expect": "5.0.4", diff --git a/bun.lock b/bun.lock index 8c97ea4e708..c5df653ec42 100644 --- a/bun.lock +++ b/bun.lock @@ -392,6 +392,7 @@ "word-extractor": "1.0.4", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "y-protocols": "1.0.7", + "yauzl": "3.4.0", "yjs": "13.6.33", "zod": "4.3.6", "zustand": "^5.0.15", @@ -422,6 +423,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "@types/ssh2": "^1.15.6", + "@types/yauzl": "3.4.0", "@vitejs/plugin-react": "^6.1.2", "@vitest/coverage-v8": "^5.0.4", "@vitest/expect": "5.0.4", @@ -2422,6 +2424,8 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@types/yauzl": ["@types/yauzl@3.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-NRPn5w6h8dhcnmx3YIRQcqMywY/+nND/uOkJessedcrowO3C0AssHp3tMJpxKAwOhFOo0OV1y9VtsC5hbKKBAw=="], + "@typescript/native": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], "@typescript/old": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], @@ -5534,6 +5538,8 @@ "@types/ws/@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="], + "@types/yauzl/@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="], + "@typespec/ts-http-runtime/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "@xyflow/react/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], diff --git a/packages/audit/src/types.ts b/packages/audit/src/types.ts index 5faf0ed77eb..db992a2988a 100644 --- a/packages/audit/src/types.ts +++ b/packages/audit/src/types.ts @@ -130,6 +130,7 @@ export const AuditAction = { KNOWLEDGE_BASE_DELETED: 'knowledge_base.deleted', KNOWLEDGE_BASE_RESTORED: 'knowledge_base.restored', KNOWLEDGE_BASE_EXPORTED: 'knowledge_base.exported', + KNOWLEDGE_BASE_IMPORT_STARTED: 'knowledge_base.import_started', MCP_SERVER_ADDED: 'mcp_server.added', MCP_SERVER_UPDATED: 'mcp_server.updated', diff --git a/packages/db/migrations/0436_knowledge_base_import.sql b/packages/db/migrations/0436_knowledge_base_import.sql new file mode 100644 index 00000000000..21a5637a4c6 --- /dev/null +++ b/packages/db/migrations/0436_knowledge_base_import.sql @@ -0,0 +1,24 @@ +ALTER TYPE "public"."upload_session_purpose" ADD VALUE IF NOT EXISTS 'knowledge_import' BEFORE 'knowledge_document';--> statement-breakpoint +CREATE TABLE "knowledge_base_import" ( + "id" text PRIMARY KEY NOT NULL, + "workspace_id" text NOT NULL, + "user_id" text NOT NULL, + "source_key" text NOT NULL, + "knowledge_base_id" text, + "status" text DEFAULT 'running' NOT NULL, + "documents_total" integer DEFAULT 0 NOT NULL, + "documents_imported" integer DEFAULT 0 NOT NULL, + "documents_failed" integer DEFAULT 0 NOT NULL, + "vectors_reused" boolean DEFAULT false NOT NULL, + "failures" jsonb DEFAULT '[]'::jsonb NOT NULL, + "error" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "started_at" timestamp, + "updated_at" timestamp DEFAULT now() NOT NULL, + "completed_at" timestamp +); +--> statement-breakpoint +ALTER TABLE "knowledge_base_import" ADD CONSTRAINT "knowledge_base_import_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knowledge_base_import" ADD CONSTRAINT "knowledge_base_import_knowledge_base_id_knowledge_base_id_fk" FOREIGN KEY ("knowledge_base_id") REFERENCES "public"."knowledge_base"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "knowledge_base_import_watchdog_idx" ON "knowledge_base_import" USING btree ("status","updated_at");--> statement-breakpoint +CREATE INDEX "knowledge_base_import_knowledge_base_id_idx" ON "knowledge_base_import" USING btree ("knowledge_base_id"); \ No newline at end of file diff --git a/packages/db/migrations/meta/0436_snapshot.json b/packages/db/migrations/meta/0436_snapshot.json new file mode 100644 index 00000000000..7c3f7d3577b --- /dev/null +++ b/packages/db/migrations/meta/0436_snapshot.json @@ -0,0 +1,31691 @@ +{ + "id": "0ac8e6c1-9440-4310-9af4-7ab28dc2de42", + "prevId": "2a4095de-e341-4264-becd-1714d26404f5", + "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'" + }, + "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.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_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.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": "'{}'" + }, + "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_run_id_idx": { + "name": "copilot_async_tool_calls_run_id_idx", + "columns": [ + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_user_id_idx": { + "name": "copilot_chats_user_id_idx", + "columns": [ + { + "expression": "user_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_run_id_idx": { + "name": "copilot_run_checkpoints_run_id_idx", + "columns": [ + { + "expression": "run_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_id_idx": { + "name": "copilot_runs_chat_id_idx", + "columns": [ + { + "expression": "chat_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_workspace_id_idx": { + "name": "copilot_runs_workspace_id_idx", + "columns": [ + { + "expression": "workspace_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_unique": { + "name": "credential_group_option_unique", + "columns": [ + { + "expression": "credential_group_enrollment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "credential_group_option_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"credential\".\"type\" = 'managed_oauth'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "credential_managed_mcp_enrollment_server_unique": { + "name": "credential_managed_mcp_enrollment_server_unique", + "columns": [ + { + "expression": "credential_group_enrollment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "mcp_server_id", + "isExpression": false, + "asc": 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 provider_subject_id IS NULL\n AND provider_tenant_id 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_id_idx": { + "name": "credential_group_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_organization_id_idx": { + "name": "custom_block_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_id_idx": { + "name": "custom_tools_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_org_idx": { + "name": "data_drains_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_kb_id_idx": { + "name": "doc_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_execution_logs_schedule_id_idx": { + "name": "job_execution_logs_schedule_id_idx", + "columns": [ + { + "expression": "schedule_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "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_user_id_idx": { + "name": "kb_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "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": {} + }, + "kb_tag_definitions_kb_id_idx": { + "name": "kb_tag_definitions_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "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_organization_id_idx": { + "name": "ked_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_id_idx": { + "name": "keg_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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.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_idx": { + "name": "memory_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "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.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_id_idx": { + "name": "permission_group_member_group_id_idx", + "columns": [ + { + "expression": "permission_group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_user_id_idx": { + "name": "permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_type_idx": { + "name": "permissions_user_entity_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "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_group_idx": { + "name": "scim_group_mapping_group_idx", + "columns": [ + { + "expression": "group_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_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_organization_id_idx": { + "name": "sso_domain_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_idx": { + "name": "usage_log_billing_entity_period_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" + } + ], + "isUnique": false, + "where": "\"usage_log\".\"billing_entity_type\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "usage_log_billing_period_cost_idx": { + "name": "usage_log_billing_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": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "billing_period_end", + "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_idx": { + "name": "usage_log_workspace_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": {} + }, + "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": {} + } + }, + "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_user_id_idx": { + "name": "workflow_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_user_id_idx": { + "name": "workflow_checkpoints_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_id_idx": { + "name": "workflow_checkpoints_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_id_idx": { + "name": "workflow_edges_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_workflow_id_idx": { + "name": "workflow_execution_logs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_started_at_idx": { + "name": "workflow_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": {} + }, + "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_workflow_id_idx": { + "name": "workflow_snapshots_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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 + }, + "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_id_idx": { + "name": "workflow_subflows_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_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_child_ws_wf_idx": { + "name": "workspace_fork_dependent_value_child_ws_wf_idx", + "columns": [ + { + "expression": "child_workspace_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_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_ws_idx": { + "name": "workspace_fork_resource_map_child_ws_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_fork_resource_map_child_ws_type_idx": { + "name": "workspace_fork_resource_map_child_ws_type_idx", + "columns": [ + { + "expression": "child_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "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_workspace_idx": { + "name": "workspace_sandbox_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "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.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": {} + } +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index b46b8f5a4e3..beb294317de 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -3046,6 +3046,13 @@ "when": 1792364982159, "tag": "0435_workspace_billed_account_user_index", "breakpoints": true + }, + { + "idx": 436, + "version": "7", + "when": 1792721320645, + "tag": "0436_knowledge_base_import", + "breakpoints": true } ] } diff --git a/packages/db/schema.ts b/packages/db/schema.ts index e98c296b45c..5c058e67c48 100644 --- a/packages/db/schema.ts +++ b/packages/db/schema.ts @@ -3304,6 +3304,7 @@ export const uploadSessionPurposeEnum = pgEnum('upload_session_purpose', [ 'workspace_file', 'project_file', 'table_import', + 'knowledge_import', 'knowledge_document', 'profile_picture', 'workspace_logo', @@ -3852,6 +3853,57 @@ export const knowledgeBase = pgTable( }) ) +/** + * One knowledge-base bundle import, from the moment its uploaded archive is + * complete. The id is the upload session's id, so the resource keeps one id + * across both halves of its life; the base it creates is linked once it exists. + */ +export const knowledgeBaseImport = pgTable( + 'knowledge_base_import', + { + id: text('id').primaryKey(), + workspaceId: text('workspace_id') + .notNull() + .references(() => workspace.id, { onDelete: 'cascade' }), + /** + * Attribution only, with no foreign key: the row is the janitor's handle on + * the bundle and the base, so it must outlive its importer's account. + */ + userId: text('user_id').notNull(), + /** The uploaded archive, deleted once the import settles. */ + sourceKey: text('source_key').notNull(), + knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBase.id, { + onDelete: 'set null', + }), + status: text('status') + .$type<'running' | 'completed' | 'failed' | 'canceled'>() + .notNull() + .default('running'), + documentsTotal: integer('documents_total').notNull().default(0), + documentsImported: integer('documents_imported').notNull().default(0), + documentsFailed: integer('documents_failed').notNull().default(0), + /** Whether the bundle's vectors matched this deployment's embedding model and were kept. */ + vectorsReused: boolean('vectors_reused').notNull().default(false), + /** The first few documents that could not be imported, as `{ filename, message }`. */ + failures: jsonb('failures') + .$type<{ filename: string; message: string }[]>() + .notNull() + .default([]), + error: text('error'), + createdAt: timestamp('created_at').notNull().defaultNow(), + /** When a worker claimed the import; unset, a retried completion dispatches it again. */ + startedAt: timestamp('started_at'), + updatedAt: timestamp('updated_at').notNull().defaultNow(), + completedAt: timestamp('completed_at'), + }, + (table) => ({ + watchdogIdx: index('knowledge_base_import_watchdog_idx').on(table.status, table.updatedAt), + knowledgeBaseIdIdx: index('knowledge_base_import_knowledge_base_id_idx').on( + table.knowledgeBaseId + ), + }) +) + export const document = pgTable( 'document', { diff --git a/packages/sim-cli/README.md b/packages/sim-cli/README.md index be70de15961..841003b2e14 100644 --- a/packages/sim-cli/README.md +++ b/packages/sim-cli/README.md @@ -236,6 +236,7 @@ The commands you will use most often are: | Search knowledge bases | `sim knowledge search --query "refund policy" --kb ` | | Upload a knowledge document | `sim knowledge documents upload ./handbook.pdf` | | Export a knowledge base | `sim knowledge export -o ./kb.simkb.zip` | +| Import a knowledge base | `sim knowledge import ./kb.simkb.zip` | | Manage integration credentials | `sim credentials --help` | | Manage workspace secrets | `sim secrets list`, `sim secrets set ` | diff --git a/packages/sim-cli/src/commands/protocol/index.ts b/packages/sim-cli/src/commands/protocol/index.ts index edc1209833f..daed7089f82 100644 --- a/packages/sim-cli/src/commands/protocol/index.ts +++ b/packages/sim-cli/src/commands/protocol/index.ts @@ -11,6 +11,7 @@ import { import { attachFileUpload, attachProjectFileUpload } from './files-upload' import { attachKnowledgeDocumentUpload } from './knowledge-document-upload' import { attachKnowledgeExport } from './knowledge-export' +import { attachKnowledgeImport } from './knowledge-import' import { attachLogsFollow } from './logs-follow' import { attachResourceDirectoryCommands } from './resource-directory' import { attachTableImport } from './tables-import' @@ -49,6 +50,7 @@ export function attachProtocolCommands(program: Command): void { const knowledge = group(program, 'knowledge') attachKnowledgeDocumentUpload(group(knowledge, 'documents')) attachKnowledgeExport(knowledge) + attachKnowledgeImport(knowledge) attachResourceDirectoryCommands(knowledge, { kind: 'knowledge', resources: 'listKnowledgeBases', diff --git a/packages/sim-cli/src/commands/protocol/knowledge-import.test.ts b/packages/sim-cli/src/commands/protocol/knowledge-import.test.ts new file mode 100644 index 00000000000..2984fb02170 --- /dev/null +++ b/packages/sim-cli/src/commands/protocol/knowledge-import.test.ts @@ -0,0 +1,202 @@ +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { Command } from 'commander' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { buildGeneratedCommands } from '../../runtime/build' +import { attachProtocolCommands } from './index' + +const { mockRequest } = vi.hoisted(() => ({ mockRequest: vi.fn() })) + +/** The poll loop's own wait; a real 1.5s pause per poll is not worth testing through. */ +vi.mock('node:timers/promises', () => ({ setTimeout: () => Promise.resolve() })) + +vi.mock('../../context', () => ({ + clientFrom: () => ({ + client: { request: mockRequest, requireWorkspace: () => 'ws_local' }, + profile: { + workspaceId: 'ws_local', + output: 'json', + name: 'default', + apiKey: 'k', + endpoint: 'https://sim.example', + }, + }), +})) + +let dir: string + +beforeEach(() => { + mockRequest.mockReset() + dir = mkdtempSync(join(tmpdir(), 'sim-kb-import-')) + vi.stubGlobal( + 'fetch', + vi.fn().mockResolvedValue(new Response(null, { status: 200, headers: { etag: '"etag-1"' } })) + ) +}) +afterEach(() => { + rmSync(dir, { recursive: true, force: true }) +}) + +function program(): Command { + const root = new Command('sim').exitOverride() + for (const group of buildGeneratedCommands()) root.addCommand(group) + attachProtocolCommands(root) + const override = (command: Command) => { + command.exitOverride() + command.commands.forEach(override) + } + override(root) + return root +} + +function bundlePath(name = 'support.simkb.zip'): string { + const path = join(dir, name) + writeFileSync(path, 'PK-bundle') + return path +} + +function importRecord(extra: Record = {}) { + return { + id: 'import_1', + workspaceId: 'ws_local', + status: 'uploading', + knowledgeBaseId: null, + documentsTotal: 0, + documentsImported: 0, + documentsFailed: 0, + vectorsReused: false, + failures: [], + error: null, + createdAt: '2026-10-22T00:00:00.000Z', + updatedAt: '2026-10-22T00:00:00.000Z', + completedAt: null, + ...extra, + } +} + +/** Create, then complete; the bundle bytes go to the signed URL in between. */ +function startedImport(completed: Record) { + mockRequest + .mockResolvedValueOnce({ + data: { + session: importRecord(), + uploadToken: 'secret-token', + transfer: { + method: 'put', + url: 'https://storage.example/bundle', + headers: { 'content-type': 'application/zip' }, + expiresAt: '2026-10-22T01:00:00.000Z', + }, + }, + }) + .mockResolvedValueOnce({ data: importRecord(completed) }) +} + +function captureOutput(): string[] { + const logged: string[] = [] + vi.spyOn(console, 'log').mockImplementation((line: string) => logged.push(line)) + return logged +} + +async function runImport(argv: string[]) { + await program().parseAsync(['node', 'sim', 'kb', 'import', ...argv]) +} + +describe('knowledge import', () => { + it('refuses a file that is not a zip archive before contacting the API', async () => { + await expect(runImport([bundlePath('support.tar')])).rejects.toThrow(/must be a \.zip archive/) + expect(mockRequest).not.toHaveBeenCalled() + }) + + it('uploads the bundle, waits for the import, and prints the new base without the upload token', async () => { + const path = bundlePath() + startedImport({ status: 'processing', documentsTotal: 2 }) + mockRequest.mockResolvedValueOnce({ + data: importRecord({ + status: 'completed', + knowledgeBaseId: 'kb_new', + documentsTotal: 2, + documentsImported: 2, + vectorsReused: true, + }), + }) + const logged = captureOutput() + + await runImport([path, '--name', 'Support copy']) + + expect(mockRequest.mock.calls[0]).toEqual([ + '/api/v2/knowledge/imports', + { + method: 'POST', + body: { + workspaceId: 'ws_local', + name: 'Support copy', + source: { + type: 'upload', + name: 'support.simkb.zip', + contentType: 'application/zip', + size: 9, + }, + }, + }, + ]) + expect(vi.mocked(fetch)).toHaveBeenCalledWith( + 'https://storage.example/bundle', + expect.objectContaining({ method: 'PUT' }) + ) + expect(mockRequest.mock.calls[1][0]).toBe('/api/v2/knowledge/imports/import_1/complete') + expect(mockRequest.mock.calls[2][0]).toBe('/api/v2/knowledge/imports/import_1') + expect(JSON.parse(logged[0])).toEqual({ + id: 'import_1', + status: 'completed', + knowledgeBaseId: 'kb_new', + documentsTotal: 2, + documentsImported: 2, + documentsFailed: 0, + vectorsReused: true, + }) + expect(logged[0]).not.toContain('secret-token') + }) + + it('returns once the import starts with --no-wait', async () => { + startedImport({ status: 'processing' }) + const logged = captureOutput() + + await runImport([bundlePath(), '--no-wait']) + + expect(mockRequest).toHaveBeenCalledTimes(2) + expect(JSON.parse(logged[0])).toMatchObject({ id: 'import_1', status: 'processing' }) + }) + + it('reports the documents an otherwise completed import skipped', async () => { + startedImport({ + status: 'completed', + knowledgeBaseId: 'kb_new', + documentsTotal: 2, + documentsImported: 1, + documentsFailed: 1, + failures: [{ filename: 'scan.tiff', message: 'Unsupported file type' }], + }) + const logged = captureOutput() + + await runImport([bundlePath()]) + + expect(JSON.parse(logged[0])).toMatchObject({ + documentsFailed: 1, + failures: ['scan.tiff: Unsupported file type'], + }) + }) + + it('fails with the import error when the import does not complete', async () => { + startedImport({ + status: 'failed', + error: 'Invalid knowledge base bundle: not a zip archive', + }) + captureOutput() + + await expect(runImport([bundlePath()])).rejects.toThrow( + 'Import failed: Invalid knowledge base bundle: not a zip archive' + ) + }) +}) diff --git a/packages/sim-cli/src/commands/protocol/knowledge-import.ts b/packages/sim-cli/src/commands/protocol/knowledge-import.ts new file mode 100644 index 00000000000..c78fc73221b --- /dev/null +++ b/packages/sim-cli/src/commands/protocol/knowledge-import.ts @@ -0,0 +1,120 @@ +import type { Command } from 'commander' +import type { + CompleteKnowledgeImportResponse, + CreateKnowledgeImportResponse, + GetKnowledgeImportResponse, +} from '../../generated/v2-api' +import { SimApiError } from '../../http/client' +import { apiCommand } from '../../runtime/called-operations' +import { watchImport } from '../../transfer/import-watch' +import { contentTypeFor, localFile } from '../../transfer/local-file' +import { finishUploadSession } from '../../transfer/upload-session' +import { printProtocolResult } from './result' + +type KnowledgeImport = GetKnowledgeImportResponse['data'] + +interface KnowledgeImportOptions { + name?: string + wait: boolean +} + +/** + * What the caller sees about an import. Failures are flattened to text because + * the result printer renders every field with `String(value)`, and only appear + * when a document was skipped, so a clean import keeps a short result. + */ +function importFields(job: KnowledgeImport): Record { + return { + id: job.id, + status: job.status, + knowledgeBaseId: job.knowledgeBaseId, + documentsTotal: job.documentsTotal, + documentsImported: job.documentsImported, + documentsFailed: job.documentsFailed, + vectorsReused: job.vectorsReused, + ...(job.failures.length > 0 + ? { failures: job.failures.map(({ filename, message }) => `${filename}: ${message}`) } + : {}), + } +} + +function progressLine(job: KnowledgeImport): string { + const failed = job.documentsFailed > 0 ? `, ${job.documentsFailed} failed` : '' + return `${job.status}… ${job.documentsImported}/${job.documentsTotal} documents${failed}` +} + +export function attachKnowledgeImport(knowledge: Command): void { + const [importCommand, connectImport] = apiCommand(knowledge, 'import', [ + 'createKnowledgeImport', + 'createKnowledgeImportPartUrls', + 'completeKnowledgeImport', + 'cancelKnowledgeImport', + 'getKnowledgeImport', + ]) + importCommand + .argument('', 'Bundle archive written by `sim knowledge export`') + .allowExcessArguments(false) + .description('Create a knowledge base from an exported .simkb.zip bundle') + .option('--name ', "Name for the new knowledge base; defaults to the bundle's own name") + .option('--no-wait', 'Return once the import is started instead of watching it') + .action(async (path: string, options: KnowledgeImportOptions) => { + const { client, profile } = connectImport() + const workspaceId = client.requireWorkspace() + const local = await localFile(path) + if (!local.name.toLowerCase().endsWith('.zip')) { + throw new SimApiError('A knowledge base bundle must be a .zip archive', 0) + } + + const started = await client.request('createKnowledgeImport', { + body: { + workspaceId, + ...(options.name !== undefined ? { name: options.name } : {}), + source: { + type: 'upload', + name: local.name, + contentType: contentTypeFor(local.name), + size: local.size, + }, + }, + }) + const job: CompleteKnowledgeImportResponse['data'] = await finishUploadSession( + client, + workspaceId, + { + operations: { + parts: 'createKnowledgeImportPartUrls', + complete: 'completeKnowledgeImport', + abort: 'cancelKnowledgeImport', + }, + params: { importId: started.data.session.id }, + uploadToken: started.data.uploadToken, + transfer: started.data.transfer, + size: local.size, + }, + path + ) + + if (!options.wait) { + printProtocolResult(profile.output, importFields(job)) + return + } + const finished = await watchImport( + job, + async (current) => + ( + await client.request<{ data: KnowledgeImport }>('getKnowledgeImport', { + params: { importId: current.id }, + query: { workspaceId }, + }) + ).data, + progressLine + ) + if (finished.status !== 'completed') { + throw new SimApiError( + `Import ${finished.status}${finished.error ? `: ${finished.error}` : ''}`, + 0 + ) + } + printProtocolResult(profile.output, importFields(finished)) + }) +} diff --git a/packages/sim-cli/src/commands/protocol/tables-import.ts b/packages/sim-cli/src/commands/protocol/tables-import.ts index 5777644c607..d84eb974eb7 100644 --- a/packages/sim-cli/src/commands/protocol/tables-import.ts +++ b/packages/sim-cli/src/commands/protocol/tables-import.ts @@ -1,15 +1,13 @@ -import { setTimeout as sleep } from 'node:timers/promises' import { type Command, Option } from 'commander' -import { writeStderr } from '#sim-cli/output/io' -import { hasProgressTerminal, styles } from '#sim-cli/output/presentation' import type { CompleteTableImportResponse, CreateTableImportResponse, GetTableImportResponse, } from '../../generated/v2-api' import { SimApiError } from '../../http/client' -import { apiCommand, type OperationClient } from '../../runtime/called-operations' +import { apiCommand } from '../../runtime/called-operations' import { coerce, encodeFolderPath, type FieldSpec } from '../../runtime/request' +import { watchImport } from '../../transfer/import-watch' import { contentTypeFor, localFile } from '../../transfer/local-file' import { finishUploadSession } from '../../transfer/upload-session' import { printProtocolResult } from './result' @@ -29,9 +27,6 @@ interface ImportOptions { yes?: boolean } -const IMPORT_POLL_MS = 1500 -const IMPORT_SETTLED = new Set(['completed', 'failed', 'canceled', 'expired']) - function tableNameFrom(fileName: string): string { const stem = fileName.replace(/\.[^.]+$/, '') const cleaned = stem.replace(/[^A-Za-z0-9]+/g, '_').replace(/^_+|_+$/g, '') @@ -91,32 +86,6 @@ function progressLine(job: TableImport): string { return `${job.status}… ${job.rowsProcessed} rows${suffix}` } -async function watchImport( - client: OperationClient<'getTableImport'>, - workspaceId: string, - job: TableImport -): Promise { - let current = job - let reported: string | null = null - - while (!IMPORT_SETTLED.has(current.status)) { - await sleep(IMPORT_POLL_MS) - const next = await client.request<{ data: TableImport }>('getTableImport', { - params: { importId: current.id }, - query: { workspaceId }, - }) - current = next.data - const line = progressLine(current) - if (hasProgressTerminal() && line !== reported) { - reported = line - writeStderr(`\r${styles().dim(line)}\u001b[K`) - } - } - - if (hasProgressTerminal() && reported !== null) writeStderr('\r\u001b[K') - return current -} - function validateTargetOptions(options: ImportOptions): boolean { const intoExisting = Boolean(options.tableId) const misplaced = intoExisting @@ -277,7 +246,17 @@ export function attachTableImport(tables: Command): void { return } - const finished = await watchImport(client, workspaceId, job) + const finished = await watchImport( + job, + async (current) => + ( + await client.request<{ data: TableImport }>('getTableImport', { + params: { importId: current.id }, + query: { workspaceId }, + }) + ).data, + progressLine + ) if (finished.status !== 'completed') { throw new SimApiError( `Import ${finished.status}${finished.error ? `: ${finished.error}` : ''}`, diff --git a/packages/sim-cli/src/contract/commands.ts b/packages/sim-cli/src/contract/commands.ts index 2fa3aa993cb..2ec1d809dd8 100644 --- a/packages/sim-cli/src/contract/commands.ts +++ b/packages/sim-cli/src/contract/commands.ts @@ -2281,6 +2281,21 @@ export const CLI_CONTRACT: CliContract = { completeKnowledgeDocumentUpload: { hidden: true }, abortKnowledgeDocumentUpload: { hidden: true }, + // The handshake behind `sim knowledge import`, hidden for the reason the + // table import steps are; `get` and `cancel` stay without the upload token, + // which only addresses an import the command never leaves mid-transfer. + createKnowledgeImport: { hidden: true }, + createKnowledgeImportPartUrls: { hidden: true }, + completeKnowledgeImport: { hidden: true }, + getKnowledgeImport: { flags: TRANSFER_TOKEN_OMITTED }, + cancelKnowledgeImport: { + command: 'knowledge imports cancel', + flags: TRANSFER_TOKEN_OMITTED, + describe: 'Stop a running import', + // Not `confirm`-gated: the documents already imported stay in the new + // knowledge base, and nothing that existed before the import is touched. + }, + // Steps of a transfer, not commands // Uploading is a presigned multipart handshake: create the upload, ask for // part URLs in batches, PUT each part to storage, then complete with the diff --git a/packages/sim-cli/src/generated/v2-api.ts b/packages/sim-cli/src/generated/v2-api.ts index 927cf0e5343..09e3a5f7992 100644 --- a/packages/sim-cli/src/generated/v2-api.ts +++ b/packages/sim-cli/src/generated/v2-api.ts @@ -967,6 +967,44 @@ export type BulkUpdateTableRowsResponse = { data: BulkUpdateTableRowsResponseRef0 } +/** `DELETE /api/v2/knowledge/imports/[importId]` */ +export type CancelKnowledgeImportParams = { + importId: string +} + +export type CancelKnowledgeImportQuery = { + workspaceId: string +} + +export type CancelKnowledgeImportHeaders = { + 'upload-token'?: string +} + +type CancelKnowledgeImportResponseRef0 = { + filename: string + message: string +} + +type CancelKnowledgeImportResponseRef1 = { + id: string + workspaceId: string + status: 'uploading' | 'processing' | 'completed' | 'failed' | 'canceled' | 'expired' + knowledgeBaseId: string | null + documentsTotal: number + documentsImported: number + documentsFailed: number + vectorsReused: boolean + failures: Array + error: string | null + createdAt: string + updatedAt: string + completedAt: string | null +} + +export type CancelKnowledgeImportResponse = { + data: CancelKnowledgeImportResponseRef1 +} + /** `POST /api/v2/organizations/[organizationId]/access-requests/[requestId]/cancel` */ export type CancelOrganizationAccessRequestParams = { organizationId: string @@ -1703,6 +1741,44 @@ export type CompleteKnowledgeDocumentUploadResponse = { data: CompleteKnowledgeDocumentUploadResponseRef1 } +/** `POST /api/v2/knowledge/imports/[importId]/complete` */ +export type CompleteKnowledgeImportParams = { + importId: string +} + +export type CompleteKnowledgeImportQuery = { + workspaceId: string +} + +export type CompleteKnowledgeImportHeaders = { + 'upload-token': string +} + +type CompleteKnowledgeImportResponseRef0 = { + filename: string + message: string +} + +type CompleteKnowledgeImportResponseRef1 = { + id: string + workspaceId: string + status: 'uploading' | 'processing' | 'completed' | 'failed' | 'canceled' | 'expired' + knowledgeBaseId: string | null + documentsTotal: number + documentsImported: number + documentsFailed: number + vectorsReused: boolean + failures: Array + error: string | null + createdAt: string + updatedAt: string + completedAt: string | null +} + +export type CompleteKnowledgeImportResponse = { + data: CompleteKnowledgeImportResponseRef1 +} + /** `POST /api/v2/projects/[projectId]/files/uploads/[uploadId]/complete` */ export type CompleteProjectFileUploadParams = { projectId: string @@ -2463,6 +2539,98 @@ export type CreateKnowledgeFolderResponse = { data: CreateKnowledgeFolderResponseRef0 } +/** `POST /api/v2/knowledge/imports` */ +export type CreateKnowledgeImportQuery = Record + +type CreateKnowledgeImportBodyRef0 = { + type: 'upload' + name: string + contentType: string + size: number +} + +export type CreateKnowledgeImportBody = { + workspaceId: string + name?: string + source: CreateKnowledgeImportBodyRef0 +} + +type CreateKnowledgeImportResponseRef0 = { + filename: string + message: string +} + +type CreateKnowledgeImportResponseRef1 = { + id: string + workspaceId: string + status: 'uploading' | 'processing' | 'completed' | 'failed' | 'canceled' | 'expired' + knowledgeBaseId: string | null + documentsTotal: number + documentsImported: number + documentsFailed: number + vectorsReused: boolean + failures: Array + error: string | null + createdAt: string + updatedAt: string + completedAt: string | null +} + +type CreateKnowledgeImportResponseRef2 = { + method: 'put' + url: string + headers: Record + expiresAt: string +} + +type CreateKnowledgeImportResponseRef3 = { + method: 'multipart' + partSize: number + partCount: number +} + +type CreateKnowledgeImportResponseRef4 = { + session: CreateKnowledgeImportResponseRef1 + uploadToken: string + transfer: CreateKnowledgeImportResponseRef2 | CreateKnowledgeImportResponseRef3 +} + +export type CreateKnowledgeImportResponse = { + data: CreateKnowledgeImportResponseRef4 +} + +/** `POST /api/v2/knowledge/imports/[importId]/parts` */ +export type CreateKnowledgeImportPartUrlsParams = { + importId: string +} + +export type CreateKnowledgeImportPartUrlsQuery = { + workspaceId: string +} + +export type CreateKnowledgeImportPartUrlsBody = { + partNumbers: Array +} + +export type CreateKnowledgeImportPartUrlsHeaders = { + 'upload-token': string +} + +type CreateKnowledgeImportPartUrlsResponseRef0 = { + partNumber: number + url: string + headers: Record + expiresAt: string +} + +type CreateKnowledgeImportPartUrlsResponseRef1 = { + parts: Array +} + +export type CreateKnowledgeImportPartUrlsResponse = { + data: CreateKnowledgeImportPartUrlsResponseRef1 +} + /** `POST /api/v2/knowledge/[knowledgeBaseId]/tags` */ export type CreateKnowledgeTagParams = { knowledgeBaseId: string @@ -6198,6 +6366,44 @@ export type GetKnowledgeDocumentResponse = { data: GetKnowledgeDocumentResponseRef0 } +/** `GET /api/v2/knowledge/imports/[importId]` */ +export type GetKnowledgeImportParams = { + importId: string +} + +export type GetKnowledgeImportQuery = { + workspaceId: string +} + +export type GetKnowledgeImportHeaders = { + 'upload-token'?: string +} + +type GetKnowledgeImportResponseRef0 = { + filename: string + message: string +} + +type GetKnowledgeImportResponseRef1 = { + id: string + workspaceId: string + status: 'uploading' | 'processing' | 'completed' | 'failed' | 'canceled' | 'expired' + knowledgeBaseId: string | null + documentsTotal: number + documentsImported: number + documentsFailed: number + vectorsReused: boolean + failures: Array + error: string | null + createdAt: string + updatedAt: string + completedAt: string | null +} + +export type GetKnowledgeImportResponse = { + data: GetKnowledgeImportResponseRef1 +} + /** `GET /api/v2/logs/[runId]` */ export type GetLogParams = { runId: string @@ -16124,6 +16330,24 @@ export const V2_OPERATIONS = { }, }, }, + cancelKnowledgeImport: { + method: 'DELETE', + path: '/api/v2/knowledge/imports/[importId]', + pathParams: ['importId'] as const, + pathParamDocs: { importId: 'Unique knowledge-base import identifier.' }, + responseMode: 'json', + summary: 'Cancel knowledge base import', + query: { + workspaceId: { kind: 'string', required: true, describe: 'Workspace that owns the import.' }, + }, + headers: { + 'upload-token': { + kind: 'string', + describe: + 'Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.', + }, + }, + }, cancelOrganizationAccessRequest: { method: 'POST', path: '/api/v2/organizations/[organizationId]/access-requests/[requestId]/cancel', @@ -16326,6 +16550,24 @@ export const V2_OPERATIONS = { }, }, }, + completeKnowledgeImport: { + method: 'POST', + path: '/api/v2/knowledge/imports/[importId]/complete', + pathParams: ['importId'] as const, + pathParamDocs: { importId: 'Unique knowledge-base import identifier.' }, + responseMode: 'json', + summary: 'Complete knowledge base import upload', + query: { + workspaceId: { kind: 'string', required: true, describe: 'Workspace that owns the import.' }, + }, + headers: { + 'upload-token': { + kind: 'string', + required: true, + describe: 'Signed upload control token returned when the upload session was created.', + }, + }, + }, completeProjectFileUpload: { method: 'POST', path: '/api/v2/projects/[projectId]/files/uploads/[uploadId]/complete', @@ -16702,6 +16944,54 @@ export const V2_OPERATIONS = { path: { kind: 'string', required: true, describe: 'Path of the folder to create.' }, }, }, + createKnowledgeImport: { + method: 'POST', + path: '/api/v2/knowledge/imports', + pathParams: [] as const, + responseMode: 'json', + summary: 'Create knowledge base import', + body: { + workspaceId: { + kind: 'string', + required: true, + describe: 'Workspace in which to create the knowledge base.', + }, + name: { + kind: 'string', + describe: "Name for the new knowledge base; defaults to the bundle's own name.", + }, + source: { + kind: 'object', + required: true, + describe: 'Bundle archive uploaded through signed transfer instructions.', + }, + }, + }, + createKnowledgeImportPartUrls: { + method: 'POST', + path: '/api/v2/knowledge/imports/[importId]/parts', + pathParams: ['importId'] as const, + pathParamDocs: { importId: 'Unique knowledge-base import identifier.' }, + responseMode: 'json', + summary: 'Create knowledge base import part URLs', + query: { + workspaceId: { kind: 'string', required: true, describe: 'Workspace that owns the import.' }, + }, + body: { + partNumbers: { + kind: 'array', + required: true, + describe: 'Multipart part numbers for which signed URLs should be created.', + }, + }, + headers: { + 'upload-token': { + kind: 'string', + required: true, + describe: 'Signed upload control token returned when the upload session was created.', + }, + }, + }, createKnowledgeTag: { method: 'POST', path: '/api/v2/knowledge/[knowledgeBaseId]/tags', @@ -18495,6 +18785,24 @@ export const V2_OPERATIONS = { }, }, }, + getKnowledgeImport: { + method: 'GET', + path: '/api/v2/knowledge/imports/[importId]', + pathParams: ['importId'] as const, + pathParamDocs: { importId: 'Unique knowledge-base import identifier.' }, + responseMode: 'json', + summary: 'Get knowledge base import', + query: { + workspaceId: { kind: 'string', required: true, describe: 'Workspace that owns the import.' }, + }, + headers: { + 'upload-token': { + kind: 'string', + describe: + 'Signed upload control token returned when the import was created; required to read or cancel the import before its upload completes.', + }, + }, + }, getLog: { method: 'GET', path: '/api/v2/logs/[runId]', diff --git a/packages/sim-cli/src/http/client.test.ts b/packages/sim-cli/src/http/client.test.ts index 63146764eb6..73d59220211 100644 --- a/packages/sim-cli/src/http/client.test.ts +++ b/packages/sim-cli/src/http/client.test.ts @@ -470,6 +470,7 @@ describe('destructive operations are gated', () => { 'chat', 'completeFileUpload', 'completeKnowledgeDocumentUpload', + 'completeKnowledgeImport', 'completeTableImport', 'createCredentialConnection', 'createCustomTool', @@ -483,6 +484,8 @@ describe('destructive operations are gated', () => { 'createKnowledgeDocumentUpload', 'createKnowledgeDocumentUploadPartUrls', 'createKnowledgeFolder', + 'createKnowledgeImport', + 'createKnowledgeImportPartUrls', 'createKnowledgeTag', 'createMcpServer', 'createSandbox', diff --git a/packages/sim-cli/src/program.ts b/packages/sim-cli/src/program.ts index fda98e468dc..7cca9a83a54 100644 --- a/packages/sim-cli/src/program.ts +++ b/packages/sim-cli/src/program.ts @@ -43,6 +43,7 @@ Examples: $ sim workflows export 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 > wf.json $ sim workflows import --workflow @wf.json $ sim knowledge export 4c1b7f60-2d55-4a3e-9c18-70b6ea2f9d31 -o ./kb.simkb.zip + $ sim knowledge import ./kb.simkb.zip --name "Docs (copy)" $ sim whoami --profile dev ` diff --git a/packages/sim-cli/src/transfer/import-watch.ts b/packages/sim-cli/src/transfer/import-watch.ts new file mode 100644 index 00000000000..19305e6c66d --- /dev/null +++ b/packages/sim-cli/src/transfer/import-watch.ts @@ -0,0 +1,30 @@ +import { setTimeout as sleep } from 'node:timers/promises' +import { writeStderr } from '#sim-cli/output/io' +import { hasProgressTerminal, styles } from '#sim-cli/output/presentation' + +const IMPORT_POLL_MS = 1500 +const IMPORT_SETTLED = new Set(['completed', 'failed', 'canceled', 'expired']) + +/** + * Polls an import until it settles, redrawing one progress line on stderr when + * it is a terminal and clearing it once the import is done. + */ +export async function watchImport( + job: T, + fetchNext: (current: T) => Promise, + progressLine: (current: T) => string +): Promise { + let current = job + let reported: string | null = null + while (!IMPORT_SETTLED.has(current.status)) { + await sleep(IMPORT_POLL_MS) + current = await fetchNext(current) + const line = progressLine(current) + if (hasProgressTerminal() && line !== reported) { + reported = line + writeStderr(`\r${styles().dim(line)}\u001b[K`) + } + } + if (hasProgressTerminal() && reported !== null) writeStderr('\r\u001b[K') + return current +} diff --git a/packages/testing/src/mocks/audit.mock.ts b/packages/testing/src/mocks/audit.mock.ts index feea8829449..1d7903d778b 100644 --- a/packages/testing/src/mocks/audit.mock.ts +++ b/packages/testing/src/mocks/audit.mock.ts @@ -102,6 +102,7 @@ const AuditAction = { KNOWLEDGE_BASE_DELETED: 'knowledge_base.deleted', KNOWLEDGE_BASE_RESTORED: 'knowledge_base.restored', KNOWLEDGE_BASE_EXPORTED: 'knowledge_base.exported', + KNOWLEDGE_BASE_IMPORT_STARTED: 'knowledge_base.import_started', MCP_SERVER_ADDED: 'mcp_server.added', MCP_SERVER_UPDATED: 'mcp_server.updated', MCP_SERVER_REMOVED: 'mcp_server.removed', diff --git a/packages/testing/src/mocks/schema-tables.generated.ts b/packages/testing/src/mocks/schema-tables.generated.ts index 7a785a3380d..c5921c973d1 100644 --- a/packages/testing/src/mocks/schema-tables.generated.ts +++ b/packages/testing/src/mocks/schema-tables.generated.ts @@ -915,6 +915,24 @@ export const GENERATED_SCHEMA_TABLES = { 'createdAt', 'updatedAt', ], + knowledgeBaseImport: [ + 'id', + 'workspaceId', + 'userId', + 'sourceKey', + 'knowledgeBaseId', + 'status', + 'documentsTotal', + 'documentsImported', + 'documentsFailed', + 'vectorsReused', + 'failures', + 'error', + 'createdAt', + 'startedAt', + 'updatedAt', + 'completedAt', + ], document: [ 'id', 'knowledgeBaseId', @@ -2188,6 +2206,7 @@ export const GENERATED_SCHEMA_ENUMS = { 'workspace_file', 'project_file', 'table_import', + 'knowledge_import', 'knowledge_document', 'profile_picture', 'workspace_logo', diff --git a/scripts/check-spec-example-ids.ts b/scripts/check-spec-example-ids.ts index 08faa2f9e61..94ed551912b 100644 --- a/scripts/check-spec-example-ids.ts +++ b/scripts/check-spec-example-ids.ts @@ -39,6 +39,7 @@ const APPROVED: Record = { '0f7c1a2e-9b3d-4c58-8a21-6d4e5f7a9b01': 'run id in the RUN_ID_CONFLICT error example', '3b1f7c92-8d4e-4a6b-9c0d-5e2f8a714b36': 'the shared workflow id placeholder', '4c1f9e77-2b3a-4f8d-9e10-6a2c8d4b1e05': 'KNOWLEDGE_CHUNK_ID', + '5e8a2c4f-1d7b-4396-a0e3-8f6b2d9c1a47': 'KNOWLEDGE_IMPORT_ID', '7c9e6679-7425-40de-944b-e07fc1f90ae7': "KNOWLEDGE_BASE_ID, Wikipedia's canonical example UUID", '9d3b7f10-2c8e-4a56-b0f4-6e1a8c5d2b97': 'pausedExecutionId on the paused-execution example', '9f4c2a10-3b7e-4d58-8f6a-2c1d0e5b7a94': 'second workspace id, where one example needs two', diff --git a/scripts/check-unused-exports.baseline.json b/scripts/check-unused-exports.baseline.json index 819df44b2ea..bd66595634f 100644 --- a/scripts/check-unused-exports.baseline.json +++ b/scripts/check-unused-exports.baseline.json @@ -4623,7 +4623,6 @@ "apps/sim/lib/knowledge/transfer/bundle.ts#KnowledgeBundleTagValues", "apps/sim/lib/knowledge/transfer/bundle.ts#chunksEntryPath", "apps/sim/lib/knowledge/transfer/bundle.ts#fileEntryPath", - "apps/sim/lib/knowledge/transfer/bundle.ts#knowledgeBundleChunkLineSchema", "apps/sim/lib/knowledge/transfer/bundle.ts#knowledgeBundleDocumentSchema", "apps/sim/lib/knowledge/transfer/bundle.ts#knowledgeBundleTagSchema", "apps/sim/lib/knowledge/types.ts#MemberSyncStatus", @@ -5054,7 +5053,6 @@ "apps/sim/lib/uploads/upload-session/service.ts#UPLOAD_SESSION_LOCAL_PUT_MAX_BYTES=UPLOAD_SESSION_PART_SIZE", "apps/sim/lib/uploads/upload-session/service.ts#UPLOAD_SESSION_MAX_PART_URLS", "apps/sim/lib/uploads/upload-session/service.ts#UPLOAD_SESSION_TTL_MS", - "apps/sim/lib/uploads/upload-session/service.ts#UploadSessionStatus", "apps/sim/lib/uploads/upload-session/service.ts#UploadTransferMethod", "apps/sim/lib/uploads/utils/file.ts#isSupportedFileType", "apps/sim/lib/uploads/utils/validation.ts#ACCEPTED_FILE_EXTENSIONS", diff --git a/scripts/generate-cli-docs.ts b/scripts/generate-cli-docs.ts index 627175aa1a9..0eab47add57 100644 --- a/scripts/generate-cli-docs.ts +++ b/scripts/generate-cli-docs.ts @@ -281,7 +281,8 @@ const GROUP_SECTIONS: Record = { title: 'Knowledge bases', prefixes: ['list', 'get', 'create', 'update', 'mv', 'delete', 'restore'], }, - { title: 'Search and export', prefixes: ['search', 'export'] }, + { title: 'Search', prefixes: ['search'] }, + { title: 'Export and import', prefixes: ['export', 'import', 'imports'] }, { title: 'Documents', prefixes: ['documents', 'from-workspace-files'] }, { title: 'Chunks', prefixes: ['chunks'] }, { title: 'Tags', prefixes: ['tags'] },