@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.
Files changed (231) hide show
  1. package/build/api/dba.d.ts +2 -1
  2. package/build/api/dba.js +3 -2
  3. package/build/api/escalations/claim.d.ts +2 -0
  4. package/build/api/escalations/claim.js +10 -6
  5. package/build/api/escalations/helpers.d.ts +24 -1
  6. package/build/api/escalations/helpers.js +48 -3
  7. package/build/api/escalations/metadata.d.ts +10 -2
  8. package/build/api/escalations/metadata.js +29 -6
  9. package/build/api/exports.d.ts +1 -0
  10. package/build/api/exports.js +1 -1
  11. package/build/api/maintenance.d.ts +1 -0
  12. package/build/api/maintenance.js +3 -3
  13. package/build/api/workflows/discovery.js +5 -2
  14. package/build/modules/auth.d.ts +1 -1
  15. package/build/modules/auth.js +3 -3
  16. package/build/modules/maintenance.js +1 -0
  17. package/build/routes/controlplane.js +40 -29
  18. package/build/routes/dba.js +13 -2
  19. package/build/routes/escalations/metadata.js +2 -1
  20. package/build/routes/escalations/single.js +1 -1
  21. package/build/routes/exports.js +6 -0
  22. package/build/routes/maintenance.js +1 -0
  23. package/build/sdk/index.d.ts +2 -0
  24. package/build/services/auth/bot-api-key.js +6 -24
  25. package/build/services/auth/service-token.js +6 -18
  26. package/build/services/auth/sql.d.ts +11 -0
  27. package/build/services/auth/sql.js +37 -0
  28. package/build/services/controlplane/index.js +7 -5
  29. package/build/services/dba.d.ts +3 -1
  30. package/build/services/dba.js +5 -4
  31. package/build/services/escalation/crud.d.ts +19 -3
  32. package/build/services/escalation/crud.js +32 -15
  33. package/build/services/escalation/sql.d.ts +9 -2
  34. package/build/services/escalation/sql.js +36 -14
  35. package/build/services/export/index.d.ts +2 -2
  36. package/build/services/export/index.js +16 -10
  37. package/build/services/maintenance/index.js +7 -4
  38. package/build/services/pipelines/queries.js +5 -2
  39. package/build/services/pipelines/sql.d.ts +0 -1
  40. package/build/services/pipelines/sql.js +1 -3
  41. package/build/system/mcp-servers/admin/controlplane.js +1 -1
  42. package/build/system/mcp-servers/admin/maintenance.js +1 -0
  43. package/build/system/mcp-servers/admin/pipelines.js +4 -4
  44. package/build/system/mcp-servers/admin/schemas.d.ts +31 -25
  45. package/build/system/mcp-servers/admin/schemas.js +9 -7
  46. package/build/system/seed/tool-manifests-admin.d.ts +59 -0
  47. package/build/system/seed/tool-manifests-admin.js +2 -2
  48. package/build/tsconfig.tsbuildinfo +1 -1
  49. package/build/types/maintenance.d.ts +2 -0
  50. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js → AdminDashboard-CgJC8ZZF.js} +2 -2
  51. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js.map → AdminDashboard-CgJC8ZZF.js.map} +1 -1
  52. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js → AgentConfigPage-Bjl2Lsvo.js} +2 -2
  53. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js.map → AgentConfigPage-Bjl2Lsvo.js.map} +1 -1
  54. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js → AgentDetailPage-D5dHrfaM.js} +2 -2
  55. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js.map → AgentDetailPage-D5dHrfaM.js.map} +1 -1
  56. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js → AgentsPage-Mom3N1Av.js} +2 -2
  57. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js.map → AgentsPage-Mom3N1Av.js.map} +1 -1
  58. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js → AvailableEscalationsPage-B2ZAb41C.js} +2 -2
  59. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js.map → AvailableEscalationsPage-B2ZAb41C.js.map} +1 -1
  60. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js → BotPicker-dCvnjynP.js} +2 -2
  61. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js.map → BotPicker-dCvnjynP.js.map} +1 -1
  62. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js → CapabilitiesPage-CK2fJ9Sy.js} +2 -2
  63. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js.map → CapabilitiesPage-CK2fJ9Sy.js.map} +1 -1
  64. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js → CollapsibleSection-bW0UZN9b.js} +2 -2
  65. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js.map → CollapsibleSection-bW0UZN9b.js.map} +1 -1
  66. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js → CredentialsPage-DVOK3aaR.js} +2 -2
  67. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js.map → CredentialsPage-DVOK3aaR.js.map} +1 -1
  68. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js → CronLabel-Cv5em7OP.js} +2 -2
  69. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js.map → CronLabel-Cv5em7OP.js.map} +1 -1
  70. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js → CustomDurationPicker-Dy4NBqhZ.js} +2 -2
  71. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js.map → CustomDurationPicker-Dy4NBqhZ.js.map} +1 -1
  72. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js → ElapsedCell-TQqWaVRq.js} +2 -2
  73. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js.map → ElapsedCell-TQqWaVRq.js.map} +1 -1
  74. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js → EscalationsOverview-Cv5UvuHI.js} +2 -2
  75. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js.map → EscalationsOverview-Cv5UvuHI.js.map} +1 -1
  76. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js → EventTable-Doky6fCO.js} +2 -2
  77. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js.map → EventTable-Doky6fCO.js.map} +1 -1
  78. package/dashboard/dist/assets/HomePage-CzvVyTq4.js +2 -0
  79. package/dashboard/dist/assets/HomePage-CzvVyTq4.js.map +1 -0
  80. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js → ListToolbar-Cfec9gz_.js} +2 -2
  81. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js.map → ListToolbar-Cfec9gz_.js.map} +1 -1
  82. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js +2 -0
  83. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js.map +1 -0
  84. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +5 -0
  85. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +1 -0
  86. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js → McpQueryPage-BK5L2PqJ.js} +2 -2
  87. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js.map → McpQueryPage-BK5L2PqJ.js.map} +1 -1
  88. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +2 -0
  89. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +1 -0
  90. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js +2 -0
  91. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js.map +1 -0
  92. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js → OperatorDashboard-CZQSINho.js} +2 -2
  93. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js.map → OperatorDashboard-CZQSINho.js.map} +1 -1
  94. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js → ProcessDetailPage-DUCOOvOK.js} +2 -2
  95. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js.map → ProcessDetailPage-DUCOOvOK.js.map} +1 -1
  96. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js → ProcessesListPage-CXvSLTIM.js} +2 -2
  97. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js.map → ProcessesListPage-CXvSLTIM.js.map} +1 -1
  98. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js +2 -0
  99. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js.map +1 -0
  100. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js → RunAsSelector-DP-jxsv6.js} +2 -2
  101. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js.map → RunAsSelector-DP-jxsv6.js.map} +1 -1
  102. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js → SwimlaneTimeline-BmASA0nN.js} +2 -2
  103. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js.map → SwimlaneTimeline-BmASA0nN.js.map} +1 -1
  104. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js → TaskDetailPage-CRowpkeZ.js} +2 -2
  105. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js.map → TaskDetailPage-CRowpkeZ.js.map} +1 -1
  106. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js → TasksListPage-uJ6z37J-.js} +2 -2
  107. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js.map → TasksListPage-uJ6z37J-.js.map} +1 -1
  108. package/dashboard/dist/assets/TimeAgo-BxwngK1D.js +2 -0
  109. package/dashboard/dist/assets/{TimeAgo-BSzN6rAH.js.map → TimeAgo-BxwngK1D.js.map} +1 -1
  110. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js → TimestampCell-CDmichOM.js} +2 -2
  111. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js.map → TimestampCell-CDmichOM.js.map} +1 -1
  112. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +2 -0
  113. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +1 -0
  114. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js → TopicDetailPage-Dm0hDlS8.js} +2 -2
  115. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js.map → TopicDetailPage-Dm0hDlS8.js.map} +1 -1
  116. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js → TopicsPage-letISGGD.js} +2 -2
  117. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js.map → TopicsPage-letISGGD.js.map} +1 -1
  118. package/dashboard/dist/assets/{UserName-BjHIJWgh.js → UserName-W6_Iz2Qb.js} +2 -2
  119. package/dashboard/dist/assets/{UserName-BjHIJWgh.js.map → UserName-W6_Iz2Qb.js.map} +1 -1
  120. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js → WorkflowExecutionPage-Cfx-xlRT.js} +2 -2
  121. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js.map → WorkflowExecutionPage-Cfx-xlRT.js.map} +1 -1
  122. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js +2 -0
  123. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js.map +1 -0
  124. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js → WorkflowsOverview-GefO_yn0.js} +2 -2
  125. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js.map → WorkflowsOverview-GefO_yn0.js.map} +1 -1
  126. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +2 -0
  127. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +1 -0
  128. package/dashboard/dist/assets/{agents-CkvQDr9b.js → agents-BI5OeN84.js} +2 -2
  129. package/dashboard/dist/assets/{agents-CkvQDr9b.js.map → agents-BI5OeN84.js.map} +1 -1
  130. package/dashboard/dist/assets/{bots-CzuMCVgU.js → bots-1UzUCsrR.js} +2 -2
  131. package/dashboard/dist/assets/{bots-CzuMCVgU.js.map → bots-1UzUCsrR.js.map} +1 -1
  132. package/dashboard/dist/assets/capabilities-BUbl-ojp.js +2 -0
  133. package/dashboard/dist/assets/{capabilities-CbGmS0ty.js.map → capabilities-BUbl-ojp.js.map} +1 -1
  134. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js → controlplane-DTFrH_vN.js} +2 -2
  135. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js.map → controlplane-DTFrH_vN.js.map} +1 -1
  136. package/dashboard/dist/assets/{escalation-B7ysVToF.js → escalation-BQhCt4W0.js} +2 -2
  137. package/dashboard/dist/assets/{escalation-B7ysVToF.js.map → escalation-BQhCt4W0.js.map} +1 -1
  138. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js → escalation-columns-J20k5CcY.js} +2 -2
  139. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js.map → escalation-columns-J20k5CcY.js.map} +1 -1
  140. package/dashboard/dist/assets/{helpers-BFOjXa4r.js → helpers-ge6Eu90Y.js} +2 -2
  141. package/dashboard/dist/assets/{helpers-BFOjXa4r.js.map → helpers-ge6Eu90Y.js.map} +1 -1
  142. package/dashboard/dist/assets/index-C-mbURj-.js +2 -0
  143. package/dashboard/dist/assets/index-C-mbURj-.js.map +1 -0
  144. package/dashboard/dist/assets/{index-BduDiGcw.js → index-C45DvtAZ.js} +2 -2
  145. package/dashboard/dist/assets/{index-BduDiGcw.js.map → index-C45DvtAZ.js.map} +1 -1
  146. package/dashboard/dist/assets/{index-B9_1AZaG.js → index-C9ClHiiW.js} +2 -2
  147. package/dashboard/dist/assets/{index-B9_1AZaG.js.map → index-C9ClHiiW.js.map} +1 -1
  148. package/dashboard/dist/assets/index-CLUYzdwz.js +2 -0
  149. package/dashboard/dist/assets/{index-DQHmfTPo.js.map → index-CLUYzdwz.js.map} +1 -1
  150. package/dashboard/dist/assets/{index-l_8R6U4r.js → index-CVGgSoda.js} +2 -2
  151. package/dashboard/dist/assets/{index-l_8R6U4r.js.map → index-CVGgSoda.js.map} +1 -1
  152. package/dashboard/dist/assets/{index-_BRA9uFL.js → index-CWEOhAiK.js} +3 -3
  153. package/dashboard/dist/assets/{index-_BRA9uFL.js.map → index-CWEOhAiK.js.map} +1 -1
  154. package/dashboard/dist/assets/{index-BFaDxPxA.js → index-CWlP6vHG.js} +2 -2
  155. package/dashboard/dist/assets/{index-BFaDxPxA.js.map → index-CWlP6vHG.js.map} +1 -1
  156. package/dashboard/dist/assets/index-DasoTRjT.js +2 -0
  157. package/dashboard/dist/assets/{index-BeLphL59.js.map → index-DasoTRjT.js.map} +1 -1
  158. package/dashboard/dist/assets/{index-CvOGgvzP.js → index-FhasoOjO.js} +2 -2
  159. package/dashboard/dist/assets/{index-CvOGgvzP.js.map → index-FhasoOjO.js.map} +1 -1
  160. package/dashboard/dist/assets/{index-a98qWLB-.js → index-WQQJ_cp7.js} +2 -2
  161. package/dashboard/dist/assets/{index-a98qWLB-.js.map → index-WQQJ_cp7.js.map} +1 -1
  162. package/dashboard/dist/assets/{index-CbrMW-gM.js → index-hAZiac0C.js} +2 -2
  163. package/dashboard/dist/assets/{index-CbrMW-gM.js.map → index-hAZiac0C.js.map} +1 -1
  164. package/dashboard/dist/assets/{index-v0OQpgXS.js → index-si70YcIP.js} +2 -2
  165. package/dashboard/dist/assets/{index-v0OQpgXS.js.map → index-si70YcIP.js.map} +1 -1
  166. package/dashboard/dist/assets/{index-CRiBkHPb.js → index-vgxjge70.js} +2 -2
  167. package/dashboard/dist/assets/{index-CRiBkHPb.js.map → index-vgxjge70.js.map} +1 -1
  168. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js → knowledge-D9Tuh-o-.js} +2 -2
  169. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js.map → knowledge-D9Tuh-o-.js.map} +1 -1
  170. package/dashboard/dist/assets/{mcp-MtXuky8q.js → mcp-BO8QnWyk.js} +2 -2
  171. package/dashboard/dist/assets/{mcp-MtXuky8q.js.map → mcp-BO8QnWyk.js.map} +1 -1
  172. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js → mcp-query-WLtQtr51.js} +2 -2
  173. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js.map → mcp-query-WLtQtr51.js.map} +1 -1
  174. package/dashboard/dist/assets/pipelines-BAVf9xud.js +2 -0
  175. package/dashboard/dist/assets/pipelines-BAVf9xud.js.map +1 -0
  176. package/dashboard/dist/assets/{roles-D-LhJ82d.js → roles-mGO2-2hA.js} +2 -2
  177. package/dashboard/dist/assets/{roles-D-LhJ82d.js.map → roles-mGO2-2hA.js.map} +1 -1
  178. package/dashboard/dist/assets/{tasks-BrP_8uEN.js → tasks-JVRVCx0f.js} +2 -2
  179. package/dashboard/dist/assets/{tasks-BrP_8uEN.js.map → tasks-JVRVCx0f.js.map} +1 -1
  180. package/dashboard/dist/assets/{topics-DUk-zX5D.js → topics-BLVnahd7.js} +2 -2
  181. package/dashboard/dist/assets/{topics-DUk-zX5D.js.map → topics-BLVnahd7.js.map} +1 -1
  182. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js → useEventHooks-BwjAi0Qq.js} +2 -2
  183. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js.map → useEventHooks-BwjAi0Qq.js.map} +1 -1
  184. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js +2 -0
  185. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js.map +1 -0
  186. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js → useYamlActivityEvents-CsaR5dWj.js} +2 -2
  187. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js.map → useYamlActivityEvents-CsaR5dWj.js.map} +1 -1
  188. package/dashboard/dist/assets/{users-vj0JgOkA.js → users-BvizpAkV.js} +2 -2
  189. package/dashboard/dist/assets/{users-vj0JgOkA.js.map → users-BvizpAkV.js.map} +1 -1
  190. package/dashboard/dist/assets/{workflows-CmqgGPzI.js → workflows-CyEYa01a.js} +2 -2
  191. package/dashboard/dist/assets/{workflows-CmqgGPzI.js.map → workflows-CyEYa01a.js.map} +1 -1
  192. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js → yaml-workflows-i3GzrEme.js} +2 -2
  193. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js.map → yaml-workflows-i3GzrEme.js.map} +1 -1
  194. package/dashboard/dist/index.html +1 -1
  195. package/docs/api/http/controlplane.md +6 -4
  196. package/docs/api/http/dba.md +1 -0
  197. package/docs/api/http/escalations.md +38 -2
  198. package/docs/api/http/exports.md +26 -0
  199. package/docs/api/http/maintenance.md +1 -0
  200. package/docs/api/mcp/admin.md +7 -7
  201. package/docs/api/sdk/controlplane.md +4 -4
  202. package/docs/api/sdk/escalations.md +25 -5
  203. package/package.json +1 -1
  204. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +0 -2
  205. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +0 -1
  206. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js +0 -2
  207. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js.map +0 -1
  208. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js +0 -5
  209. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js.map +0 -1
  210. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +0 -2
  211. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +0 -1
  212. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +0 -2
  213. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js.map +0 -1
  214. package/dashboard/dist/assets/RolesPage-pMERxj15.js +0 -2
  215. package/dashboard/dist/assets/RolesPage-pMERxj15.js.map +0 -1
  216. package/dashboard/dist/assets/TimeAgo-BSzN6rAH.js +0 -2
  217. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js +0 -2
  218. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js.map +0 -1
  219. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +0 -2
  220. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +0 -1
  221. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js +0 -2
  222. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js.map +0 -1
  223. package/dashboard/dist/assets/capabilities-CbGmS0ty.js +0 -2
  224. package/dashboard/dist/assets/index-BeLphL59.js +0 -2
  225. package/dashboard/dist/assets/index-DDlrQeTj.js +0 -2
  226. package/dashboard/dist/assets/index-DDlrQeTj.js.map +0 -1
  227. package/dashboard/dist/assets/index-DQHmfTPo.js +0 -2
  228. package/dashboard/dist/assets/namespaces-DtsT_GoV.js +0 -2
  229. package/dashboard/dist/assets/namespaces-DtsT_GoV.js.map +0 -1
  230. package/dashboard/dist/assets/pipelines-BjlCm9VH.js +0 -2
  231. package/dashboard/dist/assets/pipelines-BjlCm9VH.js.map +0 -1
@@ -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
- return {
65
- status: 403,
66
- error: `You must have the "${escalation.role}" role to claim this escalation`,
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 (!user) {
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
- return { userId: user.id };
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 CTE: find + claim + resolve in one query.
33
- * RBAC is enforced in the SQL WHERE clause.
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 CTE: find + claim + resolve in one query.
103
- * RBAC is enforced in the SQL WHERE clause.
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 escalation = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, allowedRoles);
119
- if (!escalation) {
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
- return { status: 200, data: { escalation } };
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
  }
@@ -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;
@@ -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>;
@@ -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 durable.jobs
85
+ // 2. Historical entities from jobs table
85
86
  const pool = (0, db_1.getPool)();
86
- const { rows: entityRows } = await pool.query(sql_1.DISTINCT_ENTITIES_DURABLE);
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();
@@ -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, admin, or users with the 'engineer' role.
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;
@@ -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, admin, or users with the 'engineer' role.
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 admin/superadmin
238
- if (req.auth.role === 'admin' || req.auth.role === 'superadmin') {
237
+ // Fast path: trust the JWT role claim for superadmin
238
+ if (req.auth.role === 'superadmin') {
239
239
  next();
240
240
  return;
241
241
  }
@@ -18,6 +18,7 @@ exports.defaultMaintenanceConfig = void 0;
18
18
  * inputs from the execution timeline.
19
19
  */
20
20
  exports.defaultMaintenanceConfig = {
21
+ appId: 'durable',
21
22
  schedule: '0 2 * * 0',
22
23
  rules: [
23
24
  {
@@ -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 IDs.
43
- * Admin-only.
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
- * Admin-only.
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: req.query.app_id || 'durable',
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
- * Admin-only.
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 = 'durable', throttle, topic, guid, scope } = req.body;
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&stream=hmsh:durable:x:
76
- * Stream processing statistics — pending count + processed volume by time range.
77
- * Admin-only.
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: req.query.app_id || 'durable',
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
- * Both namespace and source are required — engine and worker streams
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: req.query.namespace,
103
- source: req.query.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 an appId.
121
- * Subscribes to the HotMesh quorum channel and republishes
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 = 'durable' } = req.body;
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
  });
@@ -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 (_req, res) => {
77
- const result = await api.deploy();
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
  /**
@@ -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
  });
@@ -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;