From 178e15c82e77bd30e5adef58d47817cf028eb46e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 14 Oct 2026 09:11:58 -0700 Subject: [PATCH 1/2] improvement(api): declare OAuth scopes in OpenAPI, JSON 404s for unknown API paths, and root MCP resource metadata --- apps/docs/lib/openapi.ts | 2 +- apps/docs/openapi-v2-billing.json | 34 +- apps/docs/openapi-v2-files-audit.json | 298 +++++- apps/docs/openapi-v2-knowledge.json | 378 +++++++- apps/docs/openapi-v2-logs.json | 42 +- apps/docs/openapi-v2-resources.json | 866 +++++++++++++++++- apps/docs/openapi-v2-tables.json | 442 ++++++++- apps/docs/openapi-v2-workflows.json | 484 +++++++++- apps/sim/app/api/[[...segments]]/route.ts | 20 + .../lib/api/contracts/v2/openapi/shared.ts | 26 +- apps/sim/lib/api/mcp/host-routing.test.ts | 1 + apps/sim/lib/api/mcp/host-routing.ts | 16 +- apps/sim/lib/api/openapi/types.ts | 13 + apps/sim/scripts/test-mcp-host-e2e.ts | 52 +- scripts/check-api-validation-contracts.ts | 2 + scripts/openapi/documents.test.ts | 6 +- scripts/openapi/generator.test.ts | 14 +- scripts/openapi/generator.ts | 40 +- 18 files changed, 2683 insertions(+), 53 deletions(-) create mode 100644 apps/sim/app/api/[[...segments]]/route.ts diff --git a/apps/docs/lib/openapi.ts b/apps/docs/lib/openapi.ts index 18dc8c198d2..e4c33c983db 100644 --- a/apps/docs/lib/openapi.ts +++ b/apps/docs/lib/openapi.ts @@ -173,7 +173,7 @@ function resolveAuthHeaders( headers[scheme.name] = AUTH_SAMPLE_VALUE continue } - if (scheme.type === 'http' && scheme.scheme === 'bearer') { + if (scheme.type === 'oauth2' || (scheme.type === 'http' && scheme.scheme === 'bearer')) { headers.Authorization = `Bearer ${AUTH_SAMPLE_VALUE}` continue } diff --git a/apps/docs/openapi-v2-billing.json b/apps/docs/openapi-v2-billing.json index 7869df5c9bf..c59871327dc 100644 --- a/apps/docs/openapi-v2-billing.json +++ b/apps/docs/openapi-v2-billing.json @@ -43,6 +43,14 @@ "x-sim-operation": "billing.status.read", "x-oauth-scope": "api:read", "tags": ["Billing"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -111,6 +119,14 @@ "x-sim-operation": "billing.logs.list", "x-oauth-scope": "api:read", "tags": ["Billing"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "source", @@ -263,10 +279,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-files-audit.json b/apps/docs/openapi-v2-files-audit.json index 9e96b13c639..c456d1bd379 100644 --- a/apps/docs/openapi-v2-files-audit.json +++ b/apps/docs/openapi-v2-files-audit.json @@ -47,6 +47,14 @@ "x-sim-operation": "files.list", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -220,6 +228,14 @@ "x-sim-operation": "files.create", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Inline content and placement for a new workspace file.", @@ -294,6 +310,14 @@ "x-sim-operation": "files.upload.create", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "File metadata required to create an upload session.", @@ -365,6 +389,14 @@ "x-sim-operation": "files.upload.read", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "uploadId", @@ -453,6 +485,14 @@ "x-sim-operation": "files.upload.cancel", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "uploadId", @@ -546,6 +586,14 @@ "x-sim-operation": "files.upload.parts", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "uploadId", @@ -656,6 +704,14 @@ "x-sim-operation": "files.upload.complete", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "uploadId", @@ -749,6 +805,14 @@ "x-sim-operation": "files.read_content", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -871,6 +935,14 @@ "x-sim-operation": "files.versions.list", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -1000,6 +1072,14 @@ "x-sim-operation": "files.versions.read", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -1091,6 +1171,14 @@ "x-sim-operation": "files.versions.delete", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -1187,6 +1275,14 @@ "x-sim-operation": "files.versions.read_content", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -1322,6 +1418,14 @@ "x-sim-operation": "files.versions.download", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -1431,6 +1535,14 @@ "x-sim-operation": "files.versions.revert", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -1532,6 +1644,14 @@ "x-sim-operation": "files.download", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -1630,6 +1750,14 @@ "x-sim-operation": "files.extract_archive", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -1719,6 +1847,14 @@ "x-sim-operation": "files.download", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -1814,6 +1950,14 @@ "x-sim-operation": "files.delete", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -1893,6 +2037,14 @@ "x-sim-operation": "files.rename", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -1982,6 +2134,14 @@ "x-sim-operation": "files.restore", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -2071,6 +2231,14 @@ "x-sim-operation": "files.read_metadata", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -2164,6 +2332,14 @@ "x-sim-operation": "audit_logs.list", "x-oauth-scope": "api:read", "tags": ["Audit Logs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "action", @@ -2340,6 +2516,14 @@ "x-sim-operation": "audit_logs.read_detail", "x-oauth-scope": "api:read", "tags": ["Audit Logs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "auditLogId", @@ -2418,6 +2602,14 @@ "x-sim-operation": "files.move", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Files and destination selected for a bulk move.", @@ -2492,6 +2684,14 @@ "x-sim-operation": "files.share.read", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "fileId", @@ -2571,6 +2771,14 @@ "x-sim-operation": "files.share.update", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -2657,6 +2865,14 @@ "x-sim-operation": "files.update_content", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -2747,6 +2963,14 @@ "x-sim-operation": "files.update_content", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "fileId", @@ -2836,6 +3060,14 @@ "x-sim-operation": "files.search_content", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2978,6 +3210,14 @@ "x-sim-operation": "files.delete", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace and files selected for deletion.", @@ -3049,6 +3289,14 @@ "x-sim-operation": "files.folders.list", "x-oauth-scope": "api:read", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3209,6 +3457,14 @@ "x-sim-operation": "files.folders.create", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace and canonical path for a new folder.", @@ -3281,6 +3537,14 @@ "x-sim-operation": "files.folders.update", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Current and destination canonical paths for a folder.", @@ -3353,6 +3617,14 @@ "x-sim-operation": "files.folders.delete", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3459,6 +3731,14 @@ "x-sim-operation": "files.folders.restore", "x-oauth-scope": "api:write", "tags": ["Files"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope and archived folder path.", @@ -3535,10 +3815,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-knowledge.json b/apps/docs/openapi-v2-knowledge.json index d54d703a883..0ec86ec222b 100644 --- a/apps/docs/openapi-v2-knowledge.json +++ b/apps/docs/openapi-v2-knowledge.json @@ -43,6 +43,14 @@ "x-sim-operation": "knowledge.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -194,6 +202,14 @@ "x-sim-operation": "knowledge.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace, name, description, chunking configuration, and folder placement.", @@ -268,6 +284,14 @@ "x-sim-operation": "knowledge.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -347,6 +371,14 @@ "x-sim-operation": "knowledge.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -432,6 +464,14 @@ "x-sim-operation": "knowledge.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -510,6 +550,14 @@ "x-sim-operation": "knowledge.export", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -609,6 +657,14 @@ "x-sim-operation": "knowledge.connectors.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -734,6 +790,14 @@ "x-sim-operation": "knowledge.connectors.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -821,6 +885,14 @@ "x-sim-operation": "knowledge.connectors.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "connectorId", @@ -909,6 +981,14 @@ "x-sim-operation": "knowledge.connectors.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "connectorId", @@ -1005,6 +1085,14 @@ "x-sim-operation": "knowledge.connectors.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "connectorId", @@ -1105,6 +1193,14 @@ "x-sim-operation": "knowledge.connectors.sync", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "connectorId", @@ -1203,6 +1299,14 @@ "x-sim-operation": "knowledge.connectors.documents.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "connectorId", @@ -1325,6 +1429,14 @@ "x-sim-operation": "knowledge.connectors.documents.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "connectorId", @@ -1420,6 +1532,14 @@ "x-sim-operation": "knowledge.search", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "requestBody": { "required": true, "description": "Knowledge bases, query, result limit, retrieval mode, and optional tag filters.", @@ -1497,6 +1617,14 @@ "x-sim-operation": "knowledge.tags.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -1573,6 +1701,14 @@ "x-sim-operation": "knowledge.tags.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -1658,6 +1794,14 @@ "x-sim-operation": "knowledge.tags.bulk_save", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -1740,6 +1884,14 @@ "x-sim-operation": "knowledge.tags.cleanup", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -1829,6 +1981,14 @@ "x-sim-operation": "knowledge.documents.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -1998,6 +2158,14 @@ "x-sim-operation": "knowledge.documents.bulk", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2080,6 +2248,14 @@ "x-sim-operation": "knowledge.documents.upload", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2179,6 +2355,14 @@ "x-sim-operation": "knowledge.documents.upload.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2266,6 +2450,14 @@ "x-sim-operation": "knowledge.documents.upload.cancel", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2370,6 +2562,14 @@ "x-sim-operation": "knowledge.documents.upload.parts", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2491,6 +2691,14 @@ "x-sim-operation": "knowledge.documents.upload.complete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -2595,6 +2803,14 @@ "x-sim-operation": "knowledge.documents.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "documentId", @@ -2682,6 +2898,14 @@ "x-sim-operation": "knowledge.documents.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -2775,6 +2999,14 @@ "x-sim-operation": "knowledge.documents.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -2864,6 +3096,14 @@ "x-sim-operation": "knowledge.folders.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2979,6 +3219,14 @@ "x-sim-operation": "knowledge.folders.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace and canonical path for a new knowledge-base folder.", @@ -3051,6 +3299,14 @@ "x-sim-operation": "knowledge.folders.relocate", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Current and destination canonical paths for a knowledge-base folder.", @@ -3123,6 +3379,14 @@ "x-sim-operation": "knowledge.folders.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3232,6 +3496,14 @@ "x-sim-operation": "knowledge.restore", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -3319,6 +3591,14 @@ "x-sim-operation": "knowledge.documents.add_workspace_files", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -3406,6 +3686,14 @@ "x-sim-operation": "knowledge.chunks.list", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "documentId", @@ -3569,6 +3857,14 @@ "x-sim-operation": "knowledge.chunks.create", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -3662,6 +3958,14 @@ "x-sim-operation": "knowledge.chunks.bulk", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -3757,6 +4061,14 @@ "x-sim-operation": "knowledge.chunks.read", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "documentId", @@ -3859,6 +4171,14 @@ "x-sim-operation": "knowledge.chunks.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -3966,6 +4286,14 @@ "x-sim-operation": "knowledge.chunks.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "documentId", @@ -4070,6 +4398,14 @@ "x-sim-operation": "knowledge.tags.update", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tagId", @@ -4166,6 +4502,14 @@ "x-sim-operation": "knowledge.tags.delete", "x-oauth-scope": "api:write", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tagId", @@ -4259,6 +4603,14 @@ "x-sim-operation": "knowledge.tags.read_next_slot", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -4350,6 +4702,14 @@ "x-sim-operation": "knowledge.tags.read_usage", "x-oauth-scope": "api:read", "tags": ["Knowledge Bases"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "knowledgeBaseId", @@ -4431,10 +4791,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-logs.json b/apps/docs/openapi-v2-logs.json index 2279e818cfc..99ad513ae4f 100644 --- a/apps/docs/openapi-v2-logs.json +++ b/apps/docs/openapi-v2-logs.json @@ -43,6 +43,14 @@ "x-sim-operation": "logs.list", "x-oauth-scope": "api:read", "tags": ["Logs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -370,6 +378,14 @@ "x-sim-operation": "logs.read_detail", "x-oauth-scope": "api:read", "tags": ["Logs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "runId", @@ -452,6 +468,14 @@ "x-sim-operation": "logs.read_stats", "x-oauth-scope": "api:read", "tags": ["Logs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -638,10 +662,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-resources.json b/apps/docs/openapi-v2-resources.json index dc8999e8f76..8d72b00ef02 100644 --- a/apps/docs/openapi-v2-resources.json +++ b/apps/docs/openapi-v2-resources.json @@ -87,6 +87,14 @@ "x-sim-operation": "workspaces.list_public", "x-oauth-scope": "api:read", "tags": ["Workspaces"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "sortBy", @@ -191,6 +199,14 @@ "x-sim-operation": "workspaces.read_public_detail", "x-oauth-scope": "api:read", "tags": ["Workspaces"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -259,6 +275,14 @@ "x-sim-operation": "workspaces.members.list_public", "x-oauth-scope": "api:read", "tags": ["Workspaces"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -351,6 +375,14 @@ "x-sim-operation": "mcp_servers.list", "x-oauth-scope": "api:read", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -477,6 +509,14 @@ "x-sim-operation": "mcp_servers.create", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Configuration for a new MCP server.", @@ -551,6 +591,14 @@ "x-sim-operation": "mcp_servers.read", "x-oauth-scope": "api:read", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "mcpServerId", @@ -628,6 +676,14 @@ "x-sim-operation": "mcp_servers.update", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "mcpServerId", @@ -710,6 +766,14 @@ "x-sim-operation": "mcp_servers.delete", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "mcpServerId", @@ -789,6 +853,14 @@ "x-sim-operation": "mcp_servers.tools.discover", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "mcpServerId", @@ -881,6 +953,14 @@ "x-sim-operation": "skills.list", "x-oauth-scope": "api:read", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -1007,6 +1087,14 @@ "x-sim-operation": "skills.create", "x-oauth-scope": "api:write", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Definition of a new skill.", @@ -1081,6 +1169,14 @@ "x-sim-operation": "skills.read", "x-oauth-scope": "api:read", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "skillId", @@ -1158,6 +1254,14 @@ "x-sim-operation": "skills.update", "x-oauth-scope": "api:write", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "skillId", @@ -1243,6 +1347,14 @@ "x-sim-operation": "skills.delete", "x-oauth-scope": "api:write", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "skillId", @@ -1322,6 +1434,14 @@ "x-sim-operation": "skills.editors.list", "x-oauth-scope": "api:read", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "skillId", @@ -1447,6 +1567,14 @@ "x-sim-operation": "skills.editors.grant", "x-oauth-scope": "api:write", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "skillId", @@ -1550,6 +1678,14 @@ "x-sim-operation": "skills.editors.revoke", "x-oauth-scope": "api:write", "tags": ["Skills"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "skillId", @@ -1641,6 +1777,14 @@ "x-sim-operation": "custom_tools.list", "x-oauth-scope": "api:read", "tags": ["Custom Tools"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -1767,6 +1911,14 @@ "x-sim-operation": "custom_tools.create", "x-oauth-scope": "api:write", "tags": ["Custom Tools"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Definition and implementation of a new custom tool.", @@ -1841,6 +1993,14 @@ "x-sim-operation": "custom_tools.read", "x-oauth-scope": "api:read", "tags": ["Custom Tools"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "customToolId", @@ -1918,6 +2078,14 @@ "x-sim-operation": "custom_tools.update", "x-oauth-scope": "api:write", "tags": ["Custom Tools"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "customToolId", @@ -2003,6 +2171,14 @@ "x-sim-operation": "custom_tools.delete", "x-oauth-scope": "api:write", "tags": ["Custom Tools"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "customToolId", @@ -2082,6 +2258,14 @@ "x-sim-operation": "sandboxes.list", "x-oauth-scope": "api:read", "tags": ["Sandboxes"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2208,6 +2392,14 @@ "x-sim-operation": "sandboxes.create", "x-oauth-scope": "api:write", "tags": ["Sandboxes"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Name, language, and dependency set of a new sandbox.", @@ -2282,6 +2474,14 @@ "x-sim-operation": "sandboxes.read", "x-oauth-scope": "api:read", "tags": ["Sandboxes"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "sandboxId", @@ -2359,6 +2559,14 @@ "x-sim-operation": "sandboxes.update", "x-oauth-scope": "api:write", "tags": ["Sandboxes"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "sandboxId", @@ -2444,6 +2652,14 @@ "x-sim-operation": "sandboxes.delete", "x-oauth-scope": "api:write", "tags": ["Sandboxes"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "sandboxId", @@ -2523,6 +2739,14 @@ "x-sim-operation": "credentials.connections.list", "x-oauth-scope": "api:read", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2671,6 +2895,14 @@ "x-sim-operation": "credentials.service_accounts.create", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Provider identifier, optional display metadata, and a write-only JSON object string containing the fields declared by provider discovery.", @@ -2766,6 +2998,14 @@ "x-sim-operation": "credentials.providers.list", "x-oauth-scope": "api:read", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2846,6 +3086,14 @@ "x-sim-operation": "credentials.connections.create", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "For a new connection, provide providerId and displayName. For a reconnect, provide only credentialId; the existing display name is preserved.", @@ -2920,6 +3168,14 @@ "x-sim-operation": "credentials.delete", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "credentialId", @@ -2998,6 +3254,14 @@ "x-sim-operation": "credentials.update", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "credentialId", @@ -3098,6 +3362,14 @@ "x-sim-operation": "secrets.list", "x-oauth-scope": "api:read", "tags": ["Secrets"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3237,6 +3509,14 @@ "x-sim-operation": "secrets.set", "x-oauth-scope": "api:write", "tags": ["Secrets"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "name", @@ -3342,6 +3622,14 @@ "x-sim-operation": "secrets.delete", "x-oauth-scope": "api:write", "tags": ["Secrets"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "name", @@ -3434,6 +3722,14 @@ "x-sim-operation": "meta.capabilities.read", "x-oauth-scope": "api:read", "tags": ["Meta"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "responses": { "200": { "description": "Availability and lifecycle facts about the calling credential.", @@ -3482,6 +3778,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.list", "x-oauth-scope": "api:read", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3596,6 +3900,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.create_server", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "A new workspace-published MCP server and the workflows it exposes.", @@ -3670,6 +3982,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.read_server", "x-oauth-scope": "api:read", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "serverId", @@ -3735,6 +4055,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.update_server", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "serverId", @@ -3820,6 +4148,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.delete_server", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "serverId", @@ -3890,6 +4226,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.list_tools", "x-oauth-scope": "api:read", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "serverId", @@ -3955,6 +4299,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.deploy_tool", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "serverId", @@ -4042,6 +4394,14 @@ "x-sim-operation": "mcp_servers.workflow_deployments.undeploy_tool", "x-oauth-scope": "api:write", "tags": ["MCP Servers"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "serverId", @@ -4123,6 +4483,14 @@ "x-sim-operation": "catalog.blocks.list", "x-oauth-scope": "api:read", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4294,6 +4662,14 @@ "x-sim-operation": "catalog.blocks.read", "x-oauth-scope": "api:read", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "blockId", @@ -4374,6 +4750,14 @@ "x-sim-operation": "catalog.tools.list", "x-oauth-scope": "api:read", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4525,6 +4909,14 @@ "x-sim-operation": "catalog.tools.read", "x-oauth-scope": "api:read", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "toolId", @@ -4605,6 +4997,14 @@ "x-sim-operation": "tools.execute", "x-oauth-scope": "api:write", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "toolId", @@ -4693,6 +5093,14 @@ "x-sim-operation": "catalog.connector_types.list", "x-oauth-scope": "api:read", "tags": ["Catalog"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4809,6 +5217,14 @@ "x-sim-operation": "permission_groups.list", "x-oauth-scope": "api:read", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -4934,6 +5350,14 @@ "x-sim-operation": "permission_groups.create", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5021,6 +5445,14 @@ "x-sim-operation": "permission_groups.read", "x-oauth-scope": "api:read", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -5097,6 +5529,14 @@ "x-sim-operation": "permission_groups.update", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5193,6 +5633,14 @@ "x-sim-operation": "permission_groups.delete", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5271,6 +5719,14 @@ "x-sim-operation": "permission_groups.members.list", "x-oauth-scope": "api:read", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -5395,6 +5851,14 @@ "x-sim-operation": "permission_groups.members.add", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5493,6 +5957,14 @@ "x-sim-operation": "permission_groups.members.remove", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5585,6 +6057,14 @@ "x-sim-operation": "permission_groups.members.bulk_add", "x-oauth-scope": "api:write", "tags": ["Permission Groups"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -5683,6 +6163,14 @@ "x-sim-operation": "organizations.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "search", @@ -5799,6 +6287,14 @@ "x-sim-operation": "organizations.read", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -5866,6 +6362,14 @@ "x-sim-operation": "organizations.workspaces.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -5993,6 +6497,14 @@ "x-sim-operation": "organizations.members.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -6120,6 +6632,14 @@ "x-sim-operation": "organizations.members.update", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -6216,6 +6736,14 @@ "x-sim-operation": "organizations.members.remove", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -6297,6 +6825,14 @@ "x-sim-operation": "organizations.invitations.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -6433,6 +6969,14 @@ "x-sim-operation": "organizations.invitations.create", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -6520,6 +7064,14 @@ "x-sim-operation": "organizations.invitations.read", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -6596,6 +7148,14 @@ "x-sim-operation": "invitations.revoke", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -6677,6 +7237,14 @@ "x-sim-operation": "organizations.invitations.workspaces.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -6815,6 +7383,14 @@ "x-sim-operation": "invitations.resend", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -6913,6 +7489,14 @@ "x-sim-operation": "organization.sso.providers.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -7029,6 +7613,14 @@ "x-sim-operation": "organization.sso.providers.save", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7137,6 +7729,14 @@ "x-sim-operation": "organization.sso.providers.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -7217,6 +7817,14 @@ "x-sim-operation": "organization.sso.providers.delete", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7299,6 +7907,14 @@ "x-sim-operation": "organization.sso.set_primary_provider", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7398,6 +8014,14 @@ "x-sim-operation": "organization.sso.read_requirement", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -7466,6 +8090,14 @@ "x-sim-operation": "organization.sso.set_requirement", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7553,6 +8185,14 @@ "x-sim-operation": "organizations.domains.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -7669,6 +8309,14 @@ "x-sim-operation": "organizations.domains.add", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7777,6 +8425,14 @@ "x-sim-operation": "organizations.domains.verify", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7876,6 +8532,14 @@ "x-sim-operation": "organizations.domains.remove", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -7958,6 +8622,14 @@ "x-sim-operation": "credentials.members.list", "x-oauth-scope": "api:read", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "credentialId", @@ -8084,6 +8756,14 @@ "x-sim-operation": "credentials.members.upsert", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "credentialId", @@ -8202,6 +8882,14 @@ "x-sim-operation": "credentials.members.remove", "x-oauth-scope": "api:write", "tags": ["Credentials"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "credentialId", @@ -8294,6 +8982,14 @@ "x-sim-operation": "permission_groups.read_user_config", "x-oauth-scope": "api:read", "tags": ["Workspaces"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -8362,6 +9058,14 @@ "x-sim-operation": "workspace_invitations.send_batch", "x-oauth-scope": "api:write", "tags": ["Workspaces"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -8450,6 +9154,14 @@ "x-sim-operation": "organization_member_usage_limits.read", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -8526,6 +9238,14 @@ "x-sim-operation": "organization_member_usage_limits.update", "x-oauth-scope": "api:write", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -8621,6 +9341,14 @@ "x-sim-operation": "organization_usage.summary.read", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -8748,6 +9476,14 @@ "x-sim-operation": "organization_usage.breakdown.read", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -8902,6 +9638,14 @@ "x-sim-operation": "organization_usage.events.list", "x-oauth-scope": "api:read", "tags": ["Organizations"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -9087,6 +9831,14 @@ "x-sim-operation": "access_requests.discover", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -9250,6 +10002,14 @@ "x-sim-operation": "access_requests.list_mine", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -9378,6 +10138,14 @@ "x-sim-operation": "access_requests.create", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -9466,6 +10234,14 @@ "x-sim-operation": "access_requests.cancel", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -9549,6 +10325,14 @@ "x-sim-operation": "access_requests.discover", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -9711,6 +10495,14 @@ "x-sim-operation": "access_requests.list_mine", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -9840,6 +10632,14 @@ "x-sim-operation": "access_requests.create", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -9925,6 +10725,14 @@ "x-sim-operation": "access_requests.list_organization", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -10066,6 +10874,14 @@ "x-sim-operation": "access_requests.cancel", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -10148,6 +10964,14 @@ "x-sim-operation": "access_requests.preview", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -10230,6 +11054,14 @@ "x-sim-operation": "access_requests.resolve", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -10329,6 +11161,14 @@ "x-sim-operation": "access_requests.get_settings", "x-oauth-scope": "api:read", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "organizationId", @@ -10397,6 +11237,14 @@ "x-sim-operation": "access_requests.update_settings", "x-oauth-scope": "api:write", "tags": ["Access Requests"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "organizationId", @@ -10486,10 +11334,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-tables.json b/apps/docs/openapi-v2-tables.json index 00a5cdccb61..dec956e4e0b 100644 --- a/apps/docs/openapi-v2-tables.json +++ b/apps/docs/openapi-v2-tables.json @@ -43,6 +43,14 @@ "x-sim-operation": "tables.list", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -192,6 +200,14 @@ "x-sim-operation": "tables.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace, table metadata, folder placement, and typed columns.", @@ -266,6 +282,14 @@ "x-sim-operation": "tables.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -345,6 +369,14 @@ "x-sim-operation": "tables.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -424,6 +456,14 @@ "x-sim-operation": "tables.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -511,6 +551,14 @@ "x-sim-operation": "tables.columns.add", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -596,6 +644,14 @@ "x-sim-operation": "tables.columns.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -681,6 +737,14 @@ "x-sim-operation": "tables.columns.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -768,6 +832,14 @@ "x-sim-operation": "tables.rows.list", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -879,6 +951,14 @@ "x-sim-operation": "tables.rows.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -964,6 +1044,14 @@ "x-sim-operation": "tables.rows.update_many", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1049,6 +1137,14 @@ "x-sim-operation": "tables.rows.delete_many", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1136,6 +1232,14 @@ "x-sim-operation": "tables.rows.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -1233,6 +1337,14 @@ "x-sim-operation": "tables.rows.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1329,6 +1441,14 @@ "x-sim-operation": "tables.rows.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1421,6 +1541,14 @@ "x-sim-operation": "tables.rows.upsert", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1508,6 +1636,14 @@ "x-sim-operation": "tables.rows.query", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -1592,6 +1728,14 @@ "x-sim-operation": "tables.rows.query", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -1676,6 +1820,14 @@ "x-sim-operation": "tables.views.list", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -1752,6 +1904,14 @@ "x-sim-operation": "tables.views.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -1836,6 +1996,14 @@ "x-sim-operation": "tables.views.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -1923,6 +2091,14 @@ "x-sim-operation": "tables.views.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2016,6 +2192,14 @@ "x-sim-operation": "tables.views.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2105,6 +2289,14 @@ "x-sim-operation": "tables.groups.list", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -2181,6 +2373,14 @@ "x-sim-operation": "tables.groups.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2266,6 +2466,14 @@ "x-sim-operation": "tables.groups.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2354,6 +2562,14 @@ "x-sim-operation": "tables.groups.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2441,6 +2657,14 @@ "x-sim-operation": "tables.runs.start", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2523,6 +2747,14 @@ "x-sim-operation": "tables.runs.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -2601,6 +2833,14 @@ "x-sim-operation": "tables.runs.start", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -2705,6 +2945,14 @@ "x-sim-operation": "tables.rows.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -2805,6 +3053,14 @@ "x-sim-operation": "tables.rows.search", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -2889,6 +3145,14 @@ "x-sim-operation": "tables.imports.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace, CSV source, target table, optional mapping, and timezone.", @@ -2966,6 +3230,14 @@ "x-sim-operation": "tables.imports.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "importId", @@ -3054,6 +3326,14 @@ "x-sim-operation": "tables.imports.cancel", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "importId", @@ -3147,6 +3427,14 @@ "x-sim-operation": "tables.imports.create_parts", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "importId", @@ -3257,6 +3545,14 @@ "x-sim-operation": "tables.imports.complete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "importId", @@ -3353,6 +3649,14 @@ "x-sim-operation": "tables.exports.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -3440,6 +3744,14 @@ "x-sim-operation": "tables.exports.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -3528,6 +3840,14 @@ "x-sim-operation": "tables.exports.cancel", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -3621,6 +3941,14 @@ "x-sim-operation": "tables.exports.download", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -3714,6 +4042,14 @@ "x-sim-operation": "tables.runs.cancel", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -3798,6 +4134,14 @@ "x-sim-operation": "tables.folders.list", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3913,6 +4257,14 @@ "x-sim-operation": "tables.folders.create", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope and canonical folder path to create.", @@ -3985,6 +4337,14 @@ "x-sim-operation": "tables.folders.update", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope, current canonical path, and destination path.", @@ -4057,6 +4417,14 @@ "x-sim-operation": "tables.folders.delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4169,6 +4537,14 @@ "x-sim-operation": "tables.folders.restore", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope and the canonical path the archived folder held.", @@ -4243,6 +4619,14 @@ "x-sim-operation": "tables.restore", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -4330,6 +4714,14 @@ "x-sim-operation": "tables.rows.update_many", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -4417,6 +4809,14 @@ "x-sim-operation": "tables.runs.read", "x-oauth-scope": "api:read", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "tableId", @@ -4505,6 +4905,14 @@ "x-sim-operation": "tables.runs.cancel", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "tableId", @@ -4595,6 +5003,14 @@ "x-sim-operation": "tables.bulk_move", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope, the tables and folder paths to move, and the destination folder path.", @@ -4666,6 +5082,14 @@ "x-sim-operation": "tables.bulk_delete", "x-oauth-scope": "api:write", "tags": ["Tables"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace scope, and the tables and folder paths to delete.", @@ -4742,10 +5166,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/docs/openapi-v2-workflows.json b/apps/docs/openapi-v2-workflows.json index 31383bc19fb..e5589141f5a 100644 --- a/apps/docs/openapi-v2-workflows.json +++ b/apps/docs/openapi-v2-workflows.json @@ -51,6 +51,14 @@ "x-sim-operation": "workflows.list", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -212,6 +220,14 @@ "x-sim-operation": "workflows.create", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Name, description, workspace, and optional folder for a new workflow.", @@ -289,6 +305,14 @@ "x-sim-operation": "workflows.read", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -355,6 +379,14 @@ "x-sim-operation": "workflows.state.replace", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -456,6 +488,14 @@ "x-sim-operation": "workflows.operations.apply", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -557,6 +597,14 @@ "x-sim-operation": "workflows.variables.apply_operations", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -648,6 +696,14 @@ "x-sim-operation": "workflows.duplicate", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -739,6 +795,14 @@ "x-sim-operation": "workflows.restore", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -816,6 +880,14 @@ "x-sim-operation": "workflows.bulk.move", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workflows to relocate and the folder to relocate them into.", @@ -887,6 +959,14 @@ "x-sim-operation": "workflows.read", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -956,6 +1036,14 @@ "x-sim-operation": "workflows.update", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -1045,6 +1133,14 @@ "x-sim-operation": "workflows.delete", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -1116,6 +1212,14 @@ "x-sim-operation": "workflows.versions.list", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -1208,6 +1312,14 @@ "x-sim-operation": "workflows.versions.compare", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -1303,6 +1415,14 @@ "x-sim-operation": "workflows.versions.read", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "version", @@ -1381,6 +1501,14 @@ "x-sim-operation": "workflows.versions.update", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "version", @@ -1478,6 +1606,14 @@ "x-sim-operation": "workflows.versions.activate", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "version", @@ -1581,6 +1717,14 @@ "x-sim-operation": "workflows.versions.revert", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "version", @@ -1692,6 +1836,14 @@ "x-sim-operation": "workflows.read", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -1758,6 +1910,14 @@ "x-sim-operation": "workflows.public_api.update", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -1846,6 +2006,14 @@ "x-sim-operation": "workflows.deploy", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -1935,6 +2103,14 @@ "x-sim-operation": "workflows.undeploy", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -2006,6 +2182,14 @@ "x-sim-operation": "workflows.versions.activate", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -2097,6 +2281,14 @@ "x-sim-operation": "workflows.export", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -2188,6 +2380,14 @@ "x-sim-operation": "workflows.import", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workflow document, destination, and optional reviewed mappings.", @@ -2265,6 +2465,14 @@ "x-sim-operation": "chat_deployments.list", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -2402,6 +2610,14 @@ "x-sim-operation": "chat_deployments.read", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -2468,6 +2684,14 @@ "x-sim-operation": "chat_deployments.replace", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -2557,6 +2781,14 @@ "x-sim-operation": "chat_deployments.delete", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -2630,7 +2862,7 @@ "apiKey": [] }, { - "oauthBearer": [] + "oauthBearer": ["api:write"] }, {} ], @@ -2789,6 +3021,14 @@ "x-sim-operation": "workflows.runs.list", "x-oauth-scope": "api:read", "tags": ["Workflow Runs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -2939,6 +3179,14 @@ "x-sim-operation": "workflows.runs.read", "x-oauth-scope": "api:read", "tags": ["Workflow Runs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -3068,6 +3316,14 @@ "x-sim-operation": "workflows.download_run_file", "x-oauth-scope": "api:read", "tags": ["Workflow Runs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workflowId", @@ -3174,6 +3430,14 @@ "x-sim-operation": "workflows.runs.resume", "x-oauth-scope": "api:write", "tags": ["Workflow Runs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -3305,6 +3569,14 @@ "x-sim-operation": "workflows.runs.cancel", "x-oauth-scope": "api:write", "tags": ["Workflow Runs"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workflowId", @@ -3389,6 +3661,14 @@ "x-sim-operation": "workflows.folders.list", "x-oauth-scope": "api:read", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3504,6 +3784,14 @@ "x-sim-operation": "workflows.folders.create", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Workspace and canonical path for a new workflow folder.", @@ -3579,6 +3867,14 @@ "x-sim-operation": "workflows.folders.relocate", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Current and destination paths for a workflow folder.", @@ -3654,6 +3950,14 @@ "x-sim-operation": "workflows.folders.delete", "x-oauth-scope": "api:write", "tags": ["Workflows"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3766,6 +4070,14 @@ "x-sim-operation": "workspaces.fork.preview", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3840,6 +4152,14 @@ "x-sim-operation": "workspaces.fork.create", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3914,6 +4234,14 @@ "x-sim-operation": "workspaces.fork.sync.preview", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -3988,6 +4316,14 @@ "x-sim-operation": "workspaces.fork.sync", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4062,6 +4398,14 @@ "x-sim-operation": "workspaces.fork.sync.preview", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4136,6 +4480,14 @@ "x-sim-operation": "workspaces.fork.sync", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4210,6 +4562,14 @@ "x-sim-operation": "workspaces.fork.discover", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4273,6 +4633,14 @@ "x-sim-operation": "workspaces.fork.discover", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4336,6 +4704,14 @@ "x-sim-operation": "workspaces.fork.discover", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4447,6 +4823,14 @@ "x-sim-operation": "workspaces.fork.discover", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4577,6 +4961,14 @@ "x-sim-operation": "workspaces.fork.mappings.read", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4709,6 +5101,14 @@ "x-sim-operation": "workspaces.fork.mappings.update", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4783,6 +5183,14 @@ "x-sim-operation": "workspaces.fork.rollback", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4857,6 +5265,14 @@ "x-sim-operation": "workspaces.fork.unlink", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -4931,6 +5347,14 @@ "x-sim-operation": "workspaces.fork.exclusions", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "parameters": [ { "name": "workspaceId", @@ -5005,6 +5429,14 @@ "x-sim-operation": "workflows.import.preview", "x-oauth-scope": "api:write", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:write"] + } + ], "requestBody": { "required": true, "description": "Portable workflow data and destination metadata for an import.", @@ -5065,6 +5497,14 @@ "x-sim-operation": "selectors.execute", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "requestBody": { "required": true, "description": "The body for this operation.", @@ -5125,6 +5565,14 @@ "x-sim-operation": "selectors.execute", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "requestBody": { "required": true, "description": "The body for this operation.", @@ -5185,6 +5633,14 @@ "x-sim-operation": "workspaces.operations.read", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -5260,6 +5716,14 @@ "x-sim-operation": "workspaces.operations.read", "x-oauth-scope": "api:read", "tags": ["Workspace Sync"], + "security": [ + { + "apiKey": [] + }, + { + "oauthBearer": ["api:read"] + } + ], "parameters": [ { "name": "workspaceId", @@ -5361,10 +5825,20 @@ "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description." }, "oauthBearer": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "OAuth 2.0 access token", - "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role." + "type": "oauth2", + "description": "A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.", + "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": { diff --git a/apps/sim/app/api/[[...segments]]/route.ts b/apps/sim/app/api/[[...segments]]/route.ts new file mode 100644 index 00000000000..feae18c0231 --- /dev/null +++ b/apps/sim/app/api/[[...segments]]/route.ts @@ -0,0 +1,20 @@ +import { NextResponse } from 'next/server' +import { withRouteHandler } from '@/lib/core/utils/with-route-handler' + +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +/** + * JSON 404 for any `/api` path that matches no route file, so a mistyped API path never gets + * the global HTML `not-found` page. Unauthenticated for the reasons on its `/api/v2` counterpart, + * which keeps the v2 envelope for that prefix. + */ +const notFound = () => NextResponse.json({ error: 'Not found' }, { status: 404 }) + +export const GET = withRouteHandler(notFound) +export const POST = withRouteHandler(notFound) +export const PUT = withRouteHandler(notFound) +export const PATCH = withRouteHandler(notFound) +export const DELETE = withRouteHandler(notFound) +export const HEAD = withRouteHandler(notFound) +export const OPTIONS = withRouteHandler(notFound) diff --git a/apps/sim/lib/api/contracts/v2/openapi/shared.ts b/apps/sim/lib/api/contracts/v2/openapi/shared.ts index ec711673713..d162ee962f3 100644 --- a/apps/sim/lib/api/contracts/v2/openapi/shared.ts +++ b/apps/sim/lib/api/contracts/v2/openapi/shared.ts @@ -7,6 +7,11 @@ import type { OpenApiRouteDefinition, OpenApiSecurityScheme, } from '@/lib/api/openapi/types' +import { + OAUTH_API_READ_SCOPE, + OAUTH_API_WRITE_SCOPE, + OAUTH_SCOPE_DESCRIPTIONS, +} from '@/lib/auth/oauth-provider' interface ErrorResponseOptions { /** @@ -317,6 +322,9 @@ export function withRequestBodyErrors(route: OpenApiRouteDefinition): OpenApiRou return { ...route, operation: { ...route.operation, errors: derived } } } +/** The production authorization server, as its RFC 8414 metadata names it (`issuer`). */ +const SIM_OAUTH_ISSUER = 'https://www.sim.ai/api/auth' + export const V2_AUTH_SECURITY = [{ apiKey: [] }, { oauthBearer: [] }] as const export const V2_AUTH_SECURITY_SCHEMES = { @@ -328,11 +336,21 @@ export const V2_AUTH_SECURITY_SCHEMES = { 'Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description.', }, oauthBearer: { - type: 'http', - scheme: 'bearer', - bearerFormat: 'OAuth 2.0 access token', + type: 'oauth2', description: - 'A Sim OAuth access token obtained by a registered client through the authorization-code flow. Each operation declares its required scope: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.', + 'A Sim OAuth access token obtained by a registered client through the authorization-code flow with PKCE (S256), sent as `Authorization: Bearer`. Each operation declares the scope it requires: api:read permits reads and searches; api:write also permits changes and execution and implies api:read. Scope requirements follow the application operation, independent of HTTP method or workspace role.', + flows: { + authorizationCode: { + authorizationUrl: `${SIM_OAUTH_ISSUER}/oauth2/authorize`, + tokenUrl: `${SIM_OAUTH_ISSUER}/oauth2/token`, + refreshUrl: `${SIM_OAUTH_ISSUER}/oauth2/token`, + scopes: { + [OAUTH_API_READ_SCOPE]: OAUTH_SCOPE_DESCRIPTIONS[OAUTH_API_READ_SCOPE], + [OAUTH_API_WRITE_SCOPE]: OAUTH_SCOPE_DESCRIPTIONS[OAUTH_API_WRITE_SCOPE], + offline_access: OAUTH_SCOPE_DESCRIPTIONS.offline_access, + }, + }, + }, }, } as const satisfies Readonly> diff --git a/apps/sim/lib/api/mcp/host-routing.test.ts b/apps/sim/lib/api/mcp/host-routing.test.ts index 021aba5ce99..04b82d4d153 100644 --- a/apps/sim/lib/api/mcp/host-routing.test.ts +++ b/apps/sim/lib/api/mcp/host-routing.test.ts @@ -35,6 +35,7 @@ describe('Sim MCP host routing', () => { '/.well-known/oauth-protected-resource/mcp', '/.well-known/oauth-protected-resource/api/mcp', ], + ['/.well-known/oauth-protected-resource', '/.well-known/oauth-protected-resource/api/mcp'], ['/.well-known/oauth-authorization-server', '/.well-known/oauth-authorization-server'], ])('maps %s to %s', (pathname, target) => { expect(resolveSimMcpHostPath('mcp.sim.ai', pathname)).toBe(target) diff --git a/apps/sim/lib/api/mcp/host-routing.ts b/apps/sim/lib/api/mcp/host-routing.ts index 55d5597e827..3cec6c616aa 100644 --- a/apps/sim/lib/api/mcp/host-routing.ts +++ b/apps/sim/lib/api/mcp/host-routing.ts @@ -21,12 +21,15 @@ function authorityOf(host: string, protocol: string): string | null { * Routes requests for the Sim MCP server's canonical URL. * * On the MCP URL's host, the MCP path and its RFC 9728 metadata map onto the - * app routes that serve them. When that host is dedicated (`mcp.sim.ai`), it - * also serves the authorization-server metadata older clients look for at the - * resource origin, and every other path the proxy sees is `not_found`; the app - * host in turn answers `not_found` for the internal MCP paths, so the server has - * exactly one URL and every client binds its tokens to it. `null` leaves the - * request to the rest of the proxy. + * app routes that serve them. A dedicated host (`mcp.sim.ai`) also serves: + * - the same metadata at the root well-known path, which MCP clients try after + * the path-inserted one (MCP authorization, Protected Resource Metadata Discovery); + * - the authorization-server metadata older clients look for at the resource origin. + * + * Every other path on a dedicated host is `not_found`, and the app host answers + * `not_found` for the internal MCP paths, so the server has exactly one URL and + * every client binds its tokens to it. `null` leaves the request to the rest of + * the proxy. * * Reads `Host` rather than `X-Forwarded-Host`, which a client could set to * reach the rest of the app through the dedicated host. @@ -46,6 +49,7 @@ export function resolveSimMcpHostPath( if (pathname === mcp.pathname) return SIM_MCP_ROUTE_PATH if (pathname === `${PROTECTED_RESOURCE_METADATA}${mcp.pathname}`) return internalMetadataPath if (!dedicated) return null + if (pathname === PROTECTED_RESOURCE_METADATA) return internalMetadataPath return pathname === AUTHORIZATION_SERVER_METADATA || pathname === OPENAI_APPS_CHALLENGE ? pathname : 'not_found' diff --git a/apps/sim/lib/api/openapi/types.ts b/apps/sim/lib/api/openapi/types.ts index a0cbc704256..800881d4470 100644 --- a/apps/sim/lib/api/openapi/types.ts +++ b/apps/sim/lib/api/openapi/types.ts @@ -17,6 +17,19 @@ export type OpenApiSecurityScheme = bearerFormat?: string description: string } + | { + type: 'oauth2' + description: string + flows: { + authorizationCode: { + authorizationUrl: string + tokenUrl: string + refreshUrl?: string + /** Every scope an operation may require, keyed by name. */ + scopes: Readonly> + } + } + } export interface OpenApiInfo { title: string diff --git a/apps/sim/scripts/test-mcp-host-e2e.ts b/apps/sim/scripts/test-mcp-host-e2e.ts index 03319f69154..2d6e2c0e3d4 100644 --- a/apps/sim/scripts/test-mcp-host-e2e.ts +++ b/apps/sim/scripts/test-mcp-host-e2e.ts @@ -4,11 +4,15 @@ import { dirname } from 'node:path' import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' -/** Exercises the public ownership challenge and host isolation through a running local app. */ +/** + * Exercises the public ownership challenge, protected-resource discovery, and host isolation + * through a running local app. + */ const logger = createLogger('McpHostE2E') const CHALLENGE_PATH = '/.well-known/openai-apps-challenge' const EXPECTED_CHALLENGE = 'lFJ1-XIWpHGRNcgzTPl2Y_yYCTWLvlIbAvNRD08EvLI' const MCP_HOST = 'mcp.sim.test' +const PROTECTED_RESOURCE_PATH = '/.well-known/oauth-protected-resource' const startedAt = new Date().toISOString() const configuredBaseUrl = process.env.MCP_HOST_E2E_BASE_URL @@ -30,16 +34,23 @@ interface CheckResult { } const checks: CheckResult[] = [] -const requests: { path: string; userAgent: string; host: string; status: number }[] = [] +const requests: { + method: string + path: string + userAgent: string + host: string + status: number +}[] = [] -async function request(path: string, userAgent: string, host = MCP_HOST) { +async function request(path: string, userAgent: string, host = MCP_HOST, method = 'GET') { // boundary-raw-fetch: exercise the real proxy and route over local HTTP. const response = await fetch(new URL(path, baseUrl), { + method, headers: { Host: host, 'User-Agent': userAgent }, redirect: 'error', signal: AbortSignal.timeout(120_000), }) - requests.push({ path, userAgent, host, status: response.status }) + requests.push({ method, path, userAgent, host, status: response.status }) const body = await response.text() return { response, body } } @@ -79,6 +90,39 @@ try { }) } + for (const path of [`${PROTECTED_RESOURCE_PATH}/mcp`, PROTECTED_RESOURCE_PATH]) { + await check( + `dedicated MCP host serves its protected-resource metadata at ${path}`, + async () => { + const { response, body } = await request(path, '') + assert.equal(response.status, 200) + const metadata = JSON.parse(body) as Record + assert.equal(metadata.resource, `http://${MCP_HOST}/mcp`) + assert.deepEqual(metadata.scopes_supported, ['api:read', 'api:write']) + assert(Array.isArray(metadata.authorization_servers)) + } + ) + } + + await check('application host serves no root protected-resource metadata', async () => { + const { response } = await request(PROTECTED_RESOURCE_PATH, 'Mozilla/5.0', baseUrl.host) + assert.equal(response.status, 404) + }) + + for (const method of ['GET', 'POST']) { + await check(`application host answers an unknown API ${method} with JSON`, async () => { + const { response, body } = await request( + '/api/not-a-real-route/nested', + 'Mozilla/5.0', + baseUrl.host, + method + ) + assert.equal(response.status, 404) + assert.match(response.headers.get('content-type') ?? '', /^application\/json/) + assert.deepEqual(JSON.parse(body), { error: 'Not found' }) + }) + } + await check('application host still serves health checks', async () => { const { response } = await request('/api/health', 'Mozilla/5.0', baseUrl.host) assert.equal(response.status, 200) diff --git a/scripts/check-api-validation-contracts.ts b/scripts/check-api-validation-contracts.ts index 2ce067c42cd..71be84f6021 100644 --- a/scripts/check-api-validation-contracts.ts +++ b/scripts/check-api-validation-contracts.ts @@ -61,6 +61,8 @@ const INDIRECT_ZOD_ROUTES = new Set([ // there is no input to validate and its only response is the fixed v2 error // envelope. 'apps/sim/app/api/v2/[[...segments]]/route.ts', + // The same JSON 404 for unknown paths anywhere else under /api. + 'apps/sim/app/api/[[...segments]]/route.ts', 'apps/sim/app/api/demo-requests/route.ts', // Input-less session-bound GET: nothing to validate; response is // contract-typed via `satisfies InvitationDetails` in the route. diff --git a/scripts/openapi/documents.test.ts b/scripts/openapi/documents.test.ts index fb26ab9dbdf..35febaf2e0f 100644 --- a/scripts/openapi/documents.test.ts +++ b/scripts/openapi/documents.test.ts @@ -244,9 +244,9 @@ describe('generated OpenAPI documents', () => { ) expect(generated['x-sim-operation']).toBe(route.operation.applicationOperation.id) const operationScope = route.operation.applicationOperation.oauthScope - expect(generated['x-oauth-scope']).toBe( - operationScope === 'search:read' ? 'api:read' : operationScope - ) + const expectedScope = operationScope === 'search:read' ? 'api:read' : operationScope + expect(generated['x-oauth-scope']).toBe(expectedScope) + expect(generated.security).toContainEqual({ oauthBearer: [expectedScope] }) } } }, 30_000) diff --git a/scripts/openapi/generator.test.ts b/scripts/openapi/generator.test.ts index 52890adf773..b5070d711f8 100644 --- a/scripts/openapi/generator.test.ts +++ b/scripts/openapi/generator.test.ts @@ -344,7 +344,19 @@ describe('OpenAPI generator', () => { generateOpenApiDocument({ ...document([simpleRoute()]), security: [{ oauthBearer: [] }], - securitySchemes: { oauthBearer: { type: 'http', scheme: 'bearer' } }, + securitySchemes: { + oauthBearer: { + type: 'oauth2', + description: 'OAuth.', + flows: { + authorizationCode: { + authorizationUrl: 'https://example.com/authorize', + tokenUrl: 'https://example.com/token', + scopes: { 'api:read': 'Read.' }, + }, + }, + }, + }, }) ).toThrow("must declare its canonical application's OAuth scope") }) diff --git a/scripts/openapi/generator.ts b/scripts/openapi/generator.ts index e94245c3605..95c56831f24 100644 --- a/scripts/openapi/generator.ts +++ b/scripts/openapi/generator.ts @@ -6,6 +6,7 @@ import type { OpenApiDocumentDefinition, OpenApiOperationMetadata, OpenApiRouteDefinition, + OpenApiSecurityRequirement, OpenApiStatusSuccessMetadata, } from '@/lib/api/openapi/types' @@ -500,6 +501,31 @@ function publicApiOAuthScope( return scope === 'search:read' ? 'api:read' : scope } +function isOAuthScheme(definition: OpenApiDocumentDefinition, scheme: string): boolean { + return definition.securitySchemes[scheme]?.type === 'oauth2' +} + +/** Fills the operation's OAuth scope into every OAuth 2.0 requirement, so `security` states least privilege. */ +function operationSecurity( + operation: OpenApiOperationMetadata, + definition: OpenApiDocumentDefinition, + oauthScope: string | undefined +): readonly OpenApiSecurityRequirement[] | undefined { + const requirements = operation.security ?? definition.security + const usesOAuth = requirements.some((requirement) => + Object.keys(requirement).some((scheme) => isOAuthScheme(definition, scheme)) + ) + if (!oauthScope || !usesOAuth) return operation.security + return requirements.map((requirement) => + Object.fromEntries( + Object.entries(requirement).map(([scheme, scopes]) => [ + scheme, + isOAuthScheme(definition, scheme) ? [oauthScope] : scopes, + ]) + ) + ) +} + function operationFor( route: OpenApiRouteDefinition, definition: OpenApiDocumentDefinition, @@ -656,6 +682,7 @@ function operationFor( const requestBody = requestBodyFor(route, components, label) const oauthScope = publicApiOAuthScope(operation.applicationOperation.oauthScope) + const security = operationSecurity(operation, definition, oauthScope) return { operationId: operation.operationId, summary: operation.summary, @@ -666,7 +693,7 @@ function operationFor( ...(oauthScope ? { 'x-oauth-scope': oauthScope } : {}), tags: [...operation.tags], ...(operation.deprecated === undefined ? {} : { deprecated: operation.deprecated }), - ...(operation.security === undefined ? {} : { security: operation.security }), + ...(security === undefined ? {} : { security }), ...(parameters.length === 0 ? {} : { parameters }), ...(requestBody ? { requestBody } : {}), responses, @@ -680,11 +707,14 @@ function validateOperationMetadata( ): void { nonEmpty(operation.applicationOperation.id, `${label} application operation id`) const security = operation.security ?? definition.security - if (security.some((requirement) => 'oauthBearer' in requirement)) { + for (const scheme of new Set(security.flatMap((requirement) => Object.keys(requirement)))) { + const declared = definition.securitySchemes[scheme] + if (declared?.type !== 'oauth2') continue const oauthScope = publicApiOAuthScope(operation.applicationOperation.oauthScope) + invariant(oauthScope, `${label} must declare its canonical application's OAuth scope`) invariant( - oauthScope === 'api:read' || oauthScope === 'api:write', - `${label} must declare its canonical application's OAuth scope` + oauthScope in declared.flows.authorizationCode.scopes, + `${label} OAuth scope ${oauthScope} is not declared by security scheme ${scheme}` ) } nonEmpty(operation.operationId, `${label} operationId`) @@ -752,7 +782,7 @@ function validateSecurity( ) invariant( Array.isArray(scopes) && scopes.length === 0, - `${label} ${scheme} security requirement must use an empty scope array` + `${label} ${scheme} security requirement must use an empty scope array; OAuth scopes are derived from the application operation` ) } } From deeddaaa089d3c7d1c2b7225c6d1bfec34d6c30b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 14 Oct 2026 10:45:33 -0700 Subject: [PATCH 2/2] fix(api): shrink the unused-exports baseline and keep rewrite checks out of the dev-server e2e --- apps/sim/scripts/test-mcp-host-e2e.ts | 18 ++---------------- scripts/check-unused-exports.baseline.json | 1 - 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/apps/sim/scripts/test-mcp-host-e2e.ts b/apps/sim/scripts/test-mcp-host-e2e.ts index 2d6e2c0e3d4..208ec1ae065 100644 --- a/apps/sim/scripts/test-mcp-host-e2e.ts +++ b/apps/sim/scripts/test-mcp-host-e2e.ts @@ -5,8 +5,8 @@ import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' /** - * Exercises the public ownership challenge, protected-resource discovery, and host isolation - * through a running local app. + * Exercises the public ownership challenge, host isolation, and the app-wide JSON 404 through a + * running local app. */ const logger = createLogger('McpHostE2E') const CHALLENGE_PATH = '/.well-known/openai-apps-challenge' @@ -90,20 +90,6 @@ try { }) } - for (const path of [`${PROTECTED_RESOURCE_PATH}/mcp`, PROTECTED_RESOURCE_PATH]) { - await check( - `dedicated MCP host serves its protected-resource metadata at ${path}`, - async () => { - const { response, body } = await request(path, '') - assert.equal(response.status, 200) - const metadata = JSON.parse(body) as Record - assert.equal(metadata.resource, `http://${MCP_HOST}/mcp`) - assert.deepEqual(metadata.scopes_supported, ['api:read', 'api:write']) - assert(Array.isArray(metadata.authorization_servers)) - } - ) - } - await check('application host serves no root protected-resource metadata', async () => { const { response } = await request(PROTECTED_RESOURCE_PATH, 'Mozilla/5.0', baseUrl.host) assert.equal(response.status, 404) diff --git a/scripts/check-unused-exports.baseline.json b/scripts/check-unused-exports.baseline.json index 434fdeadc3a..1220dce515d 100644 --- a/scripts/check-unused-exports.baseline.json +++ b/scripts/check-unused-exports.baseline.json @@ -4036,7 +4036,6 @@ "apps/sim/lib/api/openapi/types.ts#OpenApiInfo", "apps/sim/lib/api/openapi/types.ts#OpenApiOperationSuccess", "apps/sim/lib/api/openapi/types.ts#OpenApiRequestBodySchema", - "apps/sim/lib/api/openapi/types.ts#OpenApiSecurityRequirement", "apps/sim/lib/api/openapi/types.ts#OpenApiServer", "apps/sim/lib/api/openapi/types.ts#OpenApiTag", "apps/sim/lib/api/server/routes/internal-json-route.ts#InternalJsonPresenterContext",