@hotmeshio/long-tail 0.4.18 → 0.4.20
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/README.md +0 -2
- package/build/api/auth-sso.d.ts +12 -0
- package/build/api/auth-sso.js +54 -0
- package/build/api/escalations/bulk.js +2 -2
- package/build/api/escalations/claim.js +3 -13
- package/build/api/escalations/create.js +3 -2
- package/build/api/escalations/helpers.d.ts +1 -0
- package/build/api/escalations/helpers.js +12 -9
- package/build/api/escalations/list.d.ts +1 -0
- package/build/api/escalations/list.js +1 -0
- package/build/api/escalations/metadata.d.ts +7 -24
- package/build/api/escalations/metadata.js +31 -65
- package/build/api/escalations/single.js +3 -2
- package/build/api/settings.js +5 -0
- package/build/api/topics.d.ts +9 -0
- package/build/api/topics.js +31 -2
- package/build/lib/events/index.d.ts +1 -0
- package/build/lib/events/index.js +4 -0
- package/build/lib/events/publish.d.ts +12 -9
- package/build/lib/events/publish.js +27 -17
- package/build/modules/auth.d.ts +7 -0
- package/build/modules/auth.js +104 -2
- package/build/modules/sso.d.ts +6 -0
- package/build/modules/sso.js +20 -0
- package/build/routes/auth-sso.d.ts +2 -0
- package/build/routes/auth-sso.js +51 -0
- package/build/routes/bot-accounts.js +1 -1
- package/build/routes/controlplane.js +6 -6
- package/build/routes/escalations/list.js +1 -0
- package/build/routes/index.js +2 -0
- package/build/routes/mcp-endpoint.d.ts +17 -0
- package/build/routes/mcp-endpoint.js +70 -0
- package/build/routes/roles.js +5 -5
- package/build/routes/topics.js +2 -0
- package/build/routes/users.js +31 -5
- package/build/sdk/index.d.ts +1 -0
- package/build/services/agent/input-mapper.js +17 -1
- package/build/services/escalation/crud.d.ts +17 -1
- package/build/services/escalation/crud.js +62 -13
- package/build/services/escalation/queries.d.ts +1 -0
- package/build/services/escalation/queries.js +7 -0
- package/build/services/escalation/sql.d.ts +14 -5
- package/build/services/escalation/sql.js +53 -16
- package/build/services/mcp/exposure.d.ts +15 -0
- package/build/services/mcp/exposure.js +18 -0
- package/build/services/mcp/external-server.d.ts +15 -0
- package/build/services/mcp/external-server.js +125 -0
- package/build/services/mcp/seed-service-account.d.ts +11 -0
- package/build/services/mcp/seed-service-account.js +77 -0
- package/build/services/role/index.d.ts +1 -1
- package/build/services/role/index.js +2 -2
- package/build/services/topics/system-topics.js +29 -25
- package/build/services/user/index.d.ts +1 -1
- package/build/services/user/index.js +3 -1
- package/build/services/user/rbac.d.ts +16 -0
- package/build/services/user/rbac.js +31 -0
- package/build/services/user/sso-provision.d.ts +19 -0
- package/build/services/user/sso-provision.js +62 -0
- package/build/services/workflow-invocation.js +5 -3
- package/build/start/config.js +6 -0
- package/build/start/server.js +2 -0
- package/build/start/workers.js +15 -0
- package/build/system/index.js +53 -35
- package/build/system/mcp-servers/admin/agent-subscriptions.d.ts +5 -0
- package/build/system/mcp-servers/admin/agent-subscriptions.js +78 -0
- package/build/system/mcp-servers/admin/agents.d.ts +5 -0
- package/build/system/mcp-servers/admin/agents.js +103 -0
- package/build/system/mcp-servers/admin/bot-accounts.d.ts +5 -0
- package/build/system/mcp-servers/admin/bot-accounts.js +126 -0
- package/build/system/mcp-servers/admin/controlplane.d.ts +5 -0
- package/build/system/mcp-servers/admin/controlplane.js +107 -0
- package/build/system/mcp-servers/admin/escalations.js +88 -0
- package/build/system/mcp-servers/admin/exports.d.ts +5 -0
- package/build/system/mcp-servers/admin/exports.js +101 -0
- package/build/system/mcp-servers/admin/index.d.ts +16 -8
- package/build/system/mcp-servers/admin/index.js +36 -21
- package/build/system/mcp-servers/admin/pipelines.d.ts +5 -0
- package/build/system/mcp-servers/admin/pipelines.js +96 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +614 -6
- package/build/system/mcp-servers/admin/schemas.js +239 -1
- package/build/system/mcp-servers/admin/settings.d.ts +5 -0
- package/build/system/mcp-servers/admin/settings.js +53 -0
- package/build/system/mcp-servers/admin/topics.d.ts +5 -0
- package/build/system/mcp-servers/admin/topics.js +101 -0
- package/build/system/seed/tool-manifests-admin.d.ts +5077 -188
- package/build/system/seed/tool-manifests-admin.js +79 -30
- package/build/system/seed/tool-manifests-data.d.ts +20 -0
- package/build/system/seed/tool-manifests-data.js +24 -6
- package/build/system/seed/tool-manifests-escalation.d.ts +5 -0
- package/build/system/seed/tool-manifests-escalation.js +5 -0
- package/build/system/seed/tool-manifests-events.d.ts +4 -0
- package/build/system/seed/tool-manifests-events.js +4 -0
- package/build/system/seed/tool-manifests-knowledge.d.ts +6 -0
- package/build/system/seed/tool-manifests-knowledge.js +7 -0
- package/build/system/seed/tool-manifests-workflows.d.ts +8 -0
- package/build/system/seed/tool-manifests-workflows.js +8 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/auth.d.ts +71 -0
- package/build/types/events.d.ts +17 -6
- package/build/types/index.d.ts +1 -1
- package/build/types/startup.d.ts +22 -1
- package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js → AdminDashboard-BwUGcCxQ.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js.map → AdminDashboard-BwUGcCxQ.js.map} +1 -1
- package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js +16 -0
- package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js.map +1 -0
- package/dashboard/dist/assets/{AgentDetailPage-3mZA7SOb.js → AgentDetailPage-XJpl7wfJ.js} +4 -4
- package/dashboard/dist/assets/AgentDetailPage-XJpl7wfJ.js.map +1 -0
- package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js → AgentsPage-CGpVG6r8.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js.map → AgentsPage-CGpVG6r8.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-DR1e0TQZ.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-CA9x9o5s.js.map → AvailableEscalationsPage-DR1e0TQZ.js.map} +1 -1
- package/dashboard/dist/assets/BotPicker-BKtjl6IL.js +2 -0
- package/dashboard/dist/assets/{BotPicker-BQp_Vs73.js.map → BotPicker-BKtjl6IL.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js → CapabilitiesPage-kCB8fyOj.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js.map → CapabilitiesPage-kCB8fyOj.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js → CollapsibleSection-C3tU61hB.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js.map → CollapsibleSection-C3tU61hB.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js → CredentialsPage-Dt4nJs_B.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js.map → CredentialsPage-Dt4nJs_B.js.map} +1 -1
- package/dashboard/dist/assets/CronLabel-BdE6mHyA.js +2 -0
- package/dashboard/dist/assets/CronLabel-BdE6mHyA.js.map +1 -0
- package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js → CustomDurationPicker-B_Yxfb-u.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js.map → CustomDurationPicker-B_Yxfb-u.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-BkfRoUcm.js → DropZone-CptiQ0wc.js} +2 -2
- package/dashboard/dist/assets/{DropZone-BkfRoUcm.js.map → DropZone-CptiQ0wc.js.map} +1 -1
- package/dashboard/dist/assets/ElapsedCell-tcGx5PFI.js +2 -0
- package/dashboard/dist/assets/{ElapsedCell-BPYm8RA7.js.map → ElapsedCell-tcGx5PFI.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js → EscalationsOverview-1KO5dXzk.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js.map → EscalationsOverview-1KO5dXzk.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DSDzJMer.js → EventTable-DnpsQ6Ew.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DSDzJMer.js.map → EventTable-DnpsQ6Ew.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +2 -0
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +1 -0
- package/dashboard/dist/assets/ListToolbar-jrVba7QN.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-DEef1_-T.js.map → ListToolbar-jrVba7QN.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js → McpOverview-BzyxJyc9.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js.map → McpOverview-BzyxJyc9.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js → McpQueryDetailPage-DXNseeKl.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js.map → McpQueryDetailPage-DXNseeKl.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-D14466yi.js → McpQueryPage-WZfTY43_.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-D14466yi.js.map → McpQueryPage-WZfTY43_.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +1 -0
- package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-aZg057y3.js.map → McpRunsPage-SXyiwc0d.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js +2 -0
- package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js.map +1 -0
- package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js → PageHeader-BuJpMxyu.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js.map → PageHeader-BuJpMxyu.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js → PageHeaderWithStats-yD_PTbOl.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js.map → PageHeaderWithStats-yD_PTbOl.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js → ProcessDetailPage-DYIfvWyc.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js.map → ProcessDetailPage-DYIfvWyc.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js → ProcessesListPage-DR1RGaMl.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js.map → ProcessesListPage-DR1RGaMl.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-BC54Vn-U.js → RolePill-SasQKc_B.js} +2 -2
- package/dashboard/dist/assets/{RolePill-BC54Vn-U.js.map → RolePill-SasQKc_B.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js → RolesPage-pMERxj15.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js.map → RolesPage-pMERxj15.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js → RunAsSelector-B-ksMoEj.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js.map → RunAsSelector-B-ksMoEj.js.map} +1 -1
- package/dashboard/dist/assets/ServerName-CHspudaC.js +2 -0
- package/dashboard/dist/assets/{ServerName-Q6okiv4f.js.map → ServerName-CHspudaC.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js → SwimlaneTimeline-Cr_K5qpu.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js.map → SwimlaneTimeline-Cr_K5qpu.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-D6l1SPWd.js → TagInput-DvF3j8MA.js} +2 -2
- package/dashboard/dist/assets/{TagInput-D6l1SPWd.js.map → TagInput-DvF3j8MA.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js → TaskDetailPage-BO5p7AEe.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js.map → TaskDetailPage-BO5p7AEe.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js → TaskQueuePill-BCQrS2oK.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js.map → TaskQueuePill-BCQrS2oK.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js → TasksListPage-BRg-uFtF.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js.map → TasksListPage-BRg-uFtF.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js → TimeAgo-BSzN6rAH.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js.map → TimeAgo-BSzN6rAH.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js → TimestampCell-DL6zMNEQ.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js.map → TimestampCell-DL6zMNEQ.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-HcRTggHo.js → ToolPill-1aTqYtzp.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-HcRTggHo.js.map → ToolPill-1aTqYtzp.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js → ToolTestPanel-fLzNp79U.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js.map → ToolTestPanel-fLzNp79U.js.map} +1 -1
- package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js +9 -0
- package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js.map +1 -0
- package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js → TopicsPage-B3Aa8Haz.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js.map → TopicsPage-B3Aa8Haz.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DX7IBjFn.js → UserName-BjHIJWgh.js} +2 -2
- package/dashboard/dist/assets/{UserName-DX7IBjFn.js.map → UserName-BjHIJWgh.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js → WorkflowExecutionPage-BQ7AYlQA.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js.map → WorkflowExecutionPage-BQ7AYlQA.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js → WorkflowPill-Z-zHRKOK.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js.map → WorkflowPill-Z-zHRKOK.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +2 -0
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js → WorkflowsOverview-B4DUcVxs.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js.map → WorkflowsOverview-B4DUcVxs.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js → YamlWorkflowsPage-CnTNOku0.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js.map → YamlWorkflowsPage-CnTNOku0.js.map} +1 -1
- package/dashboard/dist/assets/{agents-B-P5MlEx.js → agents-CkvQDr9b.js} +2 -2
- package/dashboard/dist/assets/{agents-B-P5MlEx.js.map → agents-CkvQDr9b.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CZz9iVys.js → bots-CzuMCVgU.js} +2 -2
- package/dashboard/dist/assets/{bots-CZz9iVys.js.map → bots-CzuMCVgU.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js → capabilities-CbGmS0ty.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js.map → capabilities-CbGmS0ty.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-cj-1c-1C.js → controlplane-DGvwkuYx.js} +2 -2
- package/dashboard/dist/assets/{controlplane-cj-1c-1C.js.map → controlplane-DGvwkuYx.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-BEVFyQnE.js → escalation-B7ysVToF.js} +2 -2
- package/dashboard/dist/assets/{escalation-BEVFyQnE.js.map → escalation-B7ysVToF.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js → escalation-columns-CHQEJU1j.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js.map → escalation-columns-CHQEJU1j.js.map} +1 -1
- package/dashboard/dist/assets/{helpers-B4gzNq9h.js → helpers-BFOjXa4r.js} +2 -2
- package/dashboard/dist/assets/{helpers-B4gzNq9h.js.map → helpers-BFOjXa4r.js.map} +1 -1
- package/dashboard/dist/assets/index-B9_1AZaG.js +2 -0
- package/dashboard/dist/assets/{index-3n5VREXN.js.map → index-B9_1AZaG.js.map} +1 -1
- package/dashboard/dist/assets/{index-BCQ65lNu.js → index-BFaDxPxA.js} +2 -2
- package/dashboard/dist/assets/{index-BCQ65lNu.js.map → index-BFaDxPxA.js.map} +1 -1
- package/dashboard/dist/assets/index-BduDiGcw.js +15 -0
- package/dashboard/dist/assets/{index-UtAfnStw.js.map → index-BduDiGcw.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bh-PnP17.js → index-BeLphL59.js} +2 -2
- package/dashboard/dist/assets/{index-Bh-PnP17.js.map → index-BeLphL59.js.map} +1 -1
- package/dashboard/dist/assets/index-C--SEsU7.css +1 -0
- package/dashboard/dist/assets/{index-_DfbFHXk.js → index-CRiBkHPb.js} +2 -2
- package/dashboard/dist/assets/{index-_DfbFHXk.js.map → index-CRiBkHPb.js.map} +1 -1
- package/dashboard/dist/assets/{index-DdKbIZNE.js → index-CbrMW-gM.js} +2 -2
- package/dashboard/dist/assets/{index-DdKbIZNE.js.map → index-CbrMW-gM.js.map} +1 -1
- package/dashboard/dist/assets/{index-aJRDh4zW.js → index-CvOGgvzP.js} +2 -2
- package/dashboard/dist/assets/{index-aJRDh4zW.js.map → index-CvOGgvzP.js.map} +1 -1
- package/dashboard/dist/assets/{index-D1MywQ2z.js → index-DDlrQeTj.js} +2 -2
- package/dashboard/dist/assets/{index-D1MywQ2z.js.map → index-DDlrQeTj.js.map} +1 -1
- package/dashboard/dist/assets/{index-BYXiz05a.js → index-DQHmfTPo.js} +2 -2
- package/dashboard/dist/assets/{index-BYXiz05a.js.map → index-DQHmfTPo.js.map} +1 -1
- package/dashboard/dist/assets/{index-BpN31nuC.js → index-_BRA9uFL.js} +25 -25
- package/dashboard/dist/assets/index-_BRA9uFL.js.map +1 -0
- package/dashboard/dist/assets/index-a98qWLB-.js +2 -0
- package/dashboard/dist/assets/index-a98qWLB-.js.map +1 -0
- package/dashboard/dist/assets/index-l_8R6U4r.js +6 -0
- package/dashboard/dist/assets/index-l_8R6U4r.js.map +1 -0
- package/dashboard/dist/assets/{index-D4KGadbW.js → index-v0OQpgXS.js} +2 -2
- package/dashboard/dist/assets/{index-D4KGadbW.js.map → index-v0OQpgXS.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DhtKWMON.js → knowledge-BlF8UMrk.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DhtKWMON.js.map → knowledge-BlF8UMrk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BXN7-wGF.js → mcp-MtXuky8q.js} +2 -2
- package/dashboard/dist/assets/{mcp-BXN7-wGF.js.map → mcp-MtXuky8q.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js → mcp-query-DQ-J1Q0K.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js.map → mcp-query-DQ-J1Q0K.js.map} +1 -1
- package/dashboard/dist/assets/{namespaces-ne_yDQZX.js → namespaces-DtsT_GoV.js} +2 -2
- package/dashboard/dist/assets/{namespaces-ne_yDQZX.js.map → namespaces-DtsT_GoV.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Bcz62DoS.js → pipelines-BjlCm9VH.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Bcz62DoS.js.map → pipelines-BjlCm9VH.js.map} +1 -1
- package/dashboard/dist/assets/{roles-De2CzGCy.js → roles-D-LhJ82d.js} +2 -2
- package/dashboard/dist/assets/{roles-De2CzGCy.js.map → roles-D-LhJ82d.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-4yL5EfxI.js → tasks-BrP_8uEN.js} +2 -2
- package/dashboard/dist/assets/{tasks-4yL5EfxI.js.map → tasks-BrP_8uEN.js.map} +1 -1
- package/dashboard/dist/assets/topics-DUk-zX5D.js +2 -0
- package/dashboard/dist/assets/{topics-DDKHpRwP.js.map → topics-DUk-zX5D.js.map} +1 -1
- package/dashboard/dist/assets/useEventHooks-XNNzwADV.js +2 -0
- package/dashboard/dist/assets/useEventHooks-XNNzwADV.js.map +1 -0
- package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js → useYamlActivityEvents-DANQ5jIY.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js.map → useYamlActivityEvents-DANQ5jIY.js.map} +1 -1
- package/dashboard/dist/assets/{users-pSMWP58G.js → users-vj0JgOkA.js} +2 -2
- package/dashboard/dist/assets/{users-pSMWP58G.js.map → users-vj0JgOkA.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-CrrAvF2g.js → vendor-icons-Doy0g69_.js} +116 -111
- package/dashboard/dist/assets/vendor-icons-Doy0g69_.js.map +1 -0
- package/dashboard/dist/assets/{workflows-COYPOe2I.js → workflows-CmqgGPzI.js} +2 -2
- package/dashboard/dist/assets/{workflows-COYPOe2I.js.map → workflows-CmqgGPzI.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js → yaml-workflows-DNFyjBXH.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js.map → yaml-workflows-DNFyjBXH.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/controlplane.md +1 -1
- package/docs/api/http/mcp-endpoint.md +133 -0
- package/docs/api/http/roles.md +46 -0
- package/docs/api/http/service-accounts.md +15 -0
- package/docs/api/http/settings.md +6 -0
- package/docs/api/mcp/admin.md +1187 -0
- package/docs/api/mcp/claude-code.md +47 -0
- package/docs/api/mcp/docs.md +54 -0
- package/docs/api/mcp/events.md +80 -0
- package/docs/api/mcp/file-storage.md +76 -0
- package/docs/api/mcp/http-fetch.md +64 -0
- package/docs/api/mcp/human-queue.md +101 -0
- package/docs/api/mcp/index.md +52 -0
- package/docs/api/mcp/knowledge.md +125 -0
- package/docs/api/mcp/oauth.md +62 -0
- package/docs/api/mcp/schema-exchange.md +56 -0
- package/docs/api/mcp/translation.md +28 -0
- package/docs/api/mcp/vision.md +46 -0
- package/docs/api/sdk/settings.md +3 -1
- package/docs/auth.md +109 -0
- package/docs/dashboard.md +1 -1
- package/package.json +1 -1
- package/build/system/mcp-servers/playwright/browser-lifecycle.d.ts +0 -26
- package/build/system/mcp-servers/playwright/browser-lifecycle.js +0 -125
- package/build/system/mcp-servers/playwright/index.d.ts +0 -25
- package/build/system/mcp-servers/playwright/index.js +0 -42
- package/build/system/mcp-servers/playwright/schemas.d.ts +0 -394
- package/build/system/mcp-servers/playwright/schemas.js +0 -90
- package/build/system/mcp-servers/playwright/tools-atomic.d.ts +0 -2
- package/build/system/mcp-servers/playwright/tools-atomic.js +0 -9
- package/build/system/mcp-servers/playwright/tools-navigation.d.ts +0 -2
- package/build/system/mcp-servers/playwright/tools-navigation.js +0 -153
- package/build/system/mcp-servers/playwright/tools-page-interaction.d.ts +0 -2
- package/build/system/mcp-servers/playwright/tools-page-interaction.js +0 -162
- package/build/system/mcp-servers/playwright/tools-run-script.d.ts +0 -2
- package/build/system/mcp-servers/playwright/tools-run-script.js +0 -207
- package/build/system/mcp-servers/playwright/types.d.ts +0 -8
- package/build/system/mcp-servers/playwright/types.js +0 -30
- package/build/system/mcp-servers/playwright/vision-helper.d.ts +0 -12
- package/build/system/mcp-servers/playwright/vision-helper.js +0 -81
- package/build/system/mcp-servers/playwright-cli/helpers.d.ts +0 -11
- package/build/system/mcp-servers/playwright-cli/helpers.js +0 -20
- package/build/system/mcp-servers/playwright-cli/index.d.ts +0 -4
- package/build/system/mcp-servers/playwright-cli/index.js +0 -15
- package/build/system/mcp-servers/playwright-cli/schemas.d.ts +0 -219
- package/build/system/mcp-servers/playwright-cli/schemas.js +0 -75
- package/build/system/mcp-servers/playwright-cli/tools-auth.d.ts +0 -2
- package/build/system/mcp-servers/playwright-cli/tools-auth.js +0 -183
- package/build/system/mcp-servers/playwright-cli/tools-capture.d.ts +0 -2
- package/build/system/mcp-servers/playwright-cli/tools-capture.js +0 -273
- package/build/system/seed/tool-manifests-browser.d.ts +0 -577
- package/build/system/seed/tool-manifests-browser.js +0 -158
- package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js +0 -16
- package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js.map +0 -1
- package/dashboard/dist/assets/AgentDetailPage-3mZA7SOb.js.map +0 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CA9x9o5s.js +0 -2
- package/dashboard/dist/assets/BotPicker-BQp_Vs73.js +0 -2
- package/dashboard/dist/assets/CronLabel-DY8VdTS9.js +0 -2
- package/dashboard/dist/assets/CronLabel-DY8VdTS9.js.map +0 -1
- package/dashboard/dist/assets/ElapsedCell-BPYm8RA7.js +0 -2
- package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js +0 -2
- package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js.map +0 -1
- package/dashboard/dist/assets/HomePage-CwRebzmO.js +0 -2
- package/dashboard/dist/assets/HomePage-CwRebzmO.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-DEef1_-T.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js.map +0 -1
- package/dashboard/dist/assets/McpRunsPage-aZg057y3.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js.map +0 -1
- package/dashboard/dist/assets/ServerName-Q6okiv4f.js +0 -2
- package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js +0 -9
- package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js.map +0 -1
- package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js.map +0 -1
- package/dashboard/dist/assets/index-3n5VREXN.js +0 -2
- package/dashboard/dist/assets/index-BAXzN-QB.js +0 -6
- package/dashboard/dist/assets/index-BAXzN-QB.js.map +0 -1
- package/dashboard/dist/assets/index-BpN31nuC.js.map +0 -1
- package/dashboard/dist/assets/index-C37LMzJa.css +0 -1
- package/dashboard/dist/assets/index-C5dHozmW.js +0 -2
- package/dashboard/dist/assets/index-C5dHozmW.js.map +0 -1
- package/dashboard/dist/assets/index-UtAfnStw.js +0 -15
- package/dashboard/dist/assets/topics-DDKHpRwP.js +0 -2
- package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js +0 -2
- package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-CrrAvF2g.js.map +0 -1
|
@@ -28,7 +28,7 @@ function publishMilestoneEvent(params) {
|
|
|
28
28
|
if (!params.milestones?.length)
|
|
29
29
|
return Promise.resolve();
|
|
30
30
|
return fireAndForget({
|
|
31
|
-
type:
|
|
31
|
+
type: `system.milestone.${params.workflowId}`,
|
|
32
32
|
source: params.source,
|
|
33
33
|
workflowId: params.workflowId,
|
|
34
34
|
workflowName: params.workflowName,
|
|
@@ -41,11 +41,13 @@ function publishMilestoneEvent(params) {
|
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* Publish a task lifecycle event
|
|
44
|
+
* Publish a task lifecycle event.
|
|
45
|
+
* Subject: system.task.{taskId}.{action}
|
|
45
46
|
*/
|
|
46
47
|
function publishTaskEvent(params) {
|
|
48
|
+
const action = params.type.split('.')[1]; // created, started, completed, escalated, failed
|
|
47
49
|
return fireAndForget({
|
|
48
|
-
type: params.
|
|
50
|
+
type: `system.task.${params.taskId}.${action}`,
|
|
49
51
|
source: params.source,
|
|
50
52
|
workflowId: params.workflowId,
|
|
51
53
|
workflowName: params.workflowName,
|
|
@@ -59,11 +61,13 @@ function publishTaskEvent(params) {
|
|
|
59
61
|
});
|
|
60
62
|
}
|
|
61
63
|
/**
|
|
62
|
-
* Publish an escalation lifecycle event
|
|
64
|
+
* Publish an escalation lifecycle event.
|
|
65
|
+
* Subject: system.escalation.{escalationId}.{action}
|
|
63
66
|
*/
|
|
64
67
|
function publishEscalationEvent(params) {
|
|
68
|
+
const action = params.type.split('.')[1];
|
|
65
69
|
return fireAndForget({
|
|
66
|
-
type: params.
|
|
70
|
+
type: `system.escalation.${params.escalationId}.${action}`,
|
|
67
71
|
source: params.source,
|
|
68
72
|
workflowId: params.workflowId,
|
|
69
73
|
workflowName: params.workflowName,
|
|
@@ -78,11 +82,12 @@ function publishEscalationEvent(params) {
|
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
80
84
|
* Publish an activity lifecycle event for YAML workflow steps.
|
|
81
|
-
*
|
|
85
|
+
* Subject: system.activity.{workflowId}.{activityName}.{action}
|
|
82
86
|
*/
|
|
83
87
|
function publishActivityEvent(params) {
|
|
88
|
+
const action = params.type.split('.')[1];
|
|
84
89
|
return fireAndForget({
|
|
85
|
-
type: params.
|
|
90
|
+
type: `system.activity.${params.workflowId}.${params.activityName}.${action}`,
|
|
86
91
|
source: 'yaml-worker',
|
|
87
92
|
workflowId: params.workflowId,
|
|
88
93
|
workflowName: params.workflowName,
|
|
@@ -93,13 +98,13 @@ function publishActivityEvent(params) {
|
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
100
|
/**
|
|
96
|
-
* Publish a knowledge lifecycle event
|
|
97
|
-
*
|
|
98
|
-
* happen both inside and outside workflows.
|
|
101
|
+
* Publish a knowledge lifecycle event.
|
|
102
|
+
* Subject: system.knowledge.{domain}.{action}
|
|
99
103
|
*/
|
|
100
104
|
function publishKnowledgeEvent(params) {
|
|
105
|
+
const action = params.type.split('.')[1];
|
|
101
106
|
return fireAndForget({
|
|
102
|
-
type: params.
|
|
107
|
+
type: `system.knowledge.${params.domain}.${action}`,
|
|
103
108
|
source: 'knowledge',
|
|
104
109
|
workflowId: '',
|
|
105
110
|
workflowName: '',
|
|
@@ -109,17 +114,18 @@ function publishKnowledgeEvent(params) {
|
|
|
109
114
|
});
|
|
110
115
|
}
|
|
111
116
|
/**
|
|
112
|
-
* Publish a file storage event
|
|
113
|
-
*
|
|
117
|
+
* Publish a file storage event.
|
|
118
|
+
* Subject: system.file.{action}
|
|
114
119
|
*/
|
|
115
120
|
function publishFileEvent(params) {
|
|
121
|
+
const action = params.type.split('.')[1];
|
|
116
122
|
const parsed = params.path.split('/');
|
|
117
123
|
const filename = parsed[parsed.length - 1] || '';
|
|
118
124
|
const dotIdx = filename.lastIndexOf('.');
|
|
119
125
|
const name = dotIdx > 0 ? filename.slice(0, dotIdx) : filename;
|
|
120
126
|
const extension = dotIdx > 0 ? filename.slice(dotIdx + 1) : '';
|
|
121
127
|
return fireAndForget({
|
|
122
|
-
type:
|
|
128
|
+
type: `system.file.${action}`,
|
|
123
129
|
source: 'file-storage',
|
|
124
130
|
workflowId: '',
|
|
125
131
|
workflowName: '',
|
|
@@ -137,10 +143,12 @@ function publishFileEvent(params) {
|
|
|
137
143
|
}
|
|
138
144
|
/**
|
|
139
145
|
* Publish an agent lifecycle event.
|
|
146
|
+
* Subject: system.agent.{agentName}.{action}
|
|
140
147
|
*/
|
|
141
148
|
function publishAgentEvent(params) {
|
|
149
|
+
const action = params.type.replace('agent.', '');
|
|
142
150
|
return fireAndForget({
|
|
143
|
-
type: params.
|
|
151
|
+
type: `system.agent.${params.agentName}.${action}`,
|
|
144
152
|
source: 'agent',
|
|
145
153
|
workflowId: params.agentId,
|
|
146
154
|
workflowName: params.agentName,
|
|
@@ -151,11 +159,13 @@ function publishAgentEvent(params) {
|
|
|
151
159
|
});
|
|
152
160
|
}
|
|
153
161
|
/**
|
|
154
|
-
* Publish a workflow lifecycle event
|
|
162
|
+
* Publish a workflow lifecycle event.
|
|
163
|
+
* Subject: system.workflow.{workflowId}.{action}
|
|
155
164
|
*/
|
|
156
165
|
function publishWorkflowEvent(params) {
|
|
166
|
+
const action = params.type.split('.')[1];
|
|
157
167
|
return fireAndForget({
|
|
158
|
-
type: params.
|
|
168
|
+
type: `system.workflow.${params.workflowId}.${action}`,
|
|
159
169
|
source: params.source,
|
|
160
170
|
workflowId: params.workflowId,
|
|
161
171
|
workflowName: params.workflowName,
|
package/build/modules/auth.d.ts
CHANGED
|
@@ -52,6 +52,13 @@ export declare function setAuthAdapter(adapter: LTAuthAdapter): void;
|
|
|
52
52
|
* JWT `role` claim for stateless admin checks. Returns 403 otherwise.
|
|
53
53
|
*/
|
|
54
54
|
export declare const requireAdmin: RequestHandler;
|
|
55
|
+
/**
|
|
56
|
+
* Middleware that requires builder access. Must be placed AFTER requireAuth.
|
|
57
|
+
*
|
|
58
|
+
* Builders are superadmin, admin, or users with the 'engineer' role.
|
|
59
|
+
* This is the backend equivalent of the dashboard's `isBuilder` check.
|
|
60
|
+
*/
|
|
61
|
+
export declare const requireBuilder: RequestHandler;
|
|
55
62
|
/**
|
|
56
63
|
* Generate a JWT token. Utility for tests and token provisioning.
|
|
57
64
|
*/
|
package/build/modules/auth.js
CHANGED
|
@@ -1,15 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.requireAdmin = exports.requireAuth = exports.JwtAuthAdapter = void 0;
|
|
39
|
+
exports.requireBuilder = exports.requireAdmin = exports.requireAuth = exports.JwtAuthAdapter = void 0;
|
|
7
40
|
exports.createAuthMiddleware = createAuthMiddleware;
|
|
8
41
|
exports.setAuthAdapter = setAuthAdapter;
|
|
9
42
|
exports.signToken = signToken;
|
|
10
43
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
11
44
|
const config_1 = require("./config");
|
|
45
|
+
const sso_1 = require("./sso");
|
|
12
46
|
const user_1 = require("../services/user");
|
|
47
|
+
const sso_provision_1 = require("../services/user/sso-provision");
|
|
13
48
|
const bot_api_key_1 = require("../services/auth/bot-api-key");
|
|
14
49
|
const principal_1 = require("../services/iam/principal");
|
|
15
50
|
/**
|
|
@@ -114,7 +149,39 @@ function createAuthMiddleware(adapter) {
|
|
|
114
149
|
* middleware delegates to the custom adapter instead.
|
|
115
150
|
*/
|
|
116
151
|
let _authMiddleware = null;
|
|
117
|
-
const requireAuth = (req, res, next) => {
|
|
152
|
+
const requireAuth = async (req, res, next) => {
|
|
153
|
+
// Fast path: Bearer token present — use standard JWT/adapter auth
|
|
154
|
+
const header = req.headers.authorization;
|
|
155
|
+
if (header?.startsWith('Bearer ')) {
|
|
156
|
+
const mw = _authMiddleware || createAuthMiddleware(new JwtAuthAdapter());
|
|
157
|
+
return mw(req, res, next);
|
|
158
|
+
}
|
|
159
|
+
// SSO fallback: no Bearer, but host may have authenticated via cookies/headers
|
|
160
|
+
const ssoConfig = (0, sso_1.getSSOConfig)();
|
|
161
|
+
if (ssoConfig) {
|
|
162
|
+
try {
|
|
163
|
+
const identity = await ssoConfig.resolve(req);
|
|
164
|
+
if (identity) {
|
|
165
|
+
const provisioned = await (0, sso_provision_1.ssoProvision)(identity, ssoConfig);
|
|
166
|
+
const highestType = provisioned.roles.some((r) => r.type === 'superadmin')
|
|
167
|
+
? 'superadmin'
|
|
168
|
+
: provisioned.roles.some((r) => r.type === 'admin')
|
|
169
|
+
? 'admin'
|
|
170
|
+
: 'member';
|
|
171
|
+
req.auth = {
|
|
172
|
+
userId: provisioned.userId,
|
|
173
|
+
role: highestType,
|
|
174
|
+
roles: provisioned.roles,
|
|
175
|
+
sso: true,
|
|
176
|
+
};
|
|
177
|
+
return next();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// SSO resolve failed — fall through to 401
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// No Bearer, no SSO — delegate to standard middleware (returns 401)
|
|
118
185
|
const mw = _authMiddleware || createAuthMiddleware(new JwtAuthAdapter());
|
|
119
186
|
mw(req, res, next);
|
|
120
187
|
};
|
|
@@ -155,6 +222,41 @@ const requireAdmin = async (req, res, next) => {
|
|
|
155
222
|
}
|
|
156
223
|
};
|
|
157
224
|
exports.requireAdmin = requireAdmin;
|
|
225
|
+
/**
|
|
226
|
+
* Middleware that requires builder access. Must be placed AFTER requireAuth.
|
|
227
|
+
*
|
|
228
|
+
* Builders are superadmin, admin, or users with the 'engineer' role.
|
|
229
|
+
* This is the backend equivalent of the dashboard's `isBuilder` check.
|
|
230
|
+
*/
|
|
231
|
+
const requireBuilder = async (req, res, next) => {
|
|
232
|
+
try {
|
|
233
|
+
if (!req.auth?.userId) {
|
|
234
|
+
res.status(403).json({ error: 'Forbidden' });
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// Fast path: trust the JWT role claim for admin/superadmin
|
|
238
|
+
if (req.auth.role === 'admin' || req.auth.role === 'superadmin') {
|
|
239
|
+
next();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
// Check database for superadmin role type
|
|
243
|
+
if (await (0, user_1.isSuperAdmin)(req.auth.userId)) {
|
|
244
|
+
next();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
// Check database for engineer role (builder)
|
|
248
|
+
const { hasRole } = await Promise.resolve().then(() => __importStar(require('../services/user/roles')));
|
|
249
|
+
if (await hasRole(req.auth.userId, 'engineer')) {
|
|
250
|
+
next();
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
res.status(403).json({ error: 'Forbidden: builder access required' });
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
res.status(403).json({ error: 'Forbidden' });
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
exports.requireBuilder = requireBuilder;
|
|
158
260
|
/**
|
|
159
261
|
* Generate a JWT token. Utility for tests and token provisioning.
|
|
160
262
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LTSSOConfig } from '../types/auth';
|
|
2
|
+
export declare function setSSOConfig(config: LTSSOConfig): void;
|
|
3
|
+
export declare function getSSOConfig(): LTSSOConfig | null;
|
|
4
|
+
export declare function isSSOEnabled(): boolean;
|
|
5
|
+
/** Reset SSO config. Used by tests. */
|
|
6
|
+
export declare function clearSSOConfig(): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setSSOConfig = setSSOConfig;
|
|
4
|
+
exports.getSSOConfig = getSSOConfig;
|
|
5
|
+
exports.isSSOEnabled = isSSOEnabled;
|
|
6
|
+
exports.clearSSOConfig = clearSSOConfig;
|
|
7
|
+
let _ssoConfig = null;
|
|
8
|
+
function setSSOConfig(config) {
|
|
9
|
+
_ssoConfig = config;
|
|
10
|
+
}
|
|
11
|
+
function getSSOConfig() {
|
|
12
|
+
return _ssoConfig;
|
|
13
|
+
}
|
|
14
|
+
function isSSOEnabled() {
|
|
15
|
+
return _ssoConfig !== null;
|
|
16
|
+
}
|
|
17
|
+
/** Reset SSO config. Used by tests. */
|
|
18
|
+
function clearSSOConfig() {
|
|
19
|
+
_ssoConfig = null;
|
|
20
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const express_1 = require("express");
|
|
37
|
+
const api = __importStar(require("../api/auth-sso"));
|
|
38
|
+
const router = (0, express_1.Router)();
|
|
39
|
+
/**
|
|
40
|
+
* POST /api/auth/sso
|
|
41
|
+
* Exchange host authentication for a Long Tail JWT.
|
|
42
|
+
*
|
|
43
|
+
* No Bearer token required — the host's cookies/headers carry the auth.
|
|
44
|
+
* The dashboard calls this on mount when SSO is enabled, replacing the
|
|
45
|
+
* login form with a transparent token exchange.
|
|
46
|
+
*/
|
|
47
|
+
router.post('/sso', async (req, res) => {
|
|
48
|
+
const result = await api.exchangeSSO(req);
|
|
49
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
50
|
+
});
|
|
51
|
+
exports.default = router;
|
|
@@ -38,7 +38,7 @@ const auth_1 = require("../modules/auth");
|
|
|
38
38
|
const api = __importStar(require("../api/bot-accounts"));
|
|
39
39
|
const router = (0, express_1.Router)();
|
|
40
40
|
// All bot account routes require admin access
|
|
41
|
-
router.use(auth_1.
|
|
41
|
+
router.use(auth_1.requireBuilder);
|
|
42
42
|
// ── Bot CRUD ─────────────────────────────────────────────────────────────────
|
|
43
43
|
/**
|
|
44
44
|
* GET /api/bot-accounts
|
|
@@ -42,7 +42,7 @@ const router = (0, express_1.Router)();
|
|
|
42
42
|
* List available HotMesh application IDs.
|
|
43
43
|
* Admin-only.
|
|
44
44
|
*/
|
|
45
|
-
router.get('/apps', auth_1.
|
|
45
|
+
router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
|
|
46
46
|
const result = await api.listApps();
|
|
47
47
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
48
48
|
});
|
|
@@ -51,7 +51,7 @@ router.get('/apps', auth_1.requireAdmin, async (_req, res) => {
|
|
|
51
51
|
* Execute a roll call — discovers all engines and workers.
|
|
52
52
|
* Admin-only.
|
|
53
53
|
*/
|
|
54
|
-
router.get('/rollcall', auth_1.
|
|
54
|
+
router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
|
|
55
55
|
const result = await api.rollCall({
|
|
56
56
|
appId: req.query.app_id || 'durable',
|
|
57
57
|
delay: req.query.delay ? parseInt(req.query.delay, 10) : undefined,
|
|
@@ -66,7 +66,7 @@ router.get('/rollcall', auth_1.requireAdmin, async (req, res) => {
|
|
|
66
66
|
* Body: { appId: string, throttle: number, topic?: string, guid?: string }
|
|
67
67
|
* throttle: ms delay (-1 = pause, 0 = resume, >0 = delay per msg)
|
|
68
68
|
*/
|
|
69
|
-
router.post('/throttle', auth_1.
|
|
69
|
+
router.post('/throttle', auth_1.requireBuilder, async (req, res) => {
|
|
70
70
|
const { appId = 'durable', throttle, topic, guid, scope } = req.body;
|
|
71
71
|
const result = await api.applyThrottle({ appId, throttle, topic, guid, scope });
|
|
72
72
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -79,7 +79,7 @@ router.post('/throttle', auth_1.requireAdmin, async (req, res) => {
|
|
|
79
79
|
* duration: 15m | 30m | 1h | 1d | 7d (default: 1h)
|
|
80
80
|
* stream: optional stream_name filter (specific task queue topic)
|
|
81
81
|
*/
|
|
82
|
-
router.get('/streams', auth_1.
|
|
82
|
+
router.get('/streams', auth_1.requireBuilder, async (req, res) => {
|
|
83
83
|
const result = await api.getStreamStats({
|
|
84
84
|
app_id: req.query.app_id || 'durable',
|
|
85
85
|
duration: req.query.duration || '1h',
|
|
@@ -97,7 +97,7 @@ router.get('/streams', auth_1.requireAdmin, async (req, res) => {
|
|
|
97
97
|
* are separate tables with different schemas.
|
|
98
98
|
* Admin-only.
|
|
99
99
|
*/
|
|
100
|
-
router.get('/stream-messages', auth_1.
|
|
100
|
+
router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
|
|
101
101
|
const result = await api.listStreamMessages({
|
|
102
102
|
namespace: req.query.namespace,
|
|
103
103
|
source: req.query.source,
|
|
@@ -124,7 +124,7 @@ router.get('/stream-messages', auth_1.requireAdmin, async (req, res) => {
|
|
|
124
124
|
*
|
|
125
125
|
* Body: { appId: string }
|
|
126
126
|
*/
|
|
127
|
-
router.post('/subscribe', auth_1.
|
|
127
|
+
router.post('/subscribe', auth_1.requireBuilder, async (req, res) => {
|
|
128
128
|
const { appId = 'durable' } = req.body;
|
|
129
129
|
const result = await api.subscribeMesh({ appId });
|
|
130
130
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -70,6 +70,7 @@ function registerListRoutes(router) {
|
|
|
70
70
|
type: req.query.type,
|
|
71
71
|
subtype: req.query.subtype,
|
|
72
72
|
assigned_to: req.query.assigned_to,
|
|
73
|
+
claimed: req.query.claimed === 'true',
|
|
73
74
|
priority: req.query.priority ? parseInt(req.query.priority, 10) : undefined,
|
|
74
75
|
limit: req.query.limit ? parseInt(req.query.limit, 10) : undefined,
|
|
75
76
|
offset: req.query.offset ? parseInt(req.query.offset, 10) : undefined,
|
package/build/routes/index.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const express_1 = require("express");
|
|
7
7
|
const auth_1 = require("../modules/auth");
|
|
8
8
|
const auth_2 = __importDefault(require("./auth"));
|
|
9
|
+
const auth_sso_1 = __importDefault(require("./auth-sso"));
|
|
9
10
|
const oauth_1 = __importDefault(require("./oauth"));
|
|
10
11
|
const delegation_1 = __importDefault(require("./delegation"));
|
|
11
12
|
const tasks_1 = __importDefault(require("./tasks"));
|
|
@@ -36,6 +37,7 @@ const nats_credentials_1 = __importDefault(require("./nats-credentials"));
|
|
|
36
37
|
const router = (0, express_1.Router)();
|
|
37
38
|
// Public routes (no auth required — they handle their own auth)
|
|
38
39
|
router.use('/auth', auth_2.default);
|
|
40
|
+
router.use('/auth', auth_sso_1.default);
|
|
39
41
|
router.use('/auth/oauth', oauth_1.default);
|
|
40
42
|
router.use('/delegation', delegation_1.default);
|
|
41
43
|
router.use('/files', files_1.default);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Streamable HTTP endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Exposes long-tail's built-in MCP tools to external clients
|
|
5
|
+
* (Claude Desktop, Cursor, other agents) via the standard MCP
|
|
6
|
+
* streamable-http transport protocol.
|
|
7
|
+
*
|
|
8
|
+
* Stateless mode — each POST creates a fresh server+transport pair.
|
|
9
|
+
* Auth via Bearer token (JWT or bot API key) in the Authorization header.
|
|
10
|
+
*
|
|
11
|
+
* Mount at /mcp:
|
|
12
|
+
* POST /mcp → JSON-RPC messages (initialize, tools/list, tools/call)
|
|
13
|
+
* GET /mcp → 405 (no SSE in stateless mode)
|
|
14
|
+
* DELETE /mcp → 405 (no sessions in stateless mode)
|
|
15
|
+
*/
|
|
16
|
+
declare const router: import("express-serve-static-core").Router;
|
|
17
|
+
export default router;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Streamable HTTP endpoint.
|
|
4
|
+
*
|
|
5
|
+
* Exposes long-tail's built-in MCP tools to external clients
|
|
6
|
+
* (Claude Desktop, Cursor, other agents) via the standard MCP
|
|
7
|
+
* streamable-http transport protocol.
|
|
8
|
+
*
|
|
9
|
+
* Stateless mode — each POST creates a fresh server+transport pair.
|
|
10
|
+
* Auth via Bearer token (JWT or bot API key) in the Authorization header.
|
|
11
|
+
*
|
|
12
|
+
* Mount at /mcp:
|
|
13
|
+
* POST /mcp → JSON-RPC messages (initialize, tools/list, tools/call)
|
|
14
|
+
* GET /mcp → 405 (no SSE in stateless mode)
|
|
15
|
+
* DELETE /mcp → 405 (no sessions in stateless mode)
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const express_1 = require("express");
|
|
19
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
20
|
+
const auth_1 = require("../modules/auth");
|
|
21
|
+
const logger_1 = require("../lib/logger");
|
|
22
|
+
const external_server_1 = require("../services/mcp/external-server");
|
|
23
|
+
const exposure_1 = require("../services/mcp/exposure");
|
|
24
|
+
const router = (0, express_1.Router)();
|
|
25
|
+
// All MCP endpoint requests require authentication
|
|
26
|
+
router.use(auth_1.requireAuth);
|
|
27
|
+
// POST /mcp — JSON-RPC messages
|
|
28
|
+
router.post('/', async (req, res) => {
|
|
29
|
+
try {
|
|
30
|
+
const exposure = (0, exposure_1.getExposureConfig)();
|
|
31
|
+
const callerScopes = req.auth?.scopes;
|
|
32
|
+
const server = await (0, external_server_1.createUnifiedMcpServer)(exposure, callerScopes);
|
|
33
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
34
|
+
sessionIdGenerator: undefined, // stateless
|
|
35
|
+
});
|
|
36
|
+
res.on('close', () => {
|
|
37
|
+
transport.close().catch(() => { });
|
|
38
|
+
server.close().catch(() => { });
|
|
39
|
+
});
|
|
40
|
+
await server.connect(transport);
|
|
41
|
+
await transport.handleRequest(req, res, req.body);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
logger_1.loggerRegistry.error(`[lt-mcp:endpoint] error: ${err.message}`);
|
|
45
|
+
if (!res.headersSent) {
|
|
46
|
+
res.status(500).json({
|
|
47
|
+
jsonrpc: '2.0',
|
|
48
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
49
|
+
id: null,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// GET /mcp — SSE stream (not supported in stateless mode)
|
|
55
|
+
router.get('/', (_req, res) => {
|
|
56
|
+
res.status(405).json({
|
|
57
|
+
jsonrpc: '2.0',
|
|
58
|
+
error: { code: -32000, message: 'Method not allowed. Use POST for stateless requests.' },
|
|
59
|
+
id: null,
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
// DELETE /mcp — session close (not supported in stateless mode)
|
|
63
|
+
router.delete('/', (_req, res) => {
|
|
64
|
+
res.status(405).json({
|
|
65
|
+
jsonrpc: '2.0',
|
|
66
|
+
error: { code: -32000, message: 'Method not allowed. Stateless mode has no sessions.' },
|
|
67
|
+
id: null,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
exports.default = router;
|
package/build/routes/roles.js
CHANGED
|
@@ -58,7 +58,7 @@ router.get('/details', async (_req, res) => {
|
|
|
58
58
|
* Create a standalone role. Requires admin.
|
|
59
59
|
* Body: { role: string }
|
|
60
60
|
*/
|
|
61
|
-
router.post('/', auth_1.
|
|
61
|
+
router.post('/', auth_1.requireBuilder, async (req, res) => {
|
|
62
62
|
const { role } = req.body || {};
|
|
63
63
|
const result = await api.createRole({ role });
|
|
64
64
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -76,7 +76,7 @@ router.get('/escalation-chains', async (_req, res) => {
|
|
|
76
76
|
* Add a single escalation chain entry. Requires admin.
|
|
77
77
|
* Body: { source_role: string, target_role: string }
|
|
78
78
|
*/
|
|
79
|
-
router.post('/escalation-chains', auth_1.
|
|
79
|
+
router.post('/escalation-chains', auth_1.requireBuilder, async (req, res) => {
|
|
80
80
|
const { source_role, target_role } = req.body || {};
|
|
81
81
|
const result = await api.addEscalationChain({ source_role, target_role });
|
|
82
82
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -86,7 +86,7 @@ router.post('/escalation-chains', auth_1.requireAdmin, async (req, res) => {
|
|
|
86
86
|
* Remove a single escalation chain entry. Requires admin.
|
|
87
87
|
* Body: { source_role: string, target_role: string }
|
|
88
88
|
*/
|
|
89
|
-
router.delete('/escalation-chains', auth_1.
|
|
89
|
+
router.delete('/escalation-chains', auth_1.requireBuilder, async (req, res) => {
|
|
90
90
|
const { source_role, target_role } = req.body || {};
|
|
91
91
|
const result = await api.removeEscalationChain({ source_role, target_role });
|
|
92
92
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -105,7 +105,7 @@ router.get('/:role/escalation-targets', async (req, res) => {
|
|
|
105
105
|
* Replace escalation targets for a role. Requires admin.
|
|
106
106
|
* Body: { targets: string[] }
|
|
107
107
|
*/
|
|
108
|
-
router.put('/:role/escalation-targets', auth_1.
|
|
108
|
+
router.put('/:role/escalation-targets', auth_1.requireBuilder, async (req, res) => {
|
|
109
109
|
const { targets } = req.body || {};
|
|
110
110
|
const result = await api.replaceEscalationTargets({ role: req.params.role, targets });
|
|
111
111
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -114,7 +114,7 @@ router.put('/:role/escalation-targets', auth_1.requireAdmin, async (req, res) =>
|
|
|
114
114
|
* DELETE /api/roles/:role
|
|
115
115
|
* Delete a role if it has no references. Requires admin.
|
|
116
116
|
*/
|
|
117
|
-
router.delete('/:role', auth_1.
|
|
117
|
+
router.delete('/:role', auth_1.requireBuilder, async (req, res) => {
|
|
118
118
|
const result = await api.deleteRole({ role: req.params.role });
|
|
119
119
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
120
120
|
});
|
package/build/routes/topics.js
CHANGED
|
@@ -94,6 +94,8 @@ router.delete('/by-name/:topic', async (req, res) => {
|
|
|
94
94
|
router.post('/by-name/:topic/publish', async (req, res) => {
|
|
95
95
|
const result = await api.publishTopic({
|
|
96
96
|
topic: decodeURIComponent(req.params.topic),
|
|
97
|
+
subject: req.body.subject || undefined,
|
|
98
|
+
eventId: req.body.eventId || undefined,
|
|
97
99
|
data: req.body.data ?? {},
|
|
98
100
|
source: req.body.source ?? 'dashboard',
|
|
99
101
|
});
|
package/build/routes/users.js
CHANGED
|
@@ -66,24 +66,24 @@ router.get('/:id', async (req, res) => {
|
|
|
66
66
|
* Create a new user.
|
|
67
67
|
* Body: { external_id, email?, display_name?, roles?: [{ role, type }], metadata? }
|
|
68
68
|
*/
|
|
69
|
-
router.post('/', auth_1.
|
|
69
|
+
router.post('/', auth_1.requireBuilder, async (req, res) => {
|
|
70
70
|
const result = await api.createUser(req.body || {});
|
|
71
71
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
72
72
|
});
|
|
73
73
|
/**
|
|
74
74
|
* PUT /api/users/:id
|
|
75
|
-
* Update a user.
|
|
75
|
+
* Update a user. Builder only.
|
|
76
76
|
* Body: { email?, display_name?, status?, metadata? }
|
|
77
77
|
*/
|
|
78
|
-
router.put('/:id', auth_1.
|
|
78
|
+
router.put('/:id', auth_1.requireBuilder, async (req, res) => {
|
|
79
79
|
const result = await api.updateUser({ id: req.params.id, ...(req.body || {}) });
|
|
80
80
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
81
81
|
});
|
|
82
82
|
/**
|
|
83
83
|
* DELETE /api/users/:id
|
|
84
|
-
* Delete a user.
|
|
84
|
+
* Delete a user. Builder only.
|
|
85
85
|
*/
|
|
86
|
-
router.delete('/:id', auth_1.
|
|
86
|
+
router.delete('/:id', auth_1.requireBuilder, async (req, res) => {
|
|
87
87
|
const result = await api.deleteUser({ id: req.params.id });
|
|
88
88
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
89
89
|
});
|
|
@@ -100,9 +100,35 @@ router.get('/:id/roles', async (req, res) => {
|
|
|
100
100
|
* POST /api/users/:id/roles
|
|
101
101
|
* Add a role to a user.
|
|
102
102
|
* Body: { role, type } — type must be superadmin, admin, or member
|
|
103
|
+
*
|
|
104
|
+
* Scoping rules:
|
|
105
|
+
* - superadmin: can assign any role/type
|
|
106
|
+
* - engineer: can assign up to admin type, but never superadmin type
|
|
107
|
+
* - role/admin (non-builder): can only assign member/admin for roles they hold
|
|
103
108
|
*/
|
|
104
109
|
router.post('/:id/roles', auth_1.requireAdmin, async (req, res) => {
|
|
105
110
|
const { role, type } = req.body || {};
|
|
111
|
+
const userId = req.auth.userId;
|
|
112
|
+
// Superadmin bypasses all scoping
|
|
113
|
+
const { isSuperAdmin } = await Promise.resolve().then(() => __importStar(require('../services/user/rbac')));
|
|
114
|
+
if (!(await isSuperAdmin(userId))) {
|
|
115
|
+
// Non-superadmin can never assign superadmin type
|
|
116
|
+
if (type === 'superadmin') {
|
|
117
|
+
res.status(403).json({ error: 'Only superadmin can assign superadmin role type' });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Check if caller has the engineer role (builder) — can assign any non-superadmin role
|
|
121
|
+
const { hasRole: checkRole } = await Promise.resolve().then(() => __importStar(require('../services/user/roles')));
|
|
122
|
+
const isEngineer = await checkRole(userId, 'engineer');
|
|
123
|
+
if (!isEngineer) {
|
|
124
|
+
// Non-builder admin: can only assign roles they themselves hold
|
|
125
|
+
const callerHasRole = await checkRole(userId, role);
|
|
126
|
+
if (!callerHasRole) {
|
|
127
|
+
res.status(403).json({ error: `You can only assign roles you hold. You do not have the '${role}' role.` });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
106
132
|
const result = await api.addUserRole({ id: req.params.id, role, type });
|
|
107
133
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
108
134
|
});
|