@rudderhq/server 0.6.1 → 0.6.2-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundled-plugins/plugin-linear/dist/worker.js +112 -4
- package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +2 -2
- package/dist/routes/access-onboarding.helpers.d.ts +0 -6
- package/dist/routes/access-onboarding.helpers.d.ts.map +1 -1
- package/dist/routes/access-onboarding.helpers.js +0 -7
- package/dist/routes/access-onboarding.helpers.js.map +1 -1
- package/dist/routes/access.d.ts +1 -1
- package/dist/routes/access.d.ts.map +1 -1
- package/dist/routes/access.js +2 -7
- package/dist/routes/access.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +24 -49
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/agents.management-routes.d.ts.map +1 -1
- package/dist/routes/agents.management-routes.js +0 -1
- package/dist/routes/agents.management-routes.js.map +1 -1
- package/dist/routes/chats.d.ts.map +1 -1
- package/dist/routes/chats.js +77 -62
- package/dist/routes/chats.js.map +1 -1
- package/dist/routes/chats.preflight.d.ts +56 -0
- package/dist/routes/chats.preflight.d.ts.map +1 -0
- package/dist/routes/chats.preflight.js +72 -0
- package/dist/routes/chats.preflight.js.map +1 -0
- package/dist/routes/chats.runtime-controls.d.ts +62 -0
- package/dist/routes/chats.runtime-controls.d.ts.map +1 -0
- package/dist/routes/chats.runtime-controls.js +51 -0
- package/dist/routes/chats.runtime-controls.js.map +1 -0
- package/dist/routes/chats.stream-routes.d.ts.map +1 -1
- package/dist/routes/chats.stream-routes.js +22 -38
- package/dist/routes/chats.stream-routes.js.map +1 -1
- package/dist/routes/chats.stream-support.d.ts +6 -0
- package/dist/routes/chats.stream-support.d.ts.map +1 -1
- package/dist/routes/chats.stream-support.js.map +1 -1
- package/dist/routes/chats.user-state-routes.d.ts +3 -0
- package/dist/routes/chats.user-state-routes.d.ts.map +1 -0
- package/dist/routes/chats.user-state-routes.js +40 -0
- package/dist/routes/chats.user-state-routes.js.map +1 -0
- package/dist/routes/costs.d.ts.map +1 -1
- package/dist/routes/costs.js +11 -1
- package/dist/routes/costs.js.map +1 -1
- package/dist/routes/managed-mcp-agent-bindings.d.ts +1 -1
- package/dist/routes/managed-mcp-agent-bindings.d.ts.map +1 -1
- package/dist/routes/managed-mcp-agent-bindings.js +4 -0
- package/dist/routes/managed-mcp-agent-bindings.js.map +1 -1
- package/dist/routes/managed-mcp-connections.d.ts.map +1 -1
- package/dist/routes/managed-mcp-connections.js +33 -21
- package/dist/routes/managed-mcp-connections.js.map +1 -1
- package/dist/services/agent-run-context.d.ts.map +1 -1
- package/dist/services/agent-run-context.js +5 -1
- package/dist/services/agent-run-context.js.map +1 -1
- package/dist/services/agents.d.ts +5 -25
- package/dist/services/agents.d.ts.map +1 -1
- package/dist/services/agents.js +0 -72
- package/dist/services/agents.js.map +1 -1
- package/dist/services/approvals.d.ts.map +1 -1
- package/dist/services/approvals.js +0 -1
- package/dist/services/approvals.js.map +1 -1
- package/dist/services/chat-assistant.annotations.d.ts.map +1 -1
- package/dist/services/chat-assistant.annotations.js +3 -0
- package/dist/services/chat-assistant.annotations.js.map +1 -1
- package/dist/services/chat-assistant.d.ts +7 -0
- package/dist/services/chat-assistant.d.ts.map +1 -1
- package/dist/services/chat-assistant.helpers.d.ts +7 -0
- package/dist/services/chat-assistant.helpers.d.ts.map +1 -1
- package/dist/services/chat-assistant.helpers.js +23 -3
- package/dist/services/chat-assistant.helpers.js.map +1 -1
- package/dist/services/chat-assistant.js +61 -4
- package/dist/services/chat-assistant.js.map +1 -1
- package/dist/services/chat-assistant.proposal-validation.d.ts +10 -0
- package/dist/services/chat-assistant.proposal-validation.d.ts.map +1 -0
- package/dist/services/chat-assistant.proposal-validation.js +65 -0
- package/dist/services/chat-assistant.proposal-validation.js.map +1 -0
- package/dist/services/chat-assistant.runtime-batch.d.ts +1 -1
- package/dist/services/chat-assistant.runtime-batch.d.ts.map +1 -1
- package/dist/services/chat-assistant.runtime-batch.js +6 -1
- package/dist/services/chat-assistant.runtime-batch.js.map +1 -1
- package/dist/services/chat-assistant.runtime-overrides.d.ts +6 -0
- package/dist/services/chat-assistant.runtime-overrides.d.ts.map +1 -0
- package/dist/services/chat-assistant.runtime-overrides.js +81 -0
- package/dist/services/chat-assistant.runtime-overrides.js.map +1 -0
- package/dist/services/chat-generation-protocol.d.ts.map +1 -1
- package/dist/services/chat-generation-protocol.js +2 -1
- package/dist/services/chat-generation-protocol.js.map +1 -1
- package/dist/services/chat-generation-protocol.test.js +89 -0
- package/dist/services/chat-generation-protocol.test.js.map +1 -1
- package/dist/services/chat-queued-message-materialization.d.ts +2 -0
- package/dist/services/chat-queued-message-materialization.d.ts.map +1 -1
- package/dist/services/chat-queued-message-materialization.js +12 -1
- package/dist/services/chat-queued-message-materialization.js.map +1 -1
- package/dist/services/chat-work-manifest.d.ts.map +1 -1
- package/dist/services/chat-work-manifest.js +189 -4
- package/dist/services/chat-work-manifest.js.map +1 -1
- package/dist/services/chats.create.d.ts +6 -0
- package/dist/services/chats.create.d.ts.map +1 -1
- package/dist/services/chats.create.js +10 -1
- package/dist/services/chats.create.js.map +1 -1
- package/dist/services/chats.d.ts +105 -10
- package/dist/services/chats.d.ts.map +1 -1
- package/dist/services/chats.helpers.d.ts +3 -1
- package/dist/services/chats.helpers.d.ts.map +1 -1
- package/dist/services/chats.helpers.js +4 -3
- package/dist/services/chats.helpers.js.map +1 -1
- package/dist/services/chats.js +21 -111
- package/dist/services/chats.js.map +1 -1
- package/dist/services/chats.queued-message-create.d.ts +20 -0
- package/dist/services/chats.queued-message-create.d.ts.map +1 -0
- package/dist/services/chats.queued-message-create.js +127 -0
- package/dist/services/chats.queued-message-create.js.map +1 -0
- package/dist/services/chats.runtime-controls.d.ts +53 -0
- package/dist/services/chats.runtime-controls.d.ts.map +1 -0
- package/dist/services/chats.runtime-controls.js +64 -0
- package/dist/services/chats.runtime-controls.js.map +1 -0
- package/dist/services/costs.d.ts +4 -2
- package/dist/services/costs.d.ts.map +1 -1
- package/dist/services/costs.js +59 -23
- package/dist/services/costs.js.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.core.d.ts +0 -3
- package/dist/services/knowledge-portability/organization-portability.core.d.ts.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.core.js +0 -44
- package/dist/services/knowledge-portability/organization-portability.core.js.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.export.d.ts.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.export.js +1 -20
- package/dist/services/knowledge-portability/organization-portability.export.js.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.files.d.ts +1 -3
- package/dist/services/knowledge-portability/organization-portability.files.d.ts.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.files.js +1 -26
- package/dist/services/knowledge-portability/organization-portability.files.js.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.import.d.ts.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.import.js +0 -19
- package/dist/services/knowledge-portability/organization-portability.import.js.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.package.d.ts.map +1 -1
- package/dist/services/knowledge-portability/organization-portability.package.js +2 -1
- package/dist/services/knowledge-portability/organization-portability.package.js.map +1 -1
- package/dist/services/mcp/managed-bindings.d.ts +3 -1
- package/dist/services/mcp/managed-bindings.d.ts.map +1 -1
- package/dist/services/mcp/managed-bindings.js +254 -25
- package/dist/services/mcp/managed-bindings.js.map +1 -1
- package/dist/services/mcp/managed-connections.d.ts +4 -2
- package/dist/services/mcp/managed-connections.d.ts.map +1 -1
- package/dist/services/mcp/managed-connections.js +194 -22
- package/dist/services/mcp/managed-connections.js.map +1 -1
- package/dist/services/mcp/managed-runtime.d.ts +8 -3
- package/dist/services/mcp/managed-runtime.d.ts.map +1 -1
- package/dist/services/mcp/managed-runtime.js +175 -74
- package/dist/services/mcp/managed-runtime.js.map +1 -1
- package/dist/services/mcp/oauth-helpers.d.ts +53 -0
- package/dist/services/mcp/oauth-helpers.d.ts.map +1 -0
- package/dist/services/mcp/oauth-helpers.js +267 -0
- package/dist/services/mcp/oauth-helpers.js.map +1 -0
- package/dist/services/mcp/oauth.d.ts +13 -13
- package/dist/services/mcp/oauth.d.ts.map +1 -1
- package/dist/services/mcp/oauth.js +220 -307
- package/dist/services/mcp/oauth.js.map +1 -1
- package/dist/services/mcp/provider-registry.d.ts +1 -1
- package/dist/services/mcp/provider-registry.d.ts.map +1 -1
- package/dist/services/mcp/provider-registry.js +4 -6
- package/dist/services/mcp/provider-registry.js.map +1 -1
- package/dist/services/mcp/provider-registry.test.js +20 -8
- package/dist/services/mcp/provider-registry.test.js.map +1 -1
- package/dist/services/mcp/tool-discovery.d.ts +4 -0
- package/dist/services/mcp/tool-discovery.d.ts.map +1 -1
- package/dist/services/mcp/tool-discovery.js +29 -0
- package/dist/services/mcp/tool-discovery.js.map +1 -1
- package/dist/services/mcp/tool-discovery.test.js +34 -1
- package/dist/services/mcp/tool-discovery.test.js.map +1 -1
- package/dist/services/organization-export-readme.d.ts +0 -8
- package/dist/services/organization-export-readme.d.ts.map +1 -1
- package/dist/services/organization-export-readme.js +3 -43
- package/dist/services/organization-export-readme.js.map +1 -1
- package/dist/services/plugin-registry.d.ts +21 -21
- package/dist/services/postgres-json.d.ts +2 -0
- package/dist/services/postgres-json.d.ts.map +1 -0
- package/dist/services/postgres-json.js +33 -0
- package/dist/services/postgres-json.js.map +1 -0
- package/dist/services/postgres-json.test.d.ts +2 -0
- package/dist/services/postgres-json.test.d.ts.map +1 -0
- package/dist/services/postgres-json.test.js +25 -0
- package/dist/services/postgres-json.test.js.map +1 -0
- package/dist/services/run-events.d.ts.map +1 -1
- package/dist/services/run-events.js +6 -1
- package/dist/services/run-events.js.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.core.d.ts +2 -2
- package/dist/services/runtime-kernel/heartbeat.d.ts +6 -3
- package/dist/services/runtime-kernel/heartbeat.d.ts.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.execute.d.ts.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.execute.js +2 -0
- package/dist/services/runtime-kernel/heartbeat.execute.js.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.js.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.misc.d.ts +3 -0
- package/dist/services/runtime-kernel/heartbeat.misc.d.ts.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.misc.js +16 -4
- package/dist/services/runtime-kernel/heartbeat.misc.js.map +1 -1
- package/dist/services/runtime-kernel/heartbeat.terminal.d.ts +8 -9
- package/dist/services/runtime-kernel/heartbeat.terminal.d.ts.map +1 -1
- package/dist/services/side-chats.d.ts +9 -0
- package/dist/services/side-chats.d.ts.map +1 -1
- package/dist/services/side-chats.js +18 -4
- package/dist/services/side-chats.js.map +1 -1
- package/package.json +14 -13
- package/resources/bundled-skills/rudder-docs/evals/trigger-evals.json +1 -1
- package/resources/bundled-skills/rudder-docs/references/agent-creation.md +1 -3
- package/resources/bundled-skills/rudder-docs/references/api-reference.md +3 -12
- package/resources/bundled-skills/rudder-docs/references/cli-reference.md +1 -1
- package/resources/bundled-skills/rudder-docs/references/operating-practices.md +2 -2
- package/skills/rudder-docs/evals/trigger-evals.json +1 -1
- package/skills/rudder-docs/references/agent-creation.md +1 -3
- package/skills/rudder-docs/references/api-reference.md +3 -12
- package/skills/rudder-docs/references/cli-reference.md +1 -1
- package/skills/rudder-docs/references/operating-practices.md +2 -2
- package/ui-dist/assets/{LibraryLiveSurface-C8ECMVFT.js → LibraryLiveSurface-CnZxAEHp.js} +1 -1
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-BZHkBV8B.js → abnfDiagram-VRR7QNED-B208YmVN.js} +1 -1
- package/ui-dist/assets/{arc-DhnfBt9e.js → arc-_raxgt-X.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-BKHzH5qs.js → architectureDiagram-ZJ3FMSHR-y3eHT3Gk.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3--1g_r8lr.js → blockDiagram-677ZJIJ3-BT7LIBsS.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-CnZQa_O3.js → c4Diagram-LMCZKHZV-w0r6PEZM.js} +1 -1
- package/ui-dist/assets/channel-NqK-mAXf.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-Cx1ETWPc.js → chunk-2Q5K7J3B-C3fuIoNI.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-DwH6W0QD.js → chunk-32BRIVSS-DMb9Q2qh.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-DKjzajxX.js → chunk-5VM5RSS4-BqMkrxOv.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-DqPqTdiU.js → chunk-EX3LRPZG-D0uW7ZHY.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-BGZyFOPO.js → chunk-JWPE2WC7-_2Qhrxej.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-DWj-_Y-X.js → chunk-MOJQB5TN-Bx3r3XhP.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-Bp2OOi6q.js → chunk-RYQCIY6F-ryJ6ulQN.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-CxNGWU9-.js → chunk-V7JOEXUC-CpTtqgWd.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-rrwz8tGB.js → chunk-VR4S4FIN-C4qXyyxR.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-CuinF1_q.js → chunk-XXDRQBXY-CRPbq1d0.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CRSBnWpX.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CRSBnWpX.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-BuP7WwKx.js → cose-bilkent-JH36ORCC-DClTXY3x.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-Bdib4S1v.js → cynefin-VYW2F7L2-BqQy_6rq.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-DuSsXSha.js → cynefinDiagram-TSTJHNR4-C_5uIlLF.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-Igot42Fe.js → dagre-VKFMJZFB-CvzApokN.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-e8NWjImB.js → diagram-FQU43EPY-lsQoO58-.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-BMQV4r9I.js → diagram-G47NLZAW-DJSeMnXd.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-CPKOpfkM.js → diagram-NH7WQ7WH-Cfg6gXXN.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-C_fdlr3v.js → diagram-OA4YK3LP-DUS8ge-b.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-Cu7lfxa2.js → diagram-WEI45ONY-Cp-l5tVI.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-CN6-jt9d.js → ebnfDiagram-CCIWWBDH-BlRaFF_K.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-D2z6C-we.js → erDiagram-Q63AITRT-BZwqidAe.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-CQlS5jRI.js → flowDiagram-23GEKE2U-BsfwK51N.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-BuuHqPc8.js → ganttDiagram-NO4QXBWP-D7rDtE9-.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-zmgrxxBX.js → gitGraphDiagram-IHSO6WYX-SI7fggdm.js} +1 -1
- package/ui-dist/assets/{graph-BJvZTk9a.js → graph-jB2l85dN.js} +1 -1
- package/ui-dist/assets/{index-D0VRM_9h.js → index-3UJgpZuo.js} +1 -1
- package/ui-dist/assets/{index-CLLpIiBV.js → index-BEtrDYuf.js} +1 -1
- package/ui-dist/assets/{index-HrYgeHT8.js → index-BXIRLNEz.js} +1 -1
- package/ui-dist/assets/{index-BkG5PUIN.js → index-BzZl24GX.js} +1 -1
- package/ui-dist/assets/{index-Cc-ewLqn.js → index-C2YHCs23.js} +1 -1
- package/ui-dist/assets/index-CFGCM2jL.css +1 -0
- package/ui-dist/assets/{index-DwCuHGmD.js → index-CMGFrbv8.js} +1 -1
- package/ui-dist/assets/{index-BUkyKZIq.js → index-CTAmMJYG.js} +1 -1
- package/ui-dist/assets/{index-DshvyEC6.js → index-CZoL7L4x.js} +1 -1
- package/ui-dist/assets/{index-DyfYslLG.js → index-C_i-wGZX.js} +1 -1
- package/ui-dist/assets/{index-B2ZiqwcG.js → index-CkjUvGSq.js} +1 -1
- package/ui-dist/assets/{index-8kxaiDPU.js → index-CuPTWos7.js} +1 -1
- package/ui-dist/assets/{index-B0Kc4Reu.js → index-D8o_GAok.js} +1 -1
- package/ui-dist/assets/{index-B-_jOiYM.js → index-DMFCHg9M.js} +1 -1
- package/ui-dist/assets/{index-Be6_jEMJ.js → index-DR1WCr91.js} +1 -1
- package/ui-dist/assets/{index-CagHzH_y.js → index-DV8jlH7u.js} +1 -1
- package/ui-dist/assets/{index-BYiU3CbU.js → index-DaC9LwaF.js} +1 -1
- package/ui-dist/assets/{index--DAOoBdz.js → index-DrRmkklS.js} +539 -541
- package/ui-dist/assets/{index-BoJ3Lpc0.js → index-gRrC-1Ro.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-DcewEow-.js → infoDiagram-FWYZ7A6U-Dq_2Rg1m.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-DDA-hStd.js → ishikawaDiagram-FXEZZL3T-uyywLhOx.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-Di45AJjj.js → journeyDiagram-5HDEW3XC-BSdGAEe3.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-BSCbVwWj.js → kanban-definition-HUTT4EX6-BeiytV3M.js} +1 -1
- package/ui-dist/assets/{layout-pITZAjqg.js → layout-kKtSz6Lw.js} +1 -1
- package/ui-dist/assets/{linear-Cu3rtYRt.js → linear-BNg7ltC5.js} +1 -1
- package/ui-dist/assets/{map-DYuY604Q.js → map-rBM_jVzN.js} +1 -1
- package/ui-dist/assets/{mermaid.core-DDOr0JGp.js → mermaid.core-B0lX_I1S.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-D7XVVo_g.js → mindmap-definition-LN4V7U3C-6WrmM-3d.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-BC1GaeL3.js → pegDiagram-2B236MQR-BJ0lR6j8.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-dEClB4rW.js → pieDiagram-ENE6RG2P-Ch-KedEq.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-DYEEk2Me.js → quadrantDiagram-ABIIQ3AL-BLnrHtbN.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-DNsj-q9g.js → railroadDiagram-RFXS5EU6-u0KJZK8C.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-BmkJ6fzV.js → requirementDiagram-TGXJPOKE-C1MzHKp-.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-BsOkjZzG.js → sankeyDiagram-HTMAVEWB-UIufCGDd.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-Bi3Z-JjU.js → sequenceDiagram-DBY2YBRQ-Cv8Fb7zZ.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-BL5Nebl1.js → sizeCapture-X5ZJPWSS-9U-7wwO3.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-Cq_vKfyy.js → stateDiagram-2N3HPSRC-BEOjkPpv.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-BBO_VsOI.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-2J5KFUSB.js → swimlanes-5IMT3BWC-BEwruQnI.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-DjAl9cJv.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-D1ICgYtA.js → timeline-definition-FHXFAJF6-CfWC6EYo.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-D0Pe93oZ.js → vennDiagram-L72KCM5P-B2BPrj_n.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-B7cKDg_l.js → wardleyDiagram-EHGQE667-Cx2wmgRm.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-CpD2ZP52.js → xychartDiagram-FW5EYKEG-Due4dZhR.js} +1 -1
- package/ui-dist/index.html +2 -2
- package/dist/routes/org-chart-svg.d.ts +0 -25
- package/dist/routes/org-chart-svg.d.ts.map +0 -1
- package/dist/routes/org-chart-svg.js +0 -652
- package/dist/routes/org-chart-svg.js.map +0 -1
- package/ui-dist/assets/channel-DAg8UTDO.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-BDDhIQB_.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-BDDhIQB_.js +0 -1
- package/ui-dist/assets/index-BnZ6czsu.css +0 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-BUOXYIgQ.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BCURODlK.js +0 -8
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import { auth, OAuthError, OAuthErrorCode, } from "@modelcontextprotocol/client";
|
|
2
|
-
import { activityLog, instanceUserRoles, mcpConnections, mcpOAuthGrants, mcpOAuthSessions, organizationMemberships, organizationSecrets, organizationSecretVersions, } from "@rudderhq/db";
|
|
2
|
+
import { activityLog, agentCustomIntegrationBindings, instanceUserRoles, mcpConnections, mcpOAuthGrants, mcpOAuthSessions, organizationMemberships, organizationSecrets, organizationSecretVersions, } from "@rudderhq/db";
|
|
3
3
|
import { MCP_OAUTH_SESSION_TTL_MS, mcpOAuthCallbackSchema, mcpScopeSelectionSchema, } from "@rudderhq/shared";
|
|
4
4
|
import { and, asc, eq, gt, inArray, isNull, lte, sql, } from "drizzle-orm";
|
|
5
5
|
import { createHash, randomBytes, randomUUID, } from "node:crypto";
|
|
6
6
|
import { HttpError, notFound, unprocessable } from "../../errors.js";
|
|
7
7
|
import { getSecretProvider } from "../../secrets/provider-registry.js";
|
|
8
8
|
import { lockManagedMcpOAuthAuthorizer } from "./authorizer-lock.js";
|
|
9
|
-
import {
|
|
9
|
+
import { accessToken, defaultDiscoverProviderScope, defaultValidateProviderTools, MAX_SCOPE_OPTIONS, oauthActivityValues, oauthRevocationEndpoint, parseOAuthMaterial, safeScopeOption, tokenExpiry, tokenScopes } from "./oauth-helpers.js";
|
|
10
10
|
import { PersistentMcpOAuthClientProvider, resolveMcpOAuthRedirectUri, } from "./oauth-provider.js";
|
|
11
11
|
import { createSecureMcpFetch } from "./pinned-fetch.js";
|
|
12
12
|
import { MCP_CURATED_OAUTH_ORIGINS, MCP_PROVIDER_REGISTRY, resolveCuratedMcpEndpoint, } from "./provider-registry.js";
|
|
13
13
|
import { resolveMcpHttpTarget } from "./security-policy.js";
|
|
14
|
+
export { parseProviderWorkspaceScope } from "./oauth-helpers.js";
|
|
14
15
|
function createOAuthAuthorizationSnapshot(connection) {
|
|
15
16
|
if (connection.provider === "custom") {
|
|
16
17
|
throw unprocessable("Managed MCP OAuth only supports curated providers");
|
|
17
18
|
}
|
|
18
|
-
const serverUrl =
|
|
19
|
-
|
|
20
|
-
:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
externalScope: connection.externalScope,
|
|
24
|
-
}).href;
|
|
19
|
+
const serverUrl = resolveCuratedMcpEndpoint({
|
|
20
|
+
provider: connection.provider,
|
|
21
|
+
accessMode: connection.accessMode,
|
|
22
|
+
externalScope: connection.externalScope,
|
|
23
|
+
}).href;
|
|
25
24
|
return {
|
|
26
25
|
serverUrl,
|
|
27
26
|
...(connection.provider === "linear" && connection.accessMode === "read_only"
|
|
@@ -30,6 +29,13 @@ function createOAuthAuthorizationSnapshot(connection) {
|
|
|
30
29
|
accessMode: connection.accessMode,
|
|
31
30
|
};
|
|
32
31
|
}
|
|
32
|
+
function isSupabaseAccountUpgradeCandidate(connection) {
|
|
33
|
+
return connection.provider === "supabase"
|
|
34
|
+
&& connection.scopeMode === "account"
|
|
35
|
+
&& connection.externalScope === null
|
|
36
|
+
&& connection.canonicalState === "superseded"
|
|
37
|
+
&& connection.supersededByConnectionId !== null;
|
|
38
|
+
}
|
|
33
39
|
function readOAuthAuthorizationSnapshot(statusMetadata, connection) {
|
|
34
40
|
const value = statusMetadata.authorization;
|
|
35
41
|
if (isRecord(value)
|
|
@@ -118,237 +124,6 @@ function publicConnection(row) {
|
|
|
118
124
|
updatedAt: row.updatedAt,
|
|
119
125
|
};
|
|
120
126
|
}
|
|
121
|
-
function oauthActivityValues(input) {
|
|
122
|
-
return {
|
|
123
|
-
orgId: input.orgId,
|
|
124
|
-
actorType: input.actorUserId ? "user" : "system",
|
|
125
|
-
actorId: input.actorUserId ?? "system",
|
|
126
|
-
action: input.action,
|
|
127
|
-
entityType: "mcp_connection",
|
|
128
|
-
entityId: input.connectionId,
|
|
129
|
-
details: input.details,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
function tokenExpiry(tokens, now = new Date()) {
|
|
133
|
-
if (typeof tokens?.expires_in !== "number" || !Number.isFinite(tokens.expires_in))
|
|
134
|
-
return null;
|
|
135
|
-
return new Date(now.getTime() + Math.max(0, tokens.expires_in) * 1_000);
|
|
136
|
-
}
|
|
137
|
-
function tokenScopes(tokens) {
|
|
138
|
-
return typeof tokens?.scope === "string"
|
|
139
|
-
? Array.from(new Set(tokens.scope.split(/\s+/u).filter(Boolean)))
|
|
140
|
-
: [];
|
|
141
|
-
}
|
|
142
|
-
function accessToken(material) {
|
|
143
|
-
const value = material.tokens?.access_token;
|
|
144
|
-
if (!value)
|
|
145
|
-
throw unprocessable("Managed MCP OAuth credentials are unavailable");
|
|
146
|
-
return value;
|
|
147
|
-
}
|
|
148
|
-
function oauthRevocationEndpoint(material) {
|
|
149
|
-
const metadata = material?.discoveryState?.authorizationServerMetadata;
|
|
150
|
-
return isRecord(metadata) && typeof metadata.revocation_endpoint === "string"
|
|
151
|
-
? metadata.revocation_endpoint
|
|
152
|
-
: null;
|
|
153
|
-
}
|
|
154
|
-
const SAFE_SCOPE_METADATA_KEYS = new Set([
|
|
155
|
-
"region",
|
|
156
|
-
"scopeKind",
|
|
157
|
-
"status",
|
|
158
|
-
"workspaceName",
|
|
159
|
-
"workspace_name",
|
|
160
|
-
"organizationName",
|
|
161
|
-
"organization_name",
|
|
162
|
-
]);
|
|
163
|
-
const MAX_SCOPE_OPTIONS = 500;
|
|
164
|
-
const MAX_SCOPE_METADATA_BYTES = 4_096;
|
|
165
|
-
function safeScopeMetadata(value) {
|
|
166
|
-
const output = {};
|
|
167
|
-
for (const [key, raw] of Object.entries(value)) {
|
|
168
|
-
if (!SAFE_SCOPE_METADATA_KEYS.has(key))
|
|
169
|
-
continue;
|
|
170
|
-
const safeValue = typeof raw === "string"
|
|
171
|
-
? raw.slice(0, 512)
|
|
172
|
-
: typeof raw === "number" && Number.isFinite(raw)
|
|
173
|
-
? raw
|
|
174
|
-
: typeof raw === "boolean"
|
|
175
|
-
? raw
|
|
176
|
-
: undefined;
|
|
177
|
-
if (safeValue === undefined)
|
|
178
|
-
continue;
|
|
179
|
-
const candidate = { ...output, [key]: safeValue };
|
|
180
|
-
if (Buffer.byteLength(JSON.stringify(candidate), "utf8") > MAX_SCOPE_METADATA_BYTES) {
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
output[key] = safeValue;
|
|
184
|
-
}
|
|
185
|
-
return output;
|
|
186
|
-
}
|
|
187
|
-
function safeScopeOption(value) {
|
|
188
|
-
return {
|
|
189
|
-
id: value.id.trim().slice(0, 512),
|
|
190
|
-
displayName: value.displayName.trim().slice(0, 240),
|
|
191
|
-
metadata: isRecord(value.metadata) ? safeScopeMetadata(value.metadata) : {},
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
function sanitizeScopeOptions(values) {
|
|
195
|
-
const output = [];
|
|
196
|
-
const seen = new Set();
|
|
197
|
-
for (const value of values) {
|
|
198
|
-
const safe = safeScopeOption(value);
|
|
199
|
-
if (!safe.id || !safe.displayName || seen.has(safe.id))
|
|
200
|
-
continue;
|
|
201
|
-
seen.add(safe.id);
|
|
202
|
-
output.push(safe);
|
|
203
|
-
if (output.length === MAX_SCOPE_OPTIONS)
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
return output;
|
|
207
|
-
}
|
|
208
|
-
function parseToolJson(result) {
|
|
209
|
-
for (const content of result.content ?? []) {
|
|
210
|
-
if (content.type !== "text")
|
|
211
|
-
continue;
|
|
212
|
-
try {
|
|
213
|
-
return JSON.parse(content.text);
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
// Ignore non-JSON provider prose; onboarding never persists it.
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
function asProviderScope(value, keys) {
|
|
222
|
-
if (!isRecord(value))
|
|
223
|
-
return null;
|
|
224
|
-
const id = keys.id.map((key) => value[key])
|
|
225
|
-
.find((item) => typeof item === "string" && item.length > 0);
|
|
226
|
-
if (!id)
|
|
227
|
-
return null;
|
|
228
|
-
const displayName = keys.name.map((key) => value[key])
|
|
229
|
-
.find((item) => typeof item === "string" && item.length > 0) ?? id;
|
|
230
|
-
const metadata = Object.fromEntries(["region", "status", "workspaceName", "workspace_name", "organizationName"]
|
|
231
|
-
.flatMap((key) => value[key] === undefined ? [] : [[key, value[key]]]));
|
|
232
|
-
return safeScopeOption({ id, displayName, metadata });
|
|
233
|
-
}
|
|
234
|
-
function providerScopeContainer(provider, value) {
|
|
235
|
-
const definition = MCP_PROVIDER_REGISTRY[provider].scopeIdentity;
|
|
236
|
-
const candidates = [
|
|
237
|
-
...definition.containers.map((key) => value[key]),
|
|
238
|
-
];
|
|
239
|
-
const user = value.user;
|
|
240
|
-
if (provider === "linear" && isRecord(user)) {
|
|
241
|
-
candidates.push(...definition.containers.map((key) => user[key]));
|
|
242
|
-
}
|
|
243
|
-
const bot = value.bot;
|
|
244
|
-
if (provider === "notion" && isRecord(bot)) {
|
|
245
|
-
candidates.push(...definition.containers.map((key) => bot[key]));
|
|
246
|
-
}
|
|
247
|
-
const self = value.self;
|
|
248
|
-
if (provider === "notion" && isRecord(self)) {
|
|
249
|
-
candidates.push(...definition.containers.map((key) => self[key]));
|
|
250
|
-
}
|
|
251
|
-
return candidates.find(isRecord) ?? null;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Official identity tools return an actor plus an explicit workspace or
|
|
255
|
-
* organization. The actor id is never a valid Rudder connection scope.
|
|
256
|
-
*/
|
|
257
|
-
export function parseProviderWorkspaceScope(provider, value) {
|
|
258
|
-
if (!isRecord(value))
|
|
259
|
-
return null;
|
|
260
|
-
const container = providerScopeContainer(provider, value);
|
|
261
|
-
if (container) {
|
|
262
|
-
return asProviderScope(container, {
|
|
263
|
-
id: ["workspace_id", "workspaceId", "organization_id", "organizationId", "id"],
|
|
264
|
-
name: [
|
|
265
|
-
"workspace_name",
|
|
266
|
-
"workspaceName",
|
|
267
|
-
"organization_name",
|
|
268
|
-
"organizationName",
|
|
269
|
-
"name",
|
|
270
|
-
],
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
if (provider === "linear"
|
|
274
|
-
&& typeof value.id === "string"
|
|
275
|
-
&& value.id.length > 0
|
|
276
|
-
&& Array.isArray(value.teams)
|
|
277
|
-
&& value.teams.some((team) => isRecord(team) && typeof team.id === "string")) {
|
|
278
|
-
const authorizationName = typeof value.name === "string" && value.name.length > 0
|
|
279
|
-
? `${value.name}'s Linear authorization`
|
|
280
|
-
: "Linear authorization";
|
|
281
|
-
const opaqueSubjectId = createHash("sha256")
|
|
282
|
-
.update(`linear-authorization-subject:${value.id}`)
|
|
283
|
-
.digest("hex")
|
|
284
|
-
.slice(0, 24);
|
|
285
|
-
return safeScopeOption({
|
|
286
|
-
id: `linear-authorization-subject-${opaqueSubjectId}`,
|
|
287
|
-
displayName: authorizationName,
|
|
288
|
-
metadata: {
|
|
289
|
-
scopeKind: "authorization_subject",
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
const nested = provider === "notion" && isRecord(value.bot) ? value.bot : value;
|
|
294
|
-
return asProviderScope(nested, {
|
|
295
|
-
id: ["workspace_id", "workspaceId", "organization_id", "organizationId"],
|
|
296
|
-
name: [
|
|
297
|
-
"workspace_name",
|
|
298
|
-
"workspaceName",
|
|
299
|
-
"organization_name",
|
|
300
|
-
"organizationName",
|
|
301
|
-
],
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
async function defaultDiscoverProviderScope(input) {
|
|
305
|
-
const curatedOrigin = new URL(MCP_PROVIDER_REGISTRY[input.provider].endpoint).origin;
|
|
306
|
-
const client = await createManagedMcpClient({
|
|
307
|
-
transport: "streamable_http",
|
|
308
|
-
url: input.endpoint,
|
|
309
|
-
credentials: resolveMcpHttpCredentials({ bearerToken: accessToken(input.material) }),
|
|
310
|
-
network: {
|
|
311
|
-
allowedOrigins: input.allowlists.httpOrigins,
|
|
312
|
-
curatedOrigin,
|
|
313
|
-
lookup: input.dnsLookup,
|
|
314
|
-
},
|
|
315
|
-
startupTimeoutMs: input.connection.startupTimeoutMs,
|
|
316
|
-
toolTimeoutMs: input.connection.toolTimeoutMs,
|
|
317
|
-
});
|
|
318
|
-
try {
|
|
319
|
-
if (input.provider === "supabase") {
|
|
320
|
-
const parsed = parseToolJson(await client.callTool("list_projects", {}));
|
|
321
|
-
const rawProjects = Array.isArray(parsed)
|
|
322
|
-
? parsed
|
|
323
|
-
: isRecord(parsed) && Array.isArray(parsed.projects)
|
|
324
|
-
? parsed.projects
|
|
325
|
-
: [];
|
|
326
|
-
const options = rawProjects
|
|
327
|
-
.map((project) => asProviderScope(project, {
|
|
328
|
-
id: ["ref", "id", "project_ref"],
|
|
329
|
-
name: ["name", "display_name", "ref", "id"],
|
|
330
|
-
}))
|
|
331
|
-
.filter((option) => Boolean(option));
|
|
332
|
-
return { options };
|
|
333
|
-
}
|
|
334
|
-
const identity = MCP_PROVIDER_REGISTRY[input.provider].scopeIdentity;
|
|
335
|
-
if (!identity)
|
|
336
|
-
throw new Error("Provider did not define workspace identity discovery");
|
|
337
|
-
const tools = await client.discoverTools();
|
|
338
|
-
const identityTool = identity.toolNames.find((name) => (tools.some((tool) => tool.name === name)));
|
|
339
|
-
if (!identityTool) {
|
|
340
|
-
throw new Error("Provider did not expose a safe workspace identity tool");
|
|
341
|
-
}
|
|
342
|
-
const parsed = parseToolJson(await client.callTool(identityTool, identity.arguments));
|
|
343
|
-
const selected = parseProviderWorkspaceScope(input.provider, parsed);
|
|
344
|
-
if (!selected)
|
|
345
|
-
throw new Error("Provider workspace identity was invalid");
|
|
346
|
-
return { options: [], selected };
|
|
347
|
-
}
|
|
348
|
-
finally {
|
|
349
|
-
await client.close();
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
127
|
async function prepareOAuthSecret(connectionName, kind, material) {
|
|
353
128
|
const id = randomUUID();
|
|
354
129
|
const prepared = await getSecretProvider("local_encrypted").createVersion({
|
|
@@ -383,17 +158,6 @@ async function insertOAuthSecret(tx, input) {
|
|
|
383
158
|
createdByUserId: input.actorUserId ?? null,
|
|
384
159
|
});
|
|
385
160
|
}
|
|
386
|
-
function parseOAuthMaterial(value) {
|
|
387
|
-
try {
|
|
388
|
-
const parsed = JSON.parse(value);
|
|
389
|
-
if (!isRecord(parsed))
|
|
390
|
-
throw new Error("invalid");
|
|
391
|
-
return parsed;
|
|
392
|
-
}
|
|
393
|
-
catch {
|
|
394
|
-
throw unprocessable("Managed MCP OAuth credentials are unavailable");
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
161
|
export function managedMcpOAuthService(db, options) {
|
|
398
162
|
const grantRefreshSingleFlights = new Map();
|
|
399
163
|
const runAuth = options.oauthAuth ?? auth;
|
|
@@ -471,8 +235,8 @@ export function managedMcpOAuthService(db, options) {
|
|
|
471
235
|
.for("share")
|
|
472
236
|
.then((rows) => rows[0] ?? null));
|
|
473
237
|
}
|
|
474
|
-
async function requireUsableGrant(orgId, connectionId) {
|
|
475
|
-
const
|
|
238
|
+
async function requireUsableGrant(orgId, connectionId, executor) {
|
|
239
|
+
const validate = async (tx) => {
|
|
476
240
|
const connection = await tx.select().from(mcpConnections)
|
|
477
241
|
.where(and(eq(mcpConnections.orgId, orgId), eq(mcpConnections.id, connectionId)))
|
|
478
242
|
.for("update")
|
|
@@ -493,7 +257,10 @@ export function managedMcpOAuthService(db, options) {
|
|
|
493
257
|
return { kind: "invalid_authorizer" };
|
|
494
258
|
}
|
|
495
259
|
return { kind: "usable", grant };
|
|
496
|
-
}
|
|
260
|
+
};
|
|
261
|
+
const outcome = executor
|
|
262
|
+
? await validate(executor)
|
|
263
|
+
: await db.transaction(validate);
|
|
497
264
|
if (outcome.kind === "invalid_authorizer") {
|
|
498
265
|
throw unprocessable("Managed MCP OAuth authorization must be reconnected by an owner");
|
|
499
266
|
}
|
|
@@ -557,6 +324,25 @@ export function managedMcpOAuthService(db, options) {
|
|
|
557
324
|
dnsLookup: options.dnsLookup,
|
|
558
325
|
});
|
|
559
326
|
}
|
|
327
|
+
async function validateProviderTools(input) {
|
|
328
|
+
if (options.validateProviderTools) {
|
|
329
|
+
await options.validateProviderTools({
|
|
330
|
+
provider: input.connection.provider,
|
|
331
|
+
connection: input.connection,
|
|
332
|
+
material: input.material,
|
|
333
|
+
endpoint: input.endpoint,
|
|
334
|
+
});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
await defaultValidateProviderTools({
|
|
338
|
+
provider: input.connection.provider,
|
|
339
|
+
connection: input.connection,
|
|
340
|
+
material: input.material,
|
|
341
|
+
endpoint: input.endpoint,
|
|
342
|
+
allowlists: options.allowlists,
|
|
343
|
+
dnsLookup: options.dnsLookup,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
560
346
|
async function bestEffortRevokeMaterial(material, timeoutMs) {
|
|
561
347
|
const revocationEndpoint = oauthRevocationEndpoint(material);
|
|
562
348
|
const tokens = material?.tokens;
|
|
@@ -668,14 +454,24 @@ export function managedMcpOAuthService(db, options) {
|
|
|
668
454
|
}
|
|
669
455
|
return cleaned;
|
|
670
456
|
}
|
|
671
|
-
async function start(orgId, connectionId, actor) {
|
|
457
|
+
async function start(orgId, connectionId, actor, request = {}) {
|
|
672
458
|
await cleanupExpiredSessions(orgId);
|
|
673
459
|
const connection = await findConnection(orgId, connectionId);
|
|
674
460
|
assertCurated(connection);
|
|
461
|
+
if (connection.canonicalState !== "canonical"
|
|
462
|
+
&& !isSupabaseAccountUpgradeCandidate(connection)) {
|
|
463
|
+
throw unprocessable("Superseded MCP connections cannot start authorization");
|
|
464
|
+
}
|
|
675
465
|
if (options.deploymentMode === "authenticated"
|
|
676
466
|
&& !actor.userId) {
|
|
677
467
|
throw unprocessable("Managed MCP OAuth requires an authenticated authorizing user");
|
|
678
468
|
}
|
|
469
|
+
if (request.requestedAccessMode
|
|
470
|
+
&& (!["supabase", "linear"].includes(connection.provider)
|
|
471
|
+
|| connection.status !== "active"
|
|
472
|
+
|| !connection.enabled)) {
|
|
473
|
+
throw unprocessable("Managed MCP access changes require an active Supabase or Linear connection");
|
|
474
|
+
}
|
|
679
475
|
let redirectUri;
|
|
680
476
|
try {
|
|
681
477
|
redirectUri = resolveMcpOAuthRedirectUri({
|
|
@@ -697,7 +493,12 @@ export function managedMcpOAuthService(db, options) {
|
|
|
697
493
|
material = structuredClone(next);
|
|
698
494
|
},
|
|
699
495
|
});
|
|
700
|
-
const authorization = createOAuthAuthorizationSnapshot(
|
|
496
|
+
const authorization = createOAuthAuthorizationSnapshot({
|
|
497
|
+
...connection,
|
|
498
|
+
...(request.requestedAccessMode
|
|
499
|
+
? { accessMode: request.requestedAccessMode }
|
|
500
|
+
: {}),
|
|
501
|
+
});
|
|
701
502
|
const result = await runAuth(provider, {
|
|
702
503
|
serverUrl: authorization.serverUrl,
|
|
703
504
|
scope: authorization.scope,
|
|
@@ -726,27 +527,30 @@ export function managedMcpOAuthService(db, options) {
|
|
|
726
527
|
if (!locked)
|
|
727
528
|
throw notFound("MCP connection not found");
|
|
728
529
|
assertCurated(locked);
|
|
530
|
+
if (isSupabaseAccountUpgradeCandidate(locked)) {
|
|
531
|
+
const legacy = await tx.select().from(mcpConnections)
|
|
532
|
+
.where(and(eq(mcpConnections.orgId, orgId), eq(mcpConnections.id, locked.supersededByConnectionId), eq(mcpConnections.provider, "supabase"), eq(mcpConnections.scopeMode, "legacy_project"), eq(mcpConnections.canonicalState, "canonical")))
|
|
533
|
+
.for("share")
|
|
534
|
+
.then((rows) => rows[0] ?? null);
|
|
535
|
+
if (!legacy) {
|
|
536
|
+
throw unprocessable("Supabase account upgrade is no longer available");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
729
539
|
if (locked.lifecycleRevision !== connection.lifecycleRevision) {
|
|
730
540
|
throw unprocessable("Managed MCP OAuth connection changed; start authorization again");
|
|
731
541
|
}
|
|
542
|
+
if (request.requestedAccessMode
|
|
543
|
+
&& locked.accessMode !== connection.accessMode) {
|
|
544
|
+
throw unprocessable("Managed MCP access changed; start authorization again");
|
|
545
|
+
}
|
|
732
546
|
const priorGrant = await tx.select().from(mcpOAuthGrants)
|
|
733
547
|
.where(and(eq(mcpOAuthGrants.orgId, orgId), eq(mcpOAuthGrants.connectionId, connectionId)))
|
|
734
548
|
.for("update")
|
|
735
549
|
.then((rows) => rows[0] ?? null);
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
credentialSecretId: null,
|
|
741
|
-
refreshLeaseNonce: null,
|
|
742
|
-
refreshLeaseExpiresAt: null,
|
|
743
|
-
updatedAt: now,
|
|
744
|
-
}).where(eq(mcpOAuthGrants.id, priorGrant.id));
|
|
745
|
-
if (priorGrant.credentialSecretId) {
|
|
746
|
-
await tx.delete(organizationSecrets)
|
|
747
|
-
.where(eq(organizationSecrets.id, priorGrant.credentialSecretId));
|
|
748
|
-
}
|
|
749
|
-
}
|
|
550
|
+
const isCredentialReplacement = priorGrant?.status === "active"
|
|
551
|
+
&& Boolean(priorGrant.credentialSecretId)
|
|
552
|
+
&& locked.status === "active"
|
|
553
|
+
&& locked.enabled;
|
|
750
554
|
const replacedSessions = await tx.select({
|
|
751
555
|
id: mcpOAuthSessions.id,
|
|
752
556
|
credentialSecretId: mcpOAuthSessions.credentialSecretId,
|
|
@@ -779,11 +583,17 @@ export function managedMcpOAuthService(db, options) {
|
|
|
779
583
|
credentialSecretId: sessionSecret.id,
|
|
780
584
|
redirectUri,
|
|
781
585
|
status: "authorizing",
|
|
782
|
-
statusMetadata: {
|
|
586
|
+
statusMetadata: {
|
|
587
|
+
authorization,
|
|
588
|
+
reauthorization: isCredentialReplacement,
|
|
589
|
+
...(request.requestedAccessMode
|
|
590
|
+
? { pendingAccessMode: request.requestedAccessMode }
|
|
591
|
+
: {}),
|
|
592
|
+
},
|
|
783
593
|
expiresAt,
|
|
784
594
|
});
|
|
785
595
|
await tx.update(mcpConnections).set({
|
|
786
|
-
status: "authorizing",
|
|
596
|
+
status: isCredentialReplacement ? "active" : "authorizing",
|
|
787
597
|
enabled: true,
|
|
788
598
|
disabledAt: null,
|
|
789
599
|
revokedAt: null,
|
|
@@ -822,7 +632,8 @@ export function managedMcpOAuthService(db, options) {
|
|
|
822
632
|
if (!connection)
|
|
823
633
|
return null;
|
|
824
634
|
assertCurated(connection);
|
|
825
|
-
if (connection.
|
|
635
|
+
if (connection.canonicalState !== "canonical"
|
|
636
|
+
&& !isSupabaseAccountUpgradeCandidate(connection))
|
|
826
637
|
return null;
|
|
827
638
|
const lockedSession = await tx.select().from(mcpOAuthSessions)
|
|
828
639
|
.where(and(eq(mcpOAuthSessions.id, session.id), eq(mcpOAuthSessions.stateHash, stateHash)))
|
|
@@ -831,6 +642,11 @@ export function managedMcpOAuthService(db, options) {
|
|
|
831
642
|
if (!lockedSession || lockedSession.status !== "authorizing" || lockedSession.consumedAt) {
|
|
832
643
|
return null;
|
|
833
644
|
}
|
|
645
|
+
const isCredentialReplacement = lockedSession.statusMetadata.reauthorization === true;
|
|
646
|
+
if (connection.status !== "authorizing"
|
|
647
|
+
&& !(isCredentialReplacement && connection.status === "active" && connection.enabled)) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
834
650
|
if (lockedSession.expiresAt <= now) {
|
|
835
651
|
await tx.update(mcpOAuthSessions).set({
|
|
836
652
|
consumedAt: now,
|
|
@@ -892,12 +708,29 @@ export function managedMcpOAuthService(db, options) {
|
|
|
892
708
|
.where(and(eq(mcpConnections.orgId, callbackContext.session.orgId), eq(mcpConnections.id, callbackContext.connection.id)))
|
|
893
709
|
.for("update")
|
|
894
710
|
.then((rows) => rows[0] ?? null);
|
|
711
|
+
const isCredentialReplacement = callbackContext.session.statusMetadata.reauthorization === true
|
|
712
|
+
&& locked?.status === "active"
|
|
713
|
+
&& locked.enabled;
|
|
895
714
|
if (!locked
|
|
896
|
-
|| locked.status !== "authorizing"
|
|
715
|
+
|| (locked.status !== "authorizing"
|
|
716
|
+
&& !isCredentialReplacement)
|
|
897
717
|
|| locked.lifecycleRevision !== callbackContext.connectionLifecycleRevision) {
|
|
898
718
|
return;
|
|
899
719
|
}
|
|
900
720
|
const now = new Date();
|
|
721
|
+
if (isCredentialReplacement) {
|
|
722
|
+
await tx.insert(activityLog).values(oauthActivityValues({
|
|
723
|
+
orgId: callbackContext.session.orgId,
|
|
724
|
+
connectionId: locked.id,
|
|
725
|
+
action: inputFailure.action,
|
|
726
|
+
actorUserId: callbackContext.session.authorizingUserId,
|
|
727
|
+
details: {
|
|
728
|
+
reason: inputFailure.reason,
|
|
729
|
+
existingGrantPreserved: true,
|
|
730
|
+
},
|
|
731
|
+
}));
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
901
734
|
await tx.update(mcpConnections).set({
|
|
902
735
|
status: inputFailure.status,
|
|
903
736
|
...(inputFailure.status === "needs_reauth"
|
|
@@ -932,8 +765,10 @@ export function managedMcpOAuthService(db, options) {
|
|
|
932
765
|
throw unprocessable("Managed MCP OAuth authorization was not completed");
|
|
933
766
|
}
|
|
934
767
|
const authorization = readOAuthAuthorizationSnapshot(consumed.session.statusMetadata, consumed.connection);
|
|
935
|
-
|
|
936
|
-
&&
|
|
768
|
+
const stagedAccessMode = consumed.session.statusMetadata.reauthorization === true
|
|
769
|
+
&& consumed.session.statusMetadata.pendingAccessMode === authorization.accessMode;
|
|
770
|
+
if (authorization.accessMode !== consumed.connection.accessMode
|
|
771
|
+
&& !stagedAccessMode) {
|
|
937
772
|
await finishFailure({
|
|
938
773
|
status: "needs_reauth",
|
|
939
774
|
action: "mcp_oauth.authorization_failed",
|
|
@@ -981,11 +816,13 @@ export function managedMcpOAuthService(db, options) {
|
|
|
981
816
|
if (authResult !== "AUTHORIZED" || !grantMaterial.tokens?.access_token) {
|
|
982
817
|
throw unprocessable("Managed MCP OAuth token exchange failed");
|
|
983
818
|
}
|
|
984
|
-
scope =
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
819
|
+
scope = consumed.connection.provider === "supabase"
|
|
820
|
+
? { options: [] }
|
|
821
|
+
: await discoverScope({
|
|
822
|
+
connection: consumed.connection,
|
|
823
|
+
material: grantMaterial,
|
|
824
|
+
endpoint: authorization.serverUrl,
|
|
825
|
+
});
|
|
989
826
|
}
|
|
990
827
|
catch (error) {
|
|
991
828
|
await finishUnpersistedGrantFailure({
|
|
@@ -999,23 +836,31 @@ export function managedMcpOAuthService(db, options) {
|
|
|
999
836
|
throw error;
|
|
1000
837
|
throw unprocessable("Managed MCP OAuth authorization could not be completed");
|
|
1001
838
|
}
|
|
1002
|
-
const safeOptions = sanitizeScopeOptions(scope.options);
|
|
1003
839
|
const selected = scope.selected ? safeScopeOption(scope.selected) : undefined;
|
|
1004
|
-
if (consumed.connection.provider
|
|
840
|
+
if (consumed.connection.provider !== "supabase" && !selected) {
|
|
1005
841
|
await finishUnpersistedGrantFailure({
|
|
1006
842
|
status: "error",
|
|
1007
843
|
action: "mcp_oauth.authorization_failed",
|
|
1008
|
-
reason: "
|
|
844
|
+
reason: "workspace_identity_unavailable",
|
|
1009
845
|
});
|
|
1010
|
-
throw unprocessable("
|
|
846
|
+
throw unprocessable("Managed MCP OAuth did not identify a provider workspace");
|
|
1011
847
|
}
|
|
1012
|
-
|
|
848
|
+
try {
|
|
849
|
+
await validateProviderTools({
|
|
850
|
+
connection: consumed.connection,
|
|
851
|
+
material: grantMaterial,
|
|
852
|
+
endpoint: authorization.serverUrl,
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
catch (error) {
|
|
1013
856
|
await finishUnpersistedGrantFailure({
|
|
1014
|
-
status: "error",
|
|
857
|
+
status: isInvalidGrantOAuthError(error) ? "needs_reauth" : "error",
|
|
1015
858
|
action: "mcp_oauth.authorization_failed",
|
|
1016
|
-
reason: "
|
|
859
|
+
reason: "tool_discovery_failed",
|
|
1017
860
|
});
|
|
1018
|
-
|
|
861
|
+
if (error instanceof HttpError)
|
|
862
|
+
throw error;
|
|
863
|
+
throw unprocessable("Managed MCP OAuth tool discovery could not be completed");
|
|
1019
864
|
}
|
|
1020
865
|
const outcome = await (async () => {
|
|
1021
866
|
try {
|
|
@@ -1028,10 +873,23 @@ export function managedMcpOAuthService(db, options) {
|
|
|
1028
873
|
.for("update")
|
|
1029
874
|
.then((rows) => rows[0] ?? null);
|
|
1030
875
|
if (!connection
|
|
1031
|
-
|| connection.status !== "authorizing"
|
|
876
|
+
|| (connection.status !== "authorizing"
|
|
877
|
+
&& !(consumed.session.statusMetadata.reauthorization === true
|
|
878
|
+
&& connection.status === "active"
|
|
879
|
+
&& connection.enabled))
|
|
1032
880
|
|| connection.lifecycleRevision !== consumed.connectionLifecycleRevision) {
|
|
1033
881
|
return null;
|
|
1034
882
|
}
|
|
883
|
+
const legacyUpgradeConnection = isSupabaseAccountUpgradeCandidate(connection)
|
|
884
|
+
? await tx.select().from(mcpConnections)
|
|
885
|
+
.where(and(eq(mcpConnections.orgId, connection.orgId), eq(mcpConnections.id, connection.supersededByConnectionId), eq(mcpConnections.provider, "supabase"), eq(mcpConnections.scopeMode, "legacy_project"), eq(mcpConnections.canonicalState, "canonical")))
|
|
886
|
+
.for("update")
|
|
887
|
+
.then((rows) => rows[0] ?? null)
|
|
888
|
+
: null;
|
|
889
|
+
if (isSupabaseAccountUpgradeCandidate(connection)
|
|
890
|
+
&& !legacyUpgradeConnection) {
|
|
891
|
+
return null;
|
|
892
|
+
}
|
|
1035
893
|
const stillAuthorized = options.deploymentMode === "local_trusted"
|
|
1036
894
|
&& !consumed.session.authorizingUserId
|
|
1037
895
|
? true
|
|
@@ -1046,19 +904,27 @@ export function managedMcpOAuthService(db, options) {
|
|
|
1046
904
|
.for("share")
|
|
1047
905
|
.then((rows) => rows[0] ?? null));
|
|
1048
906
|
if (!stillAuthorized) {
|
|
1049
|
-
|
|
1050
|
-
status
|
|
1051
|
-
enabled
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
907
|
+
const existingGrantPreserved = consumed.session.statusMetadata.reauthorization === true
|
|
908
|
+
&& connection.status === "active"
|
|
909
|
+
&& connection.enabled;
|
|
910
|
+
if (!existingGrantPreserved) {
|
|
911
|
+
await tx.update(mcpConnections).set({
|
|
912
|
+
status: "needs_reauth",
|
|
913
|
+
enabled: false,
|
|
914
|
+
disabledAt: now,
|
|
915
|
+
lifecycleRevision: connection.lifecycleRevision + 1,
|
|
916
|
+
updatedAt: now,
|
|
917
|
+
}).where(eq(mcpConnections.id, connection.id));
|
|
918
|
+
}
|
|
1056
919
|
await tx.insert(activityLog).values(oauthActivityValues({
|
|
1057
920
|
orgId: consumed.session.orgId,
|
|
1058
921
|
connectionId: connection.id,
|
|
1059
922
|
action: "mcp_oauth.authorization_rejected",
|
|
1060
923
|
actorUserId: consumed.session.authorizingUserId,
|
|
1061
|
-
details: {
|
|
924
|
+
details: {
|
|
925
|
+
reason: "authorizer_no_longer_authorized",
|
|
926
|
+
existingGrantPreserved,
|
|
927
|
+
},
|
|
1062
928
|
}));
|
|
1063
929
|
return { kind: "reauth" };
|
|
1064
930
|
}
|
|
@@ -1080,9 +946,6 @@ export function managedMcpOAuthService(db, options) {
|
|
|
1080
946
|
status: "active",
|
|
1081
947
|
statusMetadata: {
|
|
1082
948
|
authorization,
|
|
1083
|
-
...(connection.provider === "supabase"
|
|
1084
|
-
? { scopeOptions: safeOptions }
|
|
1085
|
-
: {}),
|
|
1086
949
|
},
|
|
1087
950
|
expiresAt: tokenExpiry(grantMaterial.tokens, now),
|
|
1088
951
|
lastRefreshedAt: now,
|
|
@@ -1106,16 +969,62 @@ export function managedMcpOAuthService(db, options) {
|
|
|
1106
969
|
await tx.delete(organizationSecrets)
|
|
1107
970
|
.where(eq(organizationSecrets.id, existingGrant.credentialSecretId));
|
|
1108
971
|
}
|
|
1109
|
-
const status =
|
|
972
|
+
const status = "active";
|
|
973
|
+
if (legacyUpgradeConnection) {
|
|
974
|
+
const legacyGrant = await tx.select().from(mcpOAuthGrants)
|
|
975
|
+
.where(and(eq(mcpOAuthGrants.orgId, connection.orgId), eq(mcpOAuthGrants.connectionId, legacyUpgradeConnection.id)))
|
|
976
|
+
.for("update")
|
|
977
|
+
.then((rows) => rows[0] ?? null);
|
|
978
|
+
await tx.update(mcpConnections).set({
|
|
979
|
+
canonicalState: "superseded",
|
|
980
|
+
supersededByConnectionId: connection.id,
|
|
981
|
+
status: "revoked",
|
|
982
|
+
enabled: false,
|
|
983
|
+
revokedAt: now,
|
|
984
|
+
lifecycleRevision: legacyUpgradeConnection.lifecycleRevision + 1,
|
|
985
|
+
revision: legacyUpgradeConnection.revision + 1,
|
|
986
|
+
updatedAt: now,
|
|
987
|
+
}).where(eq(mcpConnections.id, legacyUpgradeConnection.id));
|
|
988
|
+
await tx.update(agentCustomIntegrationBindings).set({
|
|
989
|
+
accessMode: "none",
|
|
990
|
+
policyRevision: sql `${agentCustomIntegrationBindings.policyRevision} + 1`,
|
|
991
|
+
updatedAt: now,
|
|
992
|
+
}).where(and(eq(agentCustomIntegrationBindings.orgId, connection.orgId), eq(agentCustomIntegrationBindings.connectionId, legacyUpgradeConnection.id)));
|
|
993
|
+
if (legacyGrant) {
|
|
994
|
+
await tx.update(mcpOAuthGrants).set({
|
|
995
|
+
status: "revoked",
|
|
996
|
+
credentialSecretId: null,
|
|
997
|
+
revokedAt: now,
|
|
998
|
+
updatedAt: now,
|
|
999
|
+
}).where(eq(mcpOAuthGrants.id, legacyGrant.id));
|
|
1000
|
+
if (legacyGrant.credentialSecretId) {
|
|
1001
|
+
await tx.delete(organizationSecrets)
|
|
1002
|
+
.where(eq(organizationSecrets.id, legacyGrant.credentialSecretId));
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1110
1006
|
await tx.update(mcpConnections).set({
|
|
1111
1007
|
status,
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1008
|
+
accessMode: stagedAccessMode
|
|
1009
|
+
? authorization.accessMode
|
|
1010
|
+
: connection.accessMode,
|
|
1011
|
+
externalScope: connection.provider === "supabase"
|
|
1012
|
+
? legacyUpgradeConnection || connection.scopeMode === "account"
|
|
1013
|
+
? null
|
|
1014
|
+
: connection.externalScope
|
|
1015
|
+
: selected?.id ?? null,
|
|
1016
|
+
scopeMode: legacyUpgradeConnection ? "account" : connection.scopeMode,
|
|
1017
|
+
safeConfig: legacyUpgradeConnection ? {} : connection.safeConfig,
|
|
1018
|
+
canonicalState: legacyUpgradeConnection
|
|
1019
|
+
? "canonical"
|
|
1020
|
+
: connection.canonicalState,
|
|
1021
|
+
supersededByConnectionId: legacyUpgradeConnection
|
|
1022
|
+
? null
|
|
1023
|
+
: connection.supersededByConnectionId,
|
|
1116
1024
|
enabled: true,
|
|
1117
1025
|
activatedAt: status === "active" ? connection.activatedAt ?? now : null,
|
|
1118
1026
|
lifecycleRevision: connection.lifecycleRevision + 1,
|
|
1027
|
+
revision: connection.revision + 1,
|
|
1119
1028
|
updatedAt: now,
|
|
1120
1029
|
}).where(eq(mcpConnections.id, connection.id));
|
|
1121
1030
|
await tx.insert(activityLog).values(oauthActivityValues({
|
|
@@ -1158,7 +1067,11 @@ export function managedMcpOAuthService(db, options) {
|
|
|
1158
1067
|
throw unprocessable("Managed MCP OAuth must be reauthorized by an owner");
|
|
1159
1068
|
}
|
|
1160
1069
|
if (outcome.status === "active" && options.refreshConnectionTools) {
|
|
1161
|
-
|
|
1070
|
+
// The replacement grant was already validated before the atomic swap.
|
|
1071
|
+
// A transient second discovery must not turn a successfully swapped
|
|
1072
|
+
// connection into an outage. Keep the last known-safe catalog and let a
|
|
1073
|
+
// later refresh reconcile it.
|
|
1074
|
+
await options.refreshConnectionTools(outcome.orgId, outcome.connectionId, { userId: outcome.authorizingUserId, agentId: null }).catch(() => undefined);
|
|
1162
1075
|
}
|
|
1163
1076
|
return { connectionId: outcome.connectionId, status: outcome.status };
|
|
1164
1077
|
}
|