@hotmeshio/long-tail 0.4.21 → 0.4.23
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/build/api/dba.d.ts +2 -1
- package/build/api/dba.js +3 -2
- package/build/api/escalations/claim.d.ts +2 -0
- package/build/api/escalations/claim.js +10 -6
- package/build/api/escalations/helpers.d.ts +24 -1
- package/build/api/escalations/helpers.js +48 -3
- package/build/api/escalations/metadata.d.ts +10 -2
- package/build/api/escalations/metadata.js +29 -6
- package/build/api/exports.d.ts +1 -0
- package/build/api/exports.js +1 -1
- package/build/api/maintenance.d.ts +1 -0
- package/build/api/maintenance.js +3 -3
- package/build/api/workflows/discovery.js +5 -2
- package/build/modules/auth.d.ts +1 -1
- package/build/modules/auth.js +3 -3
- package/build/modules/maintenance.js +1 -0
- package/build/routes/controlplane.js +40 -29
- package/build/routes/dba.js +13 -2
- package/build/routes/escalations/metadata.js +2 -1
- package/build/routes/escalations/single.js +1 -1
- package/build/routes/exports.js +6 -0
- package/build/routes/maintenance.js +1 -0
- package/build/sdk/index.d.ts +2 -0
- package/build/services/auth/bot-api-key.js +6 -24
- package/build/services/auth/service-token.js +6 -18
- package/build/services/auth/sql.d.ts +11 -0
- package/build/services/auth/sql.js +37 -0
- package/build/services/controlplane/index.js +7 -5
- package/build/services/dba.d.ts +3 -1
- package/build/services/dba.js +5 -4
- package/build/services/escalation/crud.d.ts +19 -3
- package/build/services/escalation/crud.js +32 -15
- package/build/services/escalation/sql.d.ts +9 -2
- package/build/services/escalation/sql.js +36 -14
- package/build/services/export/index.d.ts +2 -2
- package/build/services/export/index.js +16 -10
- package/build/services/maintenance/index.js +7 -4
- package/build/services/pipelines/queries.js +5 -2
- package/build/services/pipelines/sql.d.ts +0 -1
- package/build/services/pipelines/sql.js +1 -3
- package/build/system/mcp-servers/admin/controlplane.js +1 -1
- package/build/system/mcp-servers/admin/maintenance.js +1 -0
- package/build/system/mcp-servers/admin/pipelines.js +4 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +31 -25
- package/build/system/mcp-servers/admin/schemas.js +9 -7
- package/build/system/seed/tool-manifests-admin.d.ts +59 -0
- package/build/system/seed/tool-manifests-admin.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/maintenance.d.ts +2 -0
- package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js → AdminDashboard-CgJC8ZZF.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js.map → AdminDashboard-CgJC8ZZF.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js → AgentConfigPage-Bjl2Lsvo.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js.map → AgentConfigPage-Bjl2Lsvo.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js → AgentDetailPage-D5dHrfaM.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js.map → AgentDetailPage-D5dHrfaM.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js → AgentsPage-Mom3N1Av.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js.map → AgentsPage-Mom3N1Av.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js → AvailableEscalationsPage-B2ZAb41C.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js.map → AvailableEscalationsPage-B2ZAb41C.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js → BotPicker-dCvnjynP.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js.map → BotPicker-dCvnjynP.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js → CapabilitiesPage-CK2fJ9Sy.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js.map → CapabilitiesPage-CK2fJ9Sy.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js → CollapsibleSection-bW0UZN9b.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js.map → CollapsibleSection-bW0UZN9b.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js → CredentialsPage-DVOK3aaR.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js.map → CredentialsPage-DVOK3aaR.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js → CronLabel-Cv5em7OP.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js.map → CronLabel-Cv5em7OP.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js → CustomDurationPicker-Dy4NBqhZ.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js.map → CustomDurationPicker-Dy4NBqhZ.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js → ElapsedCell-TQqWaVRq.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js.map → ElapsedCell-TQqWaVRq.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js → EscalationsOverview-Cv5UvuHI.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js.map → EscalationsOverview-Cv5UvuHI.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js → EventTable-Doky6fCO.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js.map → EventTable-Doky6fCO.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-CzvVyTq4.js +2 -0
- package/dashboard/dist/assets/HomePage-CzvVyTq4.js.map +1 -0
- package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js → ListToolbar-Cfec9gz_.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js.map → ListToolbar-Cfec9gz_.js.map} +1 -1
- package/dashboard/dist/assets/McpOverview-BN4GsBGI.js +2 -0
- package/dashboard/dist/assets/McpOverview-BN4GsBGI.js.map +1 -0
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js → McpQueryPage-BK5L2PqJ.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js.map → McpQueryPage-BK5L2PqJ.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +1 -0
- package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js +2 -0
- package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js → OperatorDashboard-CZQSINho.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js.map → OperatorDashboard-CZQSINho.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js → ProcessDetailPage-DUCOOvOK.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js.map → ProcessDetailPage-DUCOOvOK.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js → ProcessesListPage-CXvSLTIM.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js.map → ProcessesListPage-CXvSLTIM.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js +2 -0
- package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js.map +1 -0
- package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js → RunAsSelector-DP-jxsv6.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js.map → RunAsSelector-DP-jxsv6.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js → SwimlaneTimeline-BmASA0nN.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js.map → SwimlaneTimeline-BmASA0nN.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js → TaskDetailPage-CRowpkeZ.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js.map → TaskDetailPage-CRowpkeZ.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js → TasksListPage-uJ6z37J-.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js.map → TasksListPage-uJ6z37J-.js.map} +1 -1
- package/dashboard/dist/assets/TimeAgo-BxwngK1D.js +2 -0
- package/dashboard/dist/assets/{TimeAgo-BSzN6rAH.js.map → TimeAgo-BxwngK1D.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js → TimestampCell-CDmichOM.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js.map → TimestampCell-CDmichOM.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +2 -0
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +1 -0
- package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js → TopicDetailPage-Dm0hDlS8.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js.map → TopicDetailPage-Dm0hDlS8.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js → TopicsPage-letISGGD.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js.map → TopicsPage-letISGGD.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BjHIJWgh.js → UserName-W6_Iz2Qb.js} +2 -2
- package/dashboard/dist/assets/{UserName-BjHIJWgh.js.map → UserName-W6_Iz2Qb.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js → WorkflowExecutionPage-Cfx-xlRT.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js.map → WorkflowExecutionPage-Cfx-xlRT.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js +2 -0
- package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js → WorkflowsOverview-GefO_yn0.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js.map → WorkflowsOverview-GefO_yn0.js.map} +1 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +2 -0
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +1 -0
- package/dashboard/dist/assets/{agents-CkvQDr9b.js → agents-BI5OeN84.js} +2 -2
- package/dashboard/dist/assets/{agents-CkvQDr9b.js.map → agents-BI5OeN84.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CzuMCVgU.js → bots-1UzUCsrR.js} +2 -2
- package/dashboard/dist/assets/{bots-CzuMCVgU.js.map → bots-1UzUCsrR.js.map} +1 -1
- package/dashboard/dist/assets/capabilities-BUbl-ojp.js +2 -0
- package/dashboard/dist/assets/{capabilities-CbGmS0ty.js.map → capabilities-BUbl-ojp.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DGvwkuYx.js → controlplane-DTFrH_vN.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DGvwkuYx.js.map → controlplane-DTFrH_vN.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-B7ysVToF.js → escalation-BQhCt4W0.js} +2 -2
- package/dashboard/dist/assets/{escalation-B7ysVToF.js.map → escalation-BQhCt4W0.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js → escalation-columns-J20k5CcY.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js.map → escalation-columns-J20k5CcY.js.map} +1 -1
- package/dashboard/dist/assets/{helpers-BFOjXa4r.js → helpers-ge6Eu90Y.js} +2 -2
- package/dashboard/dist/assets/{helpers-BFOjXa4r.js.map → helpers-ge6Eu90Y.js.map} +1 -1
- package/dashboard/dist/assets/index-C-mbURj-.js +2 -0
- package/dashboard/dist/assets/index-C-mbURj-.js.map +1 -0
- package/dashboard/dist/assets/{index-BduDiGcw.js → index-C45DvtAZ.js} +2 -2
- package/dashboard/dist/assets/{index-BduDiGcw.js.map → index-C45DvtAZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9_1AZaG.js → index-C9ClHiiW.js} +2 -2
- package/dashboard/dist/assets/{index-B9_1AZaG.js.map → index-C9ClHiiW.js.map} +1 -1
- package/dashboard/dist/assets/index-CLUYzdwz.js +2 -0
- package/dashboard/dist/assets/{index-DQHmfTPo.js.map → index-CLUYzdwz.js.map} +1 -1
- package/dashboard/dist/assets/{index-l_8R6U4r.js → index-CVGgSoda.js} +2 -2
- package/dashboard/dist/assets/{index-l_8R6U4r.js.map → index-CVGgSoda.js.map} +1 -1
- package/dashboard/dist/assets/{index-_BRA9uFL.js → index-CWEOhAiK.js} +3 -3
- package/dashboard/dist/assets/{index-_BRA9uFL.js.map → index-CWEOhAiK.js.map} +1 -1
- package/dashboard/dist/assets/{index-BFaDxPxA.js → index-CWlP6vHG.js} +2 -2
- package/dashboard/dist/assets/{index-BFaDxPxA.js.map → index-CWlP6vHG.js.map} +1 -1
- package/dashboard/dist/assets/index-DasoTRjT.js +2 -0
- package/dashboard/dist/assets/{index-BeLphL59.js.map → index-DasoTRjT.js.map} +1 -1
- package/dashboard/dist/assets/{index-CvOGgvzP.js → index-FhasoOjO.js} +2 -2
- package/dashboard/dist/assets/{index-CvOGgvzP.js.map → index-FhasoOjO.js.map} +1 -1
- package/dashboard/dist/assets/{index-a98qWLB-.js → index-WQQJ_cp7.js} +2 -2
- package/dashboard/dist/assets/{index-a98qWLB-.js.map → index-WQQJ_cp7.js.map} +1 -1
- package/dashboard/dist/assets/{index-CbrMW-gM.js → index-hAZiac0C.js} +2 -2
- package/dashboard/dist/assets/{index-CbrMW-gM.js.map → index-hAZiac0C.js.map} +1 -1
- package/dashboard/dist/assets/{index-v0OQpgXS.js → index-si70YcIP.js} +2 -2
- package/dashboard/dist/assets/{index-v0OQpgXS.js.map → index-si70YcIP.js.map} +1 -1
- package/dashboard/dist/assets/{index-CRiBkHPb.js → index-vgxjge70.js} +2 -2
- package/dashboard/dist/assets/{index-CRiBkHPb.js.map → index-vgxjge70.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-BlF8UMrk.js → knowledge-D9Tuh-o-.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BlF8UMrk.js.map → knowledge-D9Tuh-o-.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-MtXuky8q.js → mcp-BO8QnWyk.js} +2 -2
- package/dashboard/dist/assets/{mcp-MtXuky8q.js.map → mcp-BO8QnWyk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js → mcp-query-WLtQtr51.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js.map → mcp-query-WLtQtr51.js.map} +1 -1
- package/dashboard/dist/assets/pipelines-BAVf9xud.js +2 -0
- package/dashboard/dist/assets/pipelines-BAVf9xud.js.map +1 -0
- package/dashboard/dist/assets/{roles-D-LhJ82d.js → roles-mGO2-2hA.js} +2 -2
- package/dashboard/dist/assets/{roles-D-LhJ82d.js.map → roles-mGO2-2hA.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BrP_8uEN.js → tasks-JVRVCx0f.js} +2 -2
- package/dashboard/dist/assets/{tasks-BrP_8uEN.js.map → tasks-JVRVCx0f.js.map} +1 -1
- package/dashboard/dist/assets/{topics-DUk-zX5D.js → topics-BLVnahd7.js} +2 -2
- package/dashboard/dist/assets/{topics-DUk-zX5D.js.map → topics-BLVnahd7.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js → useEventHooks-BwjAi0Qq.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js.map → useEventHooks-BwjAi0Qq.js.map} +1 -1
- package/dashboard/dist/assets/useNamespace-DkHmXddZ.js +2 -0
- package/dashboard/dist/assets/useNamespace-DkHmXddZ.js.map +1 -0
- package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js → useYamlActivityEvents-CsaR5dWj.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js.map → useYamlActivityEvents-CsaR5dWj.js.map} +1 -1
- package/dashboard/dist/assets/{users-vj0JgOkA.js → users-BvizpAkV.js} +2 -2
- package/dashboard/dist/assets/{users-vj0JgOkA.js.map → users-BvizpAkV.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-CmqgGPzI.js → workflows-CyEYa01a.js} +2 -2
- package/dashboard/dist/assets/{workflows-CmqgGPzI.js.map → workflows-CyEYa01a.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js → yaml-workflows-i3GzrEme.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js.map → yaml-workflows-i3GzrEme.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/controlplane.md +6 -4
- package/docs/api/http/dba.md +1 -0
- package/docs/api/http/escalations.md +38 -2
- package/docs/api/http/exports.md +26 -0
- package/docs/api/http/maintenance.md +1 -0
- package/docs/api/mcp/admin.md +7 -7
- package/docs/api/sdk/controlplane.md +4 -4
- package/docs/api/sdk/escalations.md +25 -5
- package/package.json +1 -1
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +0 -2
- package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +0 -1
- package/dashboard/dist/assets/McpOverview-BzyxJyc9.js +0 -2
- package/dashboard/dist/assets/McpOverview-BzyxJyc9.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +0 -1
- package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js.map +0 -1
- package/dashboard/dist/assets/RolesPage-pMERxj15.js +0 -2
- package/dashboard/dist/assets/RolesPage-pMERxj15.js.map +0 -1
- package/dashboard/dist/assets/TimeAgo-BSzN6rAH.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js.map +0 -1
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +0 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js +0 -2
- package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js.map +0 -1
- package/dashboard/dist/assets/capabilities-CbGmS0ty.js +0 -2
- package/dashboard/dist/assets/index-BeLphL59.js +0 -2
- package/dashboard/dist/assets/index-DDlrQeTj.js +0 -2
- package/dashboard/dist/assets/index-DDlrQeTj.js.map +0 -1
- package/dashboard/dist/assets/index-DQHmfTPo.js +0 -2
- package/dashboard/dist/assets/namespaces-DtsT_GoV.js +0 -2
- package/dashboard/dist/assets/namespaces-DtsT_GoV.js.map +0 -1
- package/dashboard/dist/assets/pipelines-BjlCm9VH.js +0 -2
- package/dashboard/dist/assets/pipelines-BjlCm9VH.js.map +0 -1
package/build/api/dba.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type { LTApiResult } from '../types/sdk';
|
|
|
19
19
|
* @returns `{ status: 200, data: <prune result summary> }`
|
|
20
20
|
*/
|
|
21
21
|
export declare function prune(input: {
|
|
22
|
+
appId: string;
|
|
22
23
|
expire?: string;
|
|
23
24
|
jobs?: boolean;
|
|
24
25
|
streams?: boolean;
|
|
@@ -39,4 +40,4 @@ export declare function prune(input: {
|
|
|
39
40
|
*
|
|
40
41
|
* @returns `{ status: 200, data: { ok: true } }`
|
|
41
42
|
*/
|
|
42
|
-
export declare function deploy(): Promise<LTApiResult>;
|
|
43
|
+
export declare function deploy(appId: string): Promise<LTApiResult>;
|
package/build/api/dba.js
CHANGED
|
@@ -58,6 +58,7 @@ const dbaService = __importStar(require("../services/dba"));
|
|
|
58
58
|
async function prune(input) {
|
|
59
59
|
try {
|
|
60
60
|
const result = await dbaService.prune({
|
|
61
|
+
appId: input.appId,
|
|
61
62
|
expire: input.expire,
|
|
62
63
|
jobs: input.jobs,
|
|
63
64
|
streams: input.streams,
|
|
@@ -84,9 +85,9 @@ async function prune(input) {
|
|
|
84
85
|
*
|
|
85
86
|
* @returns `{ status: 200, data: { ok: true } }`
|
|
86
87
|
*/
|
|
87
|
-
async function deploy() {
|
|
88
|
+
async function deploy(appId) {
|
|
88
89
|
try {
|
|
89
|
-
await dbaService.deploy();
|
|
90
|
+
await dbaService.deploy(appId);
|
|
90
91
|
return { status: 200, data: { ok: true } };
|
|
91
92
|
}
|
|
92
93
|
catch (err) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProvisionIfAbsent } from './helpers';
|
|
1
2
|
import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
2
3
|
/**
|
|
3
4
|
* Claim a pending escalation for the authenticated user.
|
|
@@ -14,6 +15,7 @@ import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
|
14
15
|
export declare function claimEscalation(input: {
|
|
15
16
|
id: string;
|
|
16
17
|
durationMinutes?: number;
|
|
18
|
+
provisionIfAbsent?: ProvisionIfAbsent;
|
|
17
19
|
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
18
20
|
/**
|
|
19
21
|
* Release a claimed escalation back to the pool.
|
|
@@ -52,26 +52,30 @@ const helpers_1 = require("./helpers");
|
|
|
52
52
|
*/
|
|
53
53
|
async function claimEscalation(input, auth) {
|
|
54
54
|
try {
|
|
55
|
-
const { id, durationMinutes } = input;
|
|
55
|
+
const { id, durationMinutes, provisionIfAbsent } = input;
|
|
56
56
|
const escalation = await escalationService.getEscalation(id);
|
|
57
57
|
if (!escalation) {
|
|
58
58
|
return { status: 404, error: 'Escalation not found' };
|
|
59
59
|
}
|
|
60
|
+
// Happy path: try claim assuming user has the role
|
|
60
61
|
const hasGlobal = await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId);
|
|
61
62
|
if (!hasGlobal) {
|
|
62
63
|
const userHasRole = await userService.hasRole(auth.userId, escalation.role);
|
|
63
64
|
if (!userHasRole) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
// Unhappy path: provision role if flag present, then retry
|
|
66
|
+
const provisioned = await (0, helpers_1.ensureRoleMembership)(auth.userId, escalation.role, auth.userId, provisionIfAbsent);
|
|
67
|
+
if (!provisioned) {
|
|
68
|
+
return {
|
|
69
|
+
status: 403,
|
|
70
|
+
error: `You must have the "${escalation.role}" role to claim this escalation`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
const result = await escalationService.claimEscalation(id, auth.userId, durationMinutes);
|
|
71
76
|
if (!result) {
|
|
72
77
|
return { status: 409, error: 'Escalation not available for claim' };
|
|
73
78
|
}
|
|
74
|
-
// Event published by service layer (services/escalation/crud.ts)
|
|
75
79
|
return { status: 200, data: result };
|
|
76
80
|
}
|
|
77
81
|
catch (err) {
|
|
@@ -8,13 +8,30 @@ export declare function checkBulkPermission(userId: string, ids: string[]): Prom
|
|
|
8
8
|
status: 403;
|
|
9
9
|
error: string;
|
|
10
10
|
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Identity to provision when the assignee doesn't exist in lt_users
|
|
13
|
+
* or lacks the required role. Only honored for callers with global
|
|
14
|
+
* escalation access (superadmin, admin/admin).
|
|
15
|
+
*/
|
|
16
|
+
export interface ProvisionIfAbsent {
|
|
17
|
+
displayName?: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
roles?: Array<{
|
|
20
|
+
role: string;
|
|
21
|
+
type?: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
11
24
|
/**
|
|
12
25
|
* Resolve an optional assignee external_id to an internal userId.
|
|
13
26
|
* When omitted, returns the caller's userId from auth.
|
|
27
|
+
*
|
|
28
|
+
* When `provisionIfAbsent` is provided and the caller has global access,
|
|
29
|
+
* the user is JIT-provisioned if absent and roles are ensured. This avoids
|
|
30
|
+
* pre-flight queries — the happy path (user exists) is one lookup.
|
|
14
31
|
*/
|
|
15
32
|
export declare function resolveAssignee(assignee: string | undefined, auth: {
|
|
16
33
|
userId: string;
|
|
17
|
-
}): Promise<{
|
|
34
|
+
}, provisionIfAbsent?: ProvisionIfAbsent): Promise<{
|
|
18
35
|
userId: string;
|
|
19
36
|
} | {
|
|
20
37
|
error: {
|
|
@@ -22,4 +39,10 @@ export declare function resolveAssignee(assignee: string | undefined, auth: {
|
|
|
22
39
|
error: string;
|
|
23
40
|
};
|
|
24
41
|
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Ensure a user has the required role for an escalation.
|
|
44
|
+
* Called after claim when the atomic SQL returns null due to role mismatch.
|
|
45
|
+
* Only adds the role if `provisionIfAbsent` declares it and caller has authority.
|
|
46
|
+
*/
|
|
47
|
+
export declare function ensureRoleMembership(userId: string, requiredRole: string, callerUserId: string, provisionIfAbsent?: ProvisionIfAbsent): Promise<boolean>;
|
|
25
48
|
export declare function publishBulkClaimEvents(ids: string[], assignedTo: string): void;
|
|
@@ -38,6 +38,7 @@ exports.getVisibleRoles = getVisibleRoles;
|
|
|
38
38
|
exports.validateIds = validateIds;
|
|
39
39
|
exports.checkBulkPermission = checkBulkPermission;
|
|
40
40
|
exports.resolveAssignee = resolveAssignee;
|
|
41
|
+
exports.ensureRoleMembership = ensureRoleMembership;
|
|
41
42
|
exports.publishBulkClaimEvents = publishBulkClaimEvents;
|
|
42
43
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
43
44
|
const userService = __importStar(require("../../services/user"));
|
|
@@ -71,15 +72,59 @@ async function checkBulkPermission(userId, ids) {
|
|
|
71
72
|
/**
|
|
72
73
|
* Resolve an optional assignee external_id to an internal userId.
|
|
73
74
|
* When omitted, returns the caller's userId from auth.
|
|
75
|
+
*
|
|
76
|
+
* When `provisionIfAbsent` is provided and the caller has global access,
|
|
77
|
+
* the user is JIT-provisioned if absent and roles are ensured. This avoids
|
|
78
|
+
* pre-flight queries — the happy path (user exists) is one lookup.
|
|
74
79
|
*/
|
|
75
|
-
async function resolveAssignee(assignee, auth) {
|
|
80
|
+
async function resolveAssignee(assignee, auth, provisionIfAbsent) {
|
|
76
81
|
if (!assignee)
|
|
77
82
|
return { userId: auth.userId };
|
|
83
|
+
// Happy path: user exists
|
|
78
84
|
const user = await userService.getUserByExternalId(assignee);
|
|
79
|
-
if (
|
|
85
|
+
if (user)
|
|
86
|
+
return { userId: user.id };
|
|
87
|
+
// User not found — provision if caller has authority and flag is set
|
|
88
|
+
if (!provisionIfAbsent) {
|
|
80
89
|
return { error: { status: 404, error: `User not found for external_id: ${assignee}` } };
|
|
81
90
|
}
|
|
82
|
-
|
|
91
|
+
const hasAuthority = await userService.hasGlobalEscalationAccess(auth.userId);
|
|
92
|
+
if (!hasAuthority) {
|
|
93
|
+
return { error: { status: 403, error: 'Only superadmin or admin can provision users on claim' } };
|
|
94
|
+
}
|
|
95
|
+
// Provision the user
|
|
96
|
+
const created = await userService.createUser({
|
|
97
|
+
external_id: assignee,
|
|
98
|
+
display_name: provisionIfAbsent.displayName || assignee,
|
|
99
|
+
email: provisionIfAbsent.email,
|
|
100
|
+
roles: (provisionIfAbsent.roles || []).map((r) => ({
|
|
101
|
+
role: r.role,
|
|
102
|
+
type: (r.type || 'member'),
|
|
103
|
+
})),
|
|
104
|
+
});
|
|
105
|
+
return { userId: created.id };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Ensure a user has the required role for an escalation.
|
|
109
|
+
* Called after claim when the atomic SQL returns null due to role mismatch.
|
|
110
|
+
* Only adds the role if `provisionIfAbsent` declares it and caller has authority.
|
|
111
|
+
*/
|
|
112
|
+
async function ensureRoleMembership(userId, requiredRole, callerUserId, provisionIfAbsent) {
|
|
113
|
+
if (!provisionIfAbsent)
|
|
114
|
+
return false;
|
|
115
|
+
const hasAuthority = await userService.hasGlobalEscalationAccess(callerUserId);
|
|
116
|
+
if (!hasAuthority)
|
|
117
|
+
return false;
|
|
118
|
+
// Check if the provision declares this role
|
|
119
|
+
const declaredRole = provisionIfAbsent.roles?.find((r) => r.role === requiredRole);
|
|
120
|
+
if (!declaredRole)
|
|
121
|
+
return false;
|
|
122
|
+
// Add the role — idempotent (ON CONFLICT DO NOTHING)
|
|
123
|
+
try {
|
|
124
|
+
await userService.addUserRole(userId, requiredRole, (declaredRole.type || 'member'));
|
|
125
|
+
}
|
|
126
|
+
catch { /* already has it */ }
|
|
127
|
+
return true;
|
|
83
128
|
}
|
|
84
129
|
function publishBulkClaimEvents(ids, assignedTo) {
|
|
85
130
|
for (const id of ids) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProvisionIfAbsent } from './helpers';
|
|
1
2
|
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
2
3
|
/**
|
|
3
4
|
* Find escalations by a metadata key-value pair.
|
|
@@ -25,12 +26,19 @@ export declare function claimByMetadata(input: {
|
|
|
25
26
|
durationMinutes?: number;
|
|
26
27
|
assignee?: string;
|
|
27
28
|
metadata?: Record<string, any>;
|
|
29
|
+
provisionIfAbsent?: ProvisionIfAbsent;
|
|
28
30
|
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
29
31
|
/**
|
|
30
32
|
* Resolve an escalation by metadata key-value pair.
|
|
31
33
|
*
|
|
32
|
-
* Single atomic
|
|
33
|
-
*
|
|
34
|
+
* Single atomic query with signal guard:
|
|
35
|
+
* - No signal_id → claim + resolve atomically in SQL. One query. Done.
|
|
36
|
+
* - signal_id present → SQL returns the signal info without resolving.
|
|
37
|
+
* Caller signals the workflow; conditionLT resolves durably inside
|
|
38
|
+
* the workflow via ltResolveEscalation.
|
|
39
|
+
*
|
|
40
|
+
* Never does SELECT-then-UPDATE. The SQL CTE handles find + RBAC +
|
|
41
|
+
* claim + resolve (or signal detection) in one round-trip.
|
|
34
42
|
*/
|
|
35
43
|
export declare function resolveByMetadata(input: {
|
|
36
44
|
key: string;
|
|
@@ -76,7 +76,7 @@ async function claimByMetadata(input, auth) {
|
|
|
76
76
|
if (!input.key || !input.value) {
|
|
77
77
|
return { status: 400, error: 'key and value are required' };
|
|
78
78
|
}
|
|
79
|
-
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth);
|
|
79
|
+
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth, input.provisionIfAbsent);
|
|
80
80
|
if ('error' in resolved)
|
|
81
81
|
return resolved.error;
|
|
82
82
|
const claimUserId = resolved.userId;
|
|
@@ -99,8 +99,14 @@ async function claimByMetadata(input, auth) {
|
|
|
99
99
|
/**
|
|
100
100
|
* Resolve an escalation by metadata key-value pair.
|
|
101
101
|
*
|
|
102
|
-
* Single atomic
|
|
103
|
-
*
|
|
102
|
+
* Single atomic query with signal guard:
|
|
103
|
+
* - No signal_id → claim + resolve atomically in SQL. One query. Done.
|
|
104
|
+
* - signal_id present → SQL returns the signal info without resolving.
|
|
105
|
+
* Caller signals the workflow; conditionLT resolves durably inside
|
|
106
|
+
* the workflow via ltResolveEscalation.
|
|
107
|
+
*
|
|
108
|
+
* Never does SELECT-then-UPDATE. The SQL CTE handles find + RBAC +
|
|
109
|
+
* claim + resolve (or signal detection) in one round-trip.
|
|
104
110
|
*/
|
|
105
111
|
async function resolveByMetadata(input, auth) {
|
|
106
112
|
try {
|
|
@@ -115,11 +121,25 @@ async function resolveByMetadata(input, auth) {
|
|
|
115
121
|
return resolved.error;
|
|
116
122
|
const resolveUserId = resolved.userId;
|
|
117
123
|
const allowedRoles = await resolveAllowedRoles(auth.userId);
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
124
|
+
const result = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, allowedRoles);
|
|
125
|
+
if (result.outcome === 'not_found') {
|
|
120
126
|
return { status: 404, error: 'No pending escalation found for this metadata, or insufficient role permissions' };
|
|
121
127
|
}
|
|
122
|
-
|
|
128
|
+
if (result.outcome === 'resolved') {
|
|
129
|
+
return { status: 200, data: { escalation: result.escalation } };
|
|
130
|
+
}
|
|
131
|
+
// Signal-backed escalation — signal the workflow, conditionLT resolves durably
|
|
132
|
+
const { createClient } = await Promise.resolve().then(() => __importStar(require('../../workers')));
|
|
133
|
+
const client = createClient();
|
|
134
|
+
const handle = await client.workflow.getHandle(result.taskQueue, result.workflowType, result.workflowId);
|
|
135
|
+
await handle.signal(result.signalId, {
|
|
136
|
+
...input.resolverPayload,
|
|
137
|
+
$escalation_id: result.escalationId,
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
status: 200,
|
|
141
|
+
data: { signaled: true, escalationId: result.escalationId, workflowId: result.workflowId },
|
|
142
|
+
};
|
|
123
143
|
}
|
|
124
144
|
catch (err) {
|
|
125
145
|
return { status: 500, error: err.message };
|
|
@@ -134,5 +154,8 @@ async function resolveAllowedRoles(userId) {
|
|
|
134
154
|
if (await userService.hasGlobalEscalationAccess(userId))
|
|
135
155
|
return null;
|
|
136
156
|
const userRoles = await userService.getUserRoles(userId);
|
|
157
|
+
// Return the user's roles (may be empty → SQL filters out all rows).
|
|
158
|
+
// System/service accounts that need unrestricted access should be
|
|
159
|
+
// seeded with the superadmin role via start({ seed: { admin } }).
|
|
137
160
|
return userRoles.map(r => r.role);
|
|
138
161
|
}
|
package/build/api/exports.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type { ExportMode } from '@hotmeshio/hotmesh/build/types/exporter';
|
|
|
15
15
|
* @returns `{ status: 200, data: { jobs, total, ... } }` on success
|
|
16
16
|
*/
|
|
17
17
|
export declare function listJobs(input: {
|
|
18
|
+
app_id: string;
|
|
18
19
|
limit?: number;
|
|
19
20
|
offset?: number;
|
|
20
21
|
entity?: string;
|
package/build/api/exports.js
CHANGED
|
@@ -55,7 +55,7 @@ const resolve_1 = require("../services/task/resolve");
|
|
|
55
55
|
*/
|
|
56
56
|
async function listJobs(input) {
|
|
57
57
|
try {
|
|
58
|
-
const result = await exportService.listJobs(input);
|
|
58
|
+
const result = await exportService.listJobs(input.app_id, input);
|
|
59
59
|
return { status: 200, data: result };
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
@@ -17,6 +17,7 @@ export declare function getMaintenanceConfig(): LTApiResult;
|
|
|
17
17
|
* @returns `{ status: 200, data: { config, restarted: true } }`
|
|
18
18
|
*/
|
|
19
19
|
export declare function updateMaintenanceConfig(input: {
|
|
20
|
+
appId: string;
|
|
20
21
|
schedule: string;
|
|
21
22
|
rules: LTMaintenanceConfig['rules'];
|
|
22
23
|
}): Promise<LTApiResult>;
|
package/build/api/maintenance.js
CHANGED
|
@@ -26,11 +26,11 @@ function getMaintenanceConfig() {
|
|
|
26
26
|
*/
|
|
27
27
|
async function updateMaintenanceConfig(input) {
|
|
28
28
|
try {
|
|
29
|
-
if (!input.schedule || !Array.isArray(input.rules)) {
|
|
30
|
-
return { status: 400, error: 'schedule (string) and rules (array) are required' };
|
|
29
|
+
if (!input.appId || !input.schedule || !Array.isArray(input.rules)) {
|
|
30
|
+
return { status: 400, error: 'appId (string), schedule (string), and rules (array) are required' };
|
|
31
31
|
}
|
|
32
32
|
await maintenance_1.maintenanceRegistry.disconnect();
|
|
33
|
-
maintenance_1.maintenanceRegistry.register({ schedule: input.schedule, rules: input.rules });
|
|
33
|
+
maintenance_1.maintenanceRegistry.register({ appId: input.appId, schedule: input.schedule, rules: input.rules });
|
|
34
34
|
await maintenance_1.maintenanceRegistry.connect();
|
|
35
35
|
return {
|
|
36
36
|
status: 200,
|
|
@@ -41,6 +41,7 @@ const cron_1 = require("../../services/cron");
|
|
|
41
41
|
const db_1 = require("../../lib/db");
|
|
42
42
|
const registry_1 = require("../../services/workers/registry");
|
|
43
43
|
const sql_1 = require("../../services/pipelines/sql");
|
|
44
|
+
const hotmesh_utils_1 = require("../../services/hotmesh-utils");
|
|
44
45
|
/**
|
|
45
46
|
* List active workflow workers with their registration status.
|
|
46
47
|
*
|
|
@@ -81,9 +82,11 @@ async function listDiscoveredWorkflows(input) {
|
|
|
81
82
|
try {
|
|
82
83
|
// 1. Active workers from in-memory registry
|
|
83
84
|
const activeWorkers = (0, registry_1.getRegisteredWorkers)();
|
|
84
|
-
// 2. Historical entities from
|
|
85
|
+
// 2. Historical entities from jobs table
|
|
85
86
|
const pool = (0, db_1.getPool)();
|
|
86
|
-
|
|
87
|
+
// TODO: accept app_id parameter to avoid hardcoded schema
|
|
88
|
+
const schema = (0, hotmesh_utils_1.quoteSchema)((0, hotmesh_utils_1.sanitizeAppId)('durable'));
|
|
89
|
+
const { rows: entityRows } = await pool.query((0, sql_1.DISTINCT_ENTITIES)(schema));
|
|
87
90
|
const historicalEntities = new Set(entityRows.map((r) => r.entity));
|
|
88
91
|
// 3. Registered configs
|
|
89
92
|
const configs = await configService.listWorkflowConfigs();
|
package/build/modules/auth.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export declare const requireAdmin: RequestHandler;
|
|
|
55
55
|
/**
|
|
56
56
|
* Middleware that requires builder access. Must be placed AFTER requireAuth.
|
|
57
57
|
*
|
|
58
|
-
* Builders are superadmin
|
|
58
|
+
* Builders are superadmin or users with the 'engineer' role.
|
|
59
59
|
* This is the backend equivalent of the dashboard's `isBuilder` check.
|
|
60
60
|
*/
|
|
61
61
|
export declare const requireBuilder: RequestHandler;
|
package/build/modules/auth.js
CHANGED
|
@@ -225,7 +225,7 @@ exports.requireAdmin = requireAdmin;
|
|
|
225
225
|
/**
|
|
226
226
|
* Middleware that requires builder access. Must be placed AFTER requireAuth.
|
|
227
227
|
*
|
|
228
|
-
* Builders are superadmin
|
|
228
|
+
* Builders are superadmin or users with the 'engineer' role.
|
|
229
229
|
* This is the backend equivalent of the dashboard's `isBuilder` check.
|
|
230
230
|
*/
|
|
231
231
|
const requireBuilder = async (req, res, next) => {
|
|
@@ -234,8 +234,8 @@ const requireBuilder = async (req, res, next) => {
|
|
|
234
234
|
res.status(403).json({ error: 'Forbidden' });
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
|
-
// Fast path: trust the JWT role claim for
|
|
238
|
-
if (req.auth.role === '
|
|
237
|
+
// Fast path: trust the JWT role claim for superadmin
|
|
238
|
+
if (req.auth.role === 'superadmin') {
|
|
239
239
|
next();
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
@@ -39,8 +39,8 @@ const api = __importStar(require("../api/controlplane"));
|
|
|
39
39
|
const router = (0, express_1.Router)();
|
|
40
40
|
/**
|
|
41
41
|
* GET /api/controlplane/apps
|
|
42
|
-
* List available HotMesh application
|
|
43
|
-
*
|
|
42
|
+
* List available HotMesh application namespaces.
|
|
43
|
+
* Builder-only.
|
|
44
44
|
*/
|
|
45
45
|
router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
|
|
46
46
|
const result = await api.listApps();
|
|
@@ -49,11 +49,16 @@ router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
|
|
|
49
49
|
/**
|
|
50
50
|
* GET /api/controlplane/rollcall?app_id=durable&delay=1000
|
|
51
51
|
* Execute a roll call — discovers all engines and workers.
|
|
52
|
-
*
|
|
52
|
+
* Builder-only. app_id is required.
|
|
53
53
|
*/
|
|
54
54
|
router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
|
|
55
|
+
const appId = req.query.app_id;
|
|
56
|
+
if (!appId) {
|
|
57
|
+
res.status(400).json({ error: 'app_id query parameter is required' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
55
60
|
const result = await api.rollCall({
|
|
56
|
-
appId
|
|
61
|
+
appId,
|
|
57
62
|
delay: req.query.delay ? parseInt(req.query.delay, 10) : undefined,
|
|
58
63
|
});
|
|
59
64
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -61,27 +66,32 @@ router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
|
|
|
61
66
|
/**
|
|
62
67
|
* POST /api/controlplane/throttle
|
|
63
68
|
* Apply a throttle command to the mesh.
|
|
64
|
-
*
|
|
69
|
+
* Builder-only. appId is required in body.
|
|
65
70
|
*
|
|
66
71
|
* Body: { appId: string, throttle: number, topic?: string, guid?: string }
|
|
67
|
-
* throttle: ms delay (-1 = pause, 0 = resume, >0 = delay per msg)
|
|
68
72
|
*/
|
|
69
73
|
router.post('/throttle', auth_1.requireBuilder, async (req, res) => {
|
|
70
|
-
const { appId
|
|
74
|
+
const { appId, throttle, topic, guid, scope } = req.body;
|
|
75
|
+
if (!appId) {
|
|
76
|
+
res.status(400).json({ error: 'appId is required' });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
71
79
|
const result = await api.applyThrottle({ appId, throttle, topic, guid, scope });
|
|
72
80
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
73
81
|
});
|
|
74
82
|
/**
|
|
75
|
-
* GET /api/controlplane/streams?app_id=durable&duration=1h
|
|
76
|
-
* Stream processing statistics
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* duration: 15m | 30m | 1h | 1d | 7d (default: 1h)
|
|
80
|
-
* stream: optional stream_name filter (specific task queue topic)
|
|
83
|
+
* GET /api/controlplane/streams?app_id=durable&duration=1h
|
|
84
|
+
* Stream processing statistics.
|
|
85
|
+
* Builder-only. app_id is required.
|
|
81
86
|
*/
|
|
82
87
|
router.get('/streams', auth_1.requireBuilder, async (req, res) => {
|
|
88
|
+
const app_id = req.query.app_id;
|
|
89
|
+
if (!app_id) {
|
|
90
|
+
res.status(400).json({ error: 'app_id query parameter is required' });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
83
93
|
const result = await api.getStreamStats({
|
|
84
|
-
app_id
|
|
94
|
+
app_id,
|
|
85
95
|
duration: req.query.duration || '1h',
|
|
86
96
|
stream: req.query.stream || undefined,
|
|
87
97
|
});
|
|
@@ -89,18 +99,19 @@ router.get('/streams', auth_1.requireBuilder, async (req, res) => {
|
|
|
89
99
|
});
|
|
90
100
|
/**
|
|
91
101
|
* GET /api/controlplane/stream-messages?namespace=durable&source=worker
|
|
92
|
-
* &limit=25&offset=0&sort_by=created_at&order=desc
|
|
93
|
-
* &status=pending&stream_name=hmsh:durable:w:&msg_type=WORKER
|
|
94
|
-
*
|
|
95
102
|
* Browse stream messages with pagination, filtering, and sorting.
|
|
96
|
-
*
|
|
97
|
-
* are separate tables with different schemas.
|
|
98
|
-
* Admin-only.
|
|
103
|
+
* Builder-only. namespace and source are required.
|
|
99
104
|
*/
|
|
100
105
|
router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
|
|
106
|
+
const namespace = req.query.namespace;
|
|
107
|
+
const source = req.query.source;
|
|
108
|
+
if (!namespace || !source) {
|
|
109
|
+
res.status(400).json({ error: 'namespace and source query parameters are required' });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
101
112
|
const result = await api.listStreamMessages({
|
|
102
|
-
namespace
|
|
103
|
-
source
|
|
113
|
+
namespace,
|
|
114
|
+
source,
|
|
104
115
|
limit: req.query.limit ? parseInt(req.query.limit, 10) : undefined,
|
|
105
116
|
offset: req.query.offset ? parseInt(req.query.offset, 10) : undefined,
|
|
106
117
|
sort_by: req.query.sort_by || undefined,
|
|
@@ -117,15 +128,15 @@ router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
|
|
|
117
128
|
});
|
|
118
129
|
/**
|
|
119
130
|
* POST /api/controlplane/subscribe
|
|
120
|
-
* Start the quorum→NATS bridge for
|
|
121
|
-
*
|
|
122
|
-
* all control plane messages to NATS on `lt.mesh.*` topics.
|
|
123
|
-
* Admin-only.
|
|
124
|
-
*
|
|
125
|
-
* Body: { appId: string }
|
|
131
|
+
* Start the quorum→NATS bridge for a namespace.
|
|
132
|
+
* Builder-only. appId is required in body.
|
|
126
133
|
*/
|
|
127
134
|
router.post('/subscribe', auth_1.requireBuilder, async (req, res) => {
|
|
128
|
-
const { appId
|
|
135
|
+
const { appId } = req.body;
|
|
136
|
+
if (!appId) {
|
|
137
|
+
res.status(400).json({ error: 'appId is required' });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
129
140
|
const result = await api.subscribeMesh({ appId });
|
|
130
141
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
131
142
|
});
|
package/build/routes/dba.js
CHANGED
|
@@ -53,7 +53,13 @@ const router = (0, express_1.Router)();
|
|
|
53
53
|
* Returns: { jobs, streams, attributes, transient, marked }
|
|
54
54
|
*/
|
|
55
55
|
router.post('/prune', auth_1.requireAdmin, async (req, res) => {
|
|
56
|
+
const appId = req.body.app_id;
|
|
57
|
+
if (!appId) {
|
|
58
|
+
res.status(400).json({ error: 'app_id is required' });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
56
61
|
const result = await api.prune({
|
|
62
|
+
appId,
|
|
57
63
|
expire: req.body.expire,
|
|
58
64
|
jobs: req.body.jobs,
|
|
59
65
|
streams: req.body.streams,
|
|
@@ -73,8 +79,13 @@ router.post('/prune', auth_1.requireAdmin, async (req, res) => {
|
|
|
73
79
|
* Deploy the server-side prune function and run migrations.
|
|
74
80
|
* Idempotent — safe to call on startup or from CI/CD.
|
|
75
81
|
*/
|
|
76
|
-
router.post('/deploy', auth_1.requireAdmin, async (
|
|
77
|
-
const
|
|
82
|
+
router.post('/deploy', auth_1.requireAdmin, async (req, res) => {
|
|
83
|
+
const appId = req.body.app_id;
|
|
84
|
+
if (!appId) {
|
|
85
|
+
res.status(400).json({ error: 'app_id is required' });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const result = await api.deploy(appId);
|
|
78
89
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
79
90
|
});
|
|
80
91
|
exports.default = router;
|
|
@@ -58,7 +58,7 @@ function registerMetadataRoutes(router) {
|
|
|
58
58
|
/**
|
|
59
59
|
* POST /api/escalations/claim-by-metadata
|
|
60
60
|
* Find and claim an escalation by metadata key-value pair.
|
|
61
|
-
* Body: { key, value, durationMinutes?, assignee?, metadata? }
|
|
61
|
+
* Body: { key, value, durationMinutes?, assignee?, metadata?, provisionIfAbsent? }
|
|
62
62
|
*/
|
|
63
63
|
router.post('/claim-by-metadata', async (req, res) => {
|
|
64
64
|
const result = await api.claimByMetadata({
|
|
@@ -67,6 +67,7 @@ function registerMetadataRoutes(router) {
|
|
|
67
67
|
durationMinutes: req.body?.durationMinutes,
|
|
68
68
|
assignee: req.body?.assignee,
|
|
69
69
|
metadata: req.body?.metadata,
|
|
70
|
+
provisionIfAbsent: req.body?.provisionIfAbsent,
|
|
70
71
|
}, req.auth);
|
|
71
72
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
72
73
|
});
|
|
@@ -71,7 +71,7 @@ function registerSingleRoutes(router) {
|
|
|
71
71
|
* Body: { durationMinutes?: number }
|
|
72
72
|
*/
|
|
73
73
|
router.post('/:id/claim', async (req, res) => {
|
|
74
|
-
const result = await api.claimEscalation({ id: req.params.id, durationMinutes: req.body?.durationMinutes }, req.auth);
|
|
74
|
+
const result = await api.claimEscalation({ id: req.params.id, durationMinutes: req.body?.durationMinutes, provisionIfAbsent: req.body?.provisionIfAbsent }, req.auth);
|
|
75
75
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
76
76
|
});
|
|
77
77
|
/**
|
package/build/routes/exports.js
CHANGED
|
@@ -41,7 +41,13 @@ const router = (0, express_1.Router)();
|
|
|
41
41
|
* List workflow jobs with optional filtering and pagination.
|
|
42
42
|
*/
|
|
43
43
|
router.get('/jobs', async (req, res) => {
|
|
44
|
+
const app_id = (req.query.app_id || req.query.namespace);
|
|
45
|
+
if (!app_id) {
|
|
46
|
+
res.status(400).json({ error: 'app_id (or namespace) query parameter is required' });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
44
49
|
const result = await api.listJobs({
|
|
50
|
+
app_id,
|
|
45
51
|
limit: parseInt(req.query.limit) || undefined,
|
|
46
52
|
offset: parseInt(req.query.offset) || undefined,
|
|
47
53
|
entity: req.query.entity || undefined,
|
|
@@ -54,6 +54,7 @@ router.get('/', (_req, res) => {
|
|
|
54
54
|
*/
|
|
55
55
|
router.put('/', auth_1.requireAdmin, async (req, res) => {
|
|
56
56
|
const result = await api.updateMaintenanceConfig({
|
|
57
|
+
appId: req.body?.appId ?? req.body?.app_id,
|
|
57
58
|
schedule: req.body?.schedule,
|
|
58
59
|
rules: req.body?.rules,
|
|
59
60
|
});
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -121,6 +121,7 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
121
121
|
claim: (input: {
|
|
122
122
|
id: string;
|
|
123
123
|
durationMinutes?: number;
|
|
124
|
+
provisionIfAbsent?: import("../api/escalations/helpers").ProvisionIfAbsent;
|
|
124
125
|
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
125
126
|
release: (input: {
|
|
126
127
|
id: string;
|
|
@@ -164,6 +165,7 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
164
165
|
durationMinutes?: number;
|
|
165
166
|
assignee?: string;
|
|
166
167
|
metadata?: Record<string, any>;
|
|
168
|
+
provisionIfAbsent?: import("../api/escalations/helpers").ProvisionIfAbsent;
|
|
167
169
|
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
168
170
|
resolveByMetadata: (input: {
|
|
169
171
|
key: string;
|