@hotmeshio/long-tail 0.4.18 → 0.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +0 -2
  2. package/build/api/auth-sso.d.ts +12 -0
  3. package/build/api/auth-sso.js +54 -0
  4. package/build/api/escalations/bulk.js +2 -2
  5. package/build/api/escalations/claim.js +3 -13
  6. package/build/api/escalations/create.js +3 -2
  7. package/build/api/escalations/helpers.d.ts +1 -0
  8. package/build/api/escalations/helpers.js +12 -9
  9. package/build/api/escalations/list.d.ts +1 -0
  10. package/build/api/escalations/list.js +1 -0
  11. package/build/api/escalations/metadata.d.ts +7 -24
  12. package/build/api/escalations/metadata.js +31 -65
  13. package/build/api/escalations/single.js +3 -2
  14. package/build/api/settings.js +5 -0
  15. package/build/api/topics.d.ts +9 -0
  16. package/build/api/topics.js +31 -2
  17. package/build/lib/events/index.d.ts +1 -0
  18. package/build/lib/events/index.js +4 -0
  19. package/build/lib/events/publish.d.ts +12 -9
  20. package/build/lib/events/publish.js +27 -17
  21. package/build/modules/auth.d.ts +7 -0
  22. package/build/modules/auth.js +104 -2
  23. package/build/modules/sso.d.ts +6 -0
  24. package/build/modules/sso.js +20 -0
  25. package/build/routes/auth-sso.d.ts +2 -0
  26. package/build/routes/auth-sso.js +51 -0
  27. package/build/routes/bot-accounts.js +1 -1
  28. package/build/routes/controlplane.js +6 -6
  29. package/build/routes/escalations/list.js +1 -0
  30. package/build/routes/index.js +2 -0
  31. package/build/routes/mcp-endpoint.d.ts +17 -0
  32. package/build/routes/mcp-endpoint.js +70 -0
  33. package/build/routes/roles.js +5 -5
  34. package/build/routes/topics.js +2 -0
  35. package/build/routes/users.js +31 -5
  36. package/build/sdk/index.d.ts +1 -0
  37. package/build/services/agent/input-mapper.js +17 -1
  38. package/build/services/escalation/crud.d.ts +17 -1
  39. package/build/services/escalation/crud.js +62 -13
  40. package/build/services/escalation/queries.d.ts +1 -0
  41. package/build/services/escalation/queries.js +7 -0
  42. package/build/services/escalation/sql.d.ts +14 -5
  43. package/build/services/escalation/sql.js +53 -16
  44. package/build/services/mcp/exposure.d.ts +15 -0
  45. package/build/services/mcp/exposure.js +18 -0
  46. package/build/services/mcp/external-server.d.ts +15 -0
  47. package/build/services/mcp/external-server.js +125 -0
  48. package/build/services/mcp/seed-service-account.d.ts +11 -0
  49. package/build/services/mcp/seed-service-account.js +77 -0
  50. package/build/services/role/index.d.ts +1 -1
  51. package/build/services/role/index.js +2 -2
  52. package/build/services/topics/system-topics.js +29 -25
  53. package/build/services/user/index.d.ts +1 -1
  54. package/build/services/user/index.js +3 -1
  55. package/build/services/user/rbac.d.ts +16 -0
  56. package/build/services/user/rbac.js +31 -0
  57. package/build/services/user/sso-provision.d.ts +19 -0
  58. package/build/services/user/sso-provision.js +62 -0
  59. package/build/services/workflow-invocation.js +5 -3
  60. package/build/start/config.js +6 -0
  61. package/build/start/server.js +2 -0
  62. package/build/start/workers.js +15 -0
  63. package/build/system/index.js +53 -35
  64. package/build/system/mcp-servers/admin/agent-subscriptions.d.ts +5 -0
  65. package/build/system/mcp-servers/admin/agent-subscriptions.js +78 -0
  66. package/build/system/mcp-servers/admin/agents.d.ts +5 -0
  67. package/build/system/mcp-servers/admin/agents.js +103 -0
  68. package/build/system/mcp-servers/admin/bot-accounts.d.ts +5 -0
  69. package/build/system/mcp-servers/admin/bot-accounts.js +126 -0
  70. package/build/system/mcp-servers/admin/controlplane.d.ts +5 -0
  71. package/build/system/mcp-servers/admin/controlplane.js +107 -0
  72. package/build/system/mcp-servers/admin/escalations.js +88 -0
  73. package/build/system/mcp-servers/admin/exports.d.ts +5 -0
  74. package/build/system/mcp-servers/admin/exports.js +101 -0
  75. package/build/system/mcp-servers/admin/index.d.ts +16 -8
  76. package/build/system/mcp-servers/admin/index.js +36 -21
  77. package/build/system/mcp-servers/admin/pipelines.d.ts +5 -0
  78. package/build/system/mcp-servers/admin/pipelines.js +96 -0
  79. package/build/system/mcp-servers/admin/schemas.d.ts +614 -6
  80. package/build/system/mcp-servers/admin/schemas.js +239 -1
  81. package/build/system/mcp-servers/admin/settings.d.ts +5 -0
  82. package/build/system/mcp-servers/admin/settings.js +53 -0
  83. package/build/system/mcp-servers/admin/topics.d.ts +5 -0
  84. package/build/system/mcp-servers/admin/topics.js +101 -0
  85. package/build/system/seed/tool-manifests-admin.d.ts +5077 -188
  86. package/build/system/seed/tool-manifests-admin.js +79 -30
  87. package/build/system/seed/tool-manifests-data.d.ts +20 -0
  88. package/build/system/seed/tool-manifests-data.js +24 -6
  89. package/build/system/seed/tool-manifests-escalation.d.ts +5 -0
  90. package/build/system/seed/tool-manifests-escalation.js +5 -0
  91. package/build/system/seed/tool-manifests-events.d.ts +4 -0
  92. package/build/system/seed/tool-manifests-events.js +4 -0
  93. package/build/system/seed/tool-manifests-knowledge.d.ts +6 -0
  94. package/build/system/seed/tool-manifests-knowledge.js +7 -0
  95. package/build/system/seed/tool-manifests-workflows.d.ts +8 -0
  96. package/build/system/seed/tool-manifests-workflows.js +8 -0
  97. package/build/tsconfig.tsbuildinfo +1 -1
  98. package/build/types/auth.d.ts +71 -0
  99. package/build/types/events.d.ts +17 -6
  100. package/build/types/index.d.ts +1 -1
  101. package/build/types/startup.d.ts +22 -1
  102. package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js → AdminDashboard-BwUGcCxQ.js} +2 -2
  103. package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js.map → AdminDashboard-BwUGcCxQ.js.map} +1 -1
  104. package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js +16 -0
  105. package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js.map +1 -0
  106. package/dashboard/dist/assets/{AgentDetailPage-3mZA7SOb.js → AgentDetailPage-XJpl7wfJ.js} +4 -4
  107. package/dashboard/dist/assets/AgentDetailPage-XJpl7wfJ.js.map +1 -0
  108. package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js → AgentsPage-CGpVG6r8.js} +2 -2
  109. package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js.map → AgentsPage-CGpVG6r8.js.map} +1 -1
  110. package/dashboard/dist/assets/AvailableEscalationsPage-DR1e0TQZ.js +2 -0
  111. package/dashboard/dist/assets/{AvailableEscalationsPage-CA9x9o5s.js.map → AvailableEscalationsPage-DR1e0TQZ.js.map} +1 -1
  112. package/dashboard/dist/assets/BotPicker-BKtjl6IL.js +2 -0
  113. package/dashboard/dist/assets/{BotPicker-BQp_Vs73.js.map → BotPicker-BKtjl6IL.js.map} +1 -1
  114. package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js → CapabilitiesPage-kCB8fyOj.js} +2 -2
  115. package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js.map → CapabilitiesPage-kCB8fyOj.js.map} +1 -1
  116. package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js → CollapsibleSection-C3tU61hB.js} +2 -2
  117. package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js.map → CollapsibleSection-C3tU61hB.js.map} +1 -1
  118. package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js → CredentialsPage-Dt4nJs_B.js} +2 -2
  119. package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js.map → CredentialsPage-Dt4nJs_B.js.map} +1 -1
  120. package/dashboard/dist/assets/CronLabel-BdE6mHyA.js +2 -0
  121. package/dashboard/dist/assets/CronLabel-BdE6mHyA.js.map +1 -0
  122. package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js → CustomDurationPicker-B_Yxfb-u.js} +2 -2
  123. package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js.map → CustomDurationPicker-B_Yxfb-u.js.map} +1 -1
  124. package/dashboard/dist/assets/{DropZone-BkfRoUcm.js → DropZone-CptiQ0wc.js} +2 -2
  125. package/dashboard/dist/assets/{DropZone-BkfRoUcm.js.map → DropZone-CptiQ0wc.js.map} +1 -1
  126. package/dashboard/dist/assets/ElapsedCell-tcGx5PFI.js +2 -0
  127. package/dashboard/dist/assets/{ElapsedCell-BPYm8RA7.js.map → ElapsedCell-tcGx5PFI.js.map} +1 -1
  128. package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js → EscalationsOverview-1KO5dXzk.js} +2 -2
  129. package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js.map → EscalationsOverview-1KO5dXzk.js.map} +1 -1
  130. package/dashboard/dist/assets/{EventTable-DSDzJMer.js → EventTable-DnpsQ6Ew.js} +2 -2
  131. package/dashboard/dist/assets/{EventTable-DSDzJMer.js.map → EventTable-DnpsQ6Ew.js.map} +1 -1
  132. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +2 -0
  133. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +1 -0
  134. package/dashboard/dist/assets/ListToolbar-jrVba7QN.js +2 -0
  135. package/dashboard/dist/assets/{ListToolbar-DEef1_-T.js.map → ListToolbar-jrVba7QN.js.map} +1 -1
  136. package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js → McpOverview-BzyxJyc9.js} +2 -2
  137. package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js.map → McpOverview-BzyxJyc9.js.map} +1 -1
  138. package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js → McpQueryDetailPage-DXNseeKl.js} +2 -2
  139. package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js.map → McpQueryDetailPage-DXNseeKl.js.map} +1 -1
  140. package/dashboard/dist/assets/{McpQueryPage-D14466yi.js → McpQueryPage-WZfTY43_.js} +2 -2
  141. package/dashboard/dist/assets/{McpQueryPage-D14466yi.js.map → McpQueryPage-WZfTY43_.js.map} +1 -1
  142. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +2 -0
  143. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +1 -0
  144. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +2 -0
  145. package/dashboard/dist/assets/{McpRunsPage-aZg057y3.js.map → McpRunsPage-SXyiwc0d.js.map} +1 -1
  146. package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js +2 -0
  147. package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js.map +1 -0
  148. package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js → PageHeader-BuJpMxyu.js} +2 -2
  149. package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js.map → PageHeader-BuJpMxyu.js.map} +1 -1
  150. package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js → PageHeaderWithStats-yD_PTbOl.js} +2 -2
  151. package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js.map → PageHeaderWithStats-yD_PTbOl.js.map} +1 -1
  152. package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js → ProcessDetailPage-DYIfvWyc.js} +2 -2
  153. package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js.map → ProcessDetailPage-DYIfvWyc.js.map} +1 -1
  154. package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js → ProcessesListPage-DR1RGaMl.js} +2 -2
  155. package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js.map → ProcessesListPage-DR1RGaMl.js.map} +1 -1
  156. package/dashboard/dist/assets/{RolePill-BC54Vn-U.js → RolePill-SasQKc_B.js} +2 -2
  157. package/dashboard/dist/assets/{RolePill-BC54Vn-U.js.map → RolePill-SasQKc_B.js.map} +1 -1
  158. package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js → RolesPage-pMERxj15.js} +2 -2
  159. package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js.map → RolesPage-pMERxj15.js.map} +1 -1
  160. package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js → RunAsSelector-B-ksMoEj.js} +2 -2
  161. package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js.map → RunAsSelector-B-ksMoEj.js.map} +1 -1
  162. package/dashboard/dist/assets/ServerName-CHspudaC.js +2 -0
  163. package/dashboard/dist/assets/{ServerName-Q6okiv4f.js.map → ServerName-CHspudaC.js.map} +1 -1
  164. package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js → SwimlaneTimeline-Cr_K5qpu.js} +2 -2
  165. package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js.map → SwimlaneTimeline-Cr_K5qpu.js.map} +1 -1
  166. package/dashboard/dist/assets/{TagInput-D6l1SPWd.js → TagInput-DvF3j8MA.js} +2 -2
  167. package/dashboard/dist/assets/{TagInput-D6l1SPWd.js.map → TagInput-DvF3j8MA.js.map} +1 -1
  168. package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js → TaskDetailPage-BO5p7AEe.js} +2 -2
  169. package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js.map → TaskDetailPage-BO5p7AEe.js.map} +1 -1
  170. package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js → TaskQueuePill-BCQrS2oK.js} +2 -2
  171. package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js.map → TaskQueuePill-BCQrS2oK.js.map} +1 -1
  172. package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js → TasksListPage-BRg-uFtF.js} +2 -2
  173. package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js.map → TasksListPage-BRg-uFtF.js.map} +1 -1
  174. package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js → TimeAgo-BSzN6rAH.js} +2 -2
  175. package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js.map → TimeAgo-BSzN6rAH.js.map} +1 -1
  176. package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js → TimestampCell-DL6zMNEQ.js} +2 -2
  177. package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js.map → TimestampCell-DL6zMNEQ.js.map} +1 -1
  178. package/dashboard/dist/assets/{ToolPill-HcRTggHo.js → ToolPill-1aTqYtzp.js} +2 -2
  179. package/dashboard/dist/assets/{ToolPill-HcRTggHo.js.map → ToolPill-1aTqYtzp.js.map} +1 -1
  180. package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js → ToolTestPanel-fLzNp79U.js} +2 -2
  181. package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js.map → ToolTestPanel-fLzNp79U.js.map} +1 -1
  182. package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js +9 -0
  183. package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js.map +1 -0
  184. package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js → TopicsPage-B3Aa8Haz.js} +2 -2
  185. package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js.map → TopicsPage-B3Aa8Haz.js.map} +1 -1
  186. package/dashboard/dist/assets/{UserName-DX7IBjFn.js → UserName-BjHIJWgh.js} +2 -2
  187. package/dashboard/dist/assets/{UserName-DX7IBjFn.js.map → UserName-BjHIJWgh.js.map} +1 -1
  188. package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js → WorkflowExecutionPage-BQ7AYlQA.js} +2 -2
  189. package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js.map → WorkflowExecutionPage-BQ7AYlQA.js.map} +1 -1
  190. package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js → WorkflowPill-Z-zHRKOK.js} +2 -2
  191. package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js.map → WorkflowPill-Z-zHRKOK.js.map} +1 -1
  192. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +2 -0
  193. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +1 -0
  194. package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js → WorkflowsOverview-B4DUcVxs.js} +2 -2
  195. package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js.map → WorkflowsOverview-B4DUcVxs.js.map} +1 -1
  196. package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js → YamlWorkflowsPage-CnTNOku0.js} +2 -2
  197. package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js.map → YamlWorkflowsPage-CnTNOku0.js.map} +1 -1
  198. package/dashboard/dist/assets/{agents-B-P5MlEx.js → agents-CkvQDr9b.js} +2 -2
  199. package/dashboard/dist/assets/{agents-B-P5MlEx.js.map → agents-CkvQDr9b.js.map} +1 -1
  200. package/dashboard/dist/assets/{bots-CZz9iVys.js → bots-CzuMCVgU.js} +2 -2
  201. package/dashboard/dist/assets/{bots-CZz9iVys.js.map → bots-CzuMCVgU.js.map} +1 -1
  202. package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js → capabilities-CbGmS0ty.js} +2 -2
  203. package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js.map → capabilities-CbGmS0ty.js.map} +1 -1
  204. package/dashboard/dist/assets/{controlplane-cj-1c-1C.js → controlplane-DGvwkuYx.js} +2 -2
  205. package/dashboard/dist/assets/{controlplane-cj-1c-1C.js.map → controlplane-DGvwkuYx.js.map} +1 -1
  206. package/dashboard/dist/assets/{escalation-BEVFyQnE.js → escalation-B7ysVToF.js} +2 -2
  207. package/dashboard/dist/assets/{escalation-BEVFyQnE.js.map → escalation-B7ysVToF.js.map} +1 -1
  208. package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js → escalation-columns-CHQEJU1j.js} +2 -2
  209. package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js.map → escalation-columns-CHQEJU1j.js.map} +1 -1
  210. package/dashboard/dist/assets/{helpers-B4gzNq9h.js → helpers-BFOjXa4r.js} +2 -2
  211. package/dashboard/dist/assets/{helpers-B4gzNq9h.js.map → helpers-BFOjXa4r.js.map} +1 -1
  212. package/dashboard/dist/assets/index-B9_1AZaG.js +2 -0
  213. package/dashboard/dist/assets/{index-3n5VREXN.js.map → index-B9_1AZaG.js.map} +1 -1
  214. package/dashboard/dist/assets/{index-BCQ65lNu.js → index-BFaDxPxA.js} +2 -2
  215. package/dashboard/dist/assets/{index-BCQ65lNu.js.map → index-BFaDxPxA.js.map} +1 -1
  216. package/dashboard/dist/assets/index-BduDiGcw.js +15 -0
  217. package/dashboard/dist/assets/{index-UtAfnStw.js.map → index-BduDiGcw.js.map} +1 -1
  218. package/dashboard/dist/assets/{index-Bh-PnP17.js → index-BeLphL59.js} +2 -2
  219. package/dashboard/dist/assets/{index-Bh-PnP17.js.map → index-BeLphL59.js.map} +1 -1
  220. package/dashboard/dist/assets/index-C--SEsU7.css +1 -0
  221. package/dashboard/dist/assets/{index-_DfbFHXk.js → index-CRiBkHPb.js} +2 -2
  222. package/dashboard/dist/assets/{index-_DfbFHXk.js.map → index-CRiBkHPb.js.map} +1 -1
  223. package/dashboard/dist/assets/{index-DdKbIZNE.js → index-CbrMW-gM.js} +2 -2
  224. package/dashboard/dist/assets/{index-DdKbIZNE.js.map → index-CbrMW-gM.js.map} +1 -1
  225. package/dashboard/dist/assets/{index-aJRDh4zW.js → index-CvOGgvzP.js} +2 -2
  226. package/dashboard/dist/assets/{index-aJRDh4zW.js.map → index-CvOGgvzP.js.map} +1 -1
  227. package/dashboard/dist/assets/{index-D1MywQ2z.js → index-DDlrQeTj.js} +2 -2
  228. package/dashboard/dist/assets/{index-D1MywQ2z.js.map → index-DDlrQeTj.js.map} +1 -1
  229. package/dashboard/dist/assets/{index-BYXiz05a.js → index-DQHmfTPo.js} +2 -2
  230. package/dashboard/dist/assets/{index-BYXiz05a.js.map → index-DQHmfTPo.js.map} +1 -1
  231. package/dashboard/dist/assets/{index-BpN31nuC.js → index-_BRA9uFL.js} +25 -25
  232. package/dashboard/dist/assets/index-_BRA9uFL.js.map +1 -0
  233. package/dashboard/dist/assets/index-a98qWLB-.js +2 -0
  234. package/dashboard/dist/assets/index-a98qWLB-.js.map +1 -0
  235. package/dashboard/dist/assets/index-l_8R6U4r.js +6 -0
  236. package/dashboard/dist/assets/index-l_8R6U4r.js.map +1 -0
  237. package/dashboard/dist/assets/{index-D4KGadbW.js → index-v0OQpgXS.js} +2 -2
  238. package/dashboard/dist/assets/{index-D4KGadbW.js.map → index-v0OQpgXS.js.map} +1 -1
  239. package/dashboard/dist/assets/{knowledge-DhtKWMON.js → knowledge-BlF8UMrk.js} +2 -2
  240. package/dashboard/dist/assets/{knowledge-DhtKWMON.js.map → knowledge-BlF8UMrk.js.map} +1 -1
  241. package/dashboard/dist/assets/{mcp-BXN7-wGF.js → mcp-MtXuky8q.js} +2 -2
  242. package/dashboard/dist/assets/{mcp-BXN7-wGF.js.map → mcp-MtXuky8q.js.map} +1 -1
  243. package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js → mcp-query-DQ-J1Q0K.js} +2 -2
  244. package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js.map → mcp-query-DQ-J1Q0K.js.map} +1 -1
  245. package/dashboard/dist/assets/{namespaces-ne_yDQZX.js → namespaces-DtsT_GoV.js} +2 -2
  246. package/dashboard/dist/assets/{namespaces-ne_yDQZX.js.map → namespaces-DtsT_GoV.js.map} +1 -1
  247. package/dashboard/dist/assets/{pipelines-Bcz62DoS.js → pipelines-BjlCm9VH.js} +2 -2
  248. package/dashboard/dist/assets/{pipelines-Bcz62DoS.js.map → pipelines-BjlCm9VH.js.map} +1 -1
  249. package/dashboard/dist/assets/{roles-De2CzGCy.js → roles-D-LhJ82d.js} +2 -2
  250. package/dashboard/dist/assets/{roles-De2CzGCy.js.map → roles-D-LhJ82d.js.map} +1 -1
  251. package/dashboard/dist/assets/{tasks-4yL5EfxI.js → tasks-BrP_8uEN.js} +2 -2
  252. package/dashboard/dist/assets/{tasks-4yL5EfxI.js.map → tasks-BrP_8uEN.js.map} +1 -1
  253. package/dashboard/dist/assets/topics-DUk-zX5D.js +2 -0
  254. package/dashboard/dist/assets/{topics-DDKHpRwP.js.map → topics-DUk-zX5D.js.map} +1 -1
  255. package/dashboard/dist/assets/useEventHooks-XNNzwADV.js +2 -0
  256. package/dashboard/dist/assets/useEventHooks-XNNzwADV.js.map +1 -0
  257. package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js → useYamlActivityEvents-DANQ5jIY.js} +2 -2
  258. package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js.map → useYamlActivityEvents-DANQ5jIY.js.map} +1 -1
  259. package/dashboard/dist/assets/{users-pSMWP58G.js → users-vj0JgOkA.js} +2 -2
  260. package/dashboard/dist/assets/{users-pSMWP58G.js.map → users-vj0JgOkA.js.map} +1 -1
  261. package/dashboard/dist/assets/{vendor-icons-CrrAvF2g.js → vendor-icons-Doy0g69_.js} +116 -111
  262. package/dashboard/dist/assets/vendor-icons-Doy0g69_.js.map +1 -0
  263. package/dashboard/dist/assets/{workflows-COYPOe2I.js → workflows-CmqgGPzI.js} +2 -2
  264. package/dashboard/dist/assets/{workflows-COYPOe2I.js.map → workflows-CmqgGPzI.js.map} +1 -1
  265. package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js → yaml-workflows-DNFyjBXH.js} +2 -2
  266. package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js.map → yaml-workflows-DNFyjBXH.js.map} +1 -1
  267. package/dashboard/dist/index.html +3 -3
  268. package/docs/api/http/controlplane.md +1 -1
  269. package/docs/api/http/mcp-endpoint.md +133 -0
  270. package/docs/api/http/roles.md +46 -0
  271. package/docs/api/http/service-accounts.md +15 -0
  272. package/docs/api/http/settings.md +6 -0
  273. package/docs/api/mcp/admin.md +1187 -0
  274. package/docs/api/mcp/claude-code.md +47 -0
  275. package/docs/api/mcp/docs.md +54 -0
  276. package/docs/api/mcp/events.md +80 -0
  277. package/docs/api/mcp/file-storage.md +76 -0
  278. package/docs/api/mcp/http-fetch.md +64 -0
  279. package/docs/api/mcp/human-queue.md +101 -0
  280. package/docs/api/mcp/index.md +52 -0
  281. package/docs/api/mcp/knowledge.md +125 -0
  282. package/docs/api/mcp/oauth.md +62 -0
  283. package/docs/api/mcp/schema-exchange.md +56 -0
  284. package/docs/api/mcp/translation.md +28 -0
  285. package/docs/api/mcp/vision.md +46 -0
  286. package/docs/api/sdk/settings.md +3 -1
  287. package/docs/auth.md +109 -0
  288. package/docs/dashboard.md +1 -1
  289. package/package.json +1 -1
  290. package/build/system/mcp-servers/playwright/browser-lifecycle.d.ts +0 -26
  291. package/build/system/mcp-servers/playwright/browser-lifecycle.js +0 -125
  292. package/build/system/mcp-servers/playwright/index.d.ts +0 -25
  293. package/build/system/mcp-servers/playwright/index.js +0 -42
  294. package/build/system/mcp-servers/playwright/schemas.d.ts +0 -394
  295. package/build/system/mcp-servers/playwright/schemas.js +0 -90
  296. package/build/system/mcp-servers/playwright/tools-atomic.d.ts +0 -2
  297. package/build/system/mcp-servers/playwright/tools-atomic.js +0 -9
  298. package/build/system/mcp-servers/playwright/tools-navigation.d.ts +0 -2
  299. package/build/system/mcp-servers/playwright/tools-navigation.js +0 -153
  300. package/build/system/mcp-servers/playwright/tools-page-interaction.d.ts +0 -2
  301. package/build/system/mcp-servers/playwright/tools-page-interaction.js +0 -162
  302. package/build/system/mcp-servers/playwright/tools-run-script.d.ts +0 -2
  303. package/build/system/mcp-servers/playwright/tools-run-script.js +0 -207
  304. package/build/system/mcp-servers/playwright/types.d.ts +0 -8
  305. package/build/system/mcp-servers/playwright/types.js +0 -30
  306. package/build/system/mcp-servers/playwright/vision-helper.d.ts +0 -12
  307. package/build/system/mcp-servers/playwright/vision-helper.js +0 -81
  308. package/build/system/mcp-servers/playwright-cli/helpers.d.ts +0 -11
  309. package/build/system/mcp-servers/playwright-cli/helpers.js +0 -20
  310. package/build/system/mcp-servers/playwright-cli/index.d.ts +0 -4
  311. package/build/system/mcp-servers/playwright-cli/index.js +0 -15
  312. package/build/system/mcp-servers/playwright-cli/schemas.d.ts +0 -219
  313. package/build/system/mcp-servers/playwright-cli/schemas.js +0 -75
  314. package/build/system/mcp-servers/playwright-cli/tools-auth.d.ts +0 -2
  315. package/build/system/mcp-servers/playwright-cli/tools-auth.js +0 -183
  316. package/build/system/mcp-servers/playwright-cli/tools-capture.d.ts +0 -2
  317. package/build/system/mcp-servers/playwright-cli/tools-capture.js +0 -273
  318. package/build/system/seed/tool-manifests-browser.d.ts +0 -577
  319. package/build/system/seed/tool-manifests-browser.js +0 -158
  320. package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js +0 -16
  321. package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js.map +0 -1
  322. package/dashboard/dist/assets/AgentDetailPage-3mZA7SOb.js.map +0 -1
  323. package/dashboard/dist/assets/AvailableEscalationsPage-CA9x9o5s.js +0 -2
  324. package/dashboard/dist/assets/BotPicker-BQp_Vs73.js +0 -2
  325. package/dashboard/dist/assets/CronLabel-DY8VdTS9.js +0 -2
  326. package/dashboard/dist/assets/CronLabel-DY8VdTS9.js.map +0 -1
  327. package/dashboard/dist/assets/ElapsedCell-BPYm8RA7.js +0 -2
  328. package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js +0 -2
  329. package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js.map +0 -1
  330. package/dashboard/dist/assets/HomePage-CwRebzmO.js +0 -2
  331. package/dashboard/dist/assets/HomePage-CwRebzmO.js.map +0 -1
  332. package/dashboard/dist/assets/ListToolbar-DEef1_-T.js +0 -2
  333. package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js +0 -2
  334. package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js.map +0 -1
  335. package/dashboard/dist/assets/McpRunsPage-aZg057y3.js +0 -2
  336. package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js +0 -2
  337. package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js.map +0 -1
  338. package/dashboard/dist/assets/ServerName-Q6okiv4f.js +0 -2
  339. package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js +0 -9
  340. package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js.map +0 -1
  341. package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js +0 -2
  342. package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js.map +0 -1
  343. package/dashboard/dist/assets/index-3n5VREXN.js +0 -2
  344. package/dashboard/dist/assets/index-BAXzN-QB.js +0 -6
  345. package/dashboard/dist/assets/index-BAXzN-QB.js.map +0 -1
  346. package/dashboard/dist/assets/index-BpN31nuC.js.map +0 -1
  347. package/dashboard/dist/assets/index-C37LMzJa.css +0 -1
  348. package/dashboard/dist/assets/index-C5dHozmW.js +0 -2
  349. package/dashboard/dist/assets/index-C5dHozmW.js.map +0 -1
  350. package/dashboard/dist/assets/index-UtAfnStw.js +0 -15
  351. package/dashboard/dist/assets/topics-DDKHpRwP.js +0 -2
  352. package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js +0 -2
  353. package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js.map +0 -1
  354. package/dashboard/dist/assets/vendor-icons-CrrAvF2g.js.map +0 -1
package/README.md CHANGED
@@ -62,8 +62,6 @@ Dashboard at [http://localhost:3000](http://localhost:3000). The [boilerplate](h
62
62
 
63
63
  ## The pattern
64
64
 
65
- Most systems start with a durable workflow and stop there. Long Tail keeps going.
66
-
67
65
  **Step 1 — Author a durable workflow.** Your function checkpoints to Postgres. It can sleep, branch, call child workflows, wait for signals. Standard durable execution.
68
66
 
69
67
  **Step 2 — Certify it.** Promotion to certified adds interceptor guarantees: failures escalate instead of throwing, escalation chains route through RBAC-scoped roles, and every error is either handled or surfaced. It cannot silently fail.
@@ -0,0 +1,12 @@
1
+ import type { Request } from 'express';
2
+ import type { LTApiResult } from '../types/sdk';
3
+ /**
4
+ * Exchange host authentication for a Long Tail JWT.
5
+ *
6
+ * Calls `sso.resolve(req)` to extract the host identity, JIT provisions
7
+ * the user in `lt_users`, and returns a signed JWT the dashboard can
8
+ * store for subsequent API calls.
9
+ *
10
+ * No request body required — the host's cookies/headers carry the auth.
11
+ */
12
+ export declare function exchangeSSO(req: Request): Promise<LTApiResult>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exchangeSSO = exchangeSSO;
4
+ const sso_1 = require("../modules/sso");
5
+ const sso_provision_1 = require("../services/user/sso-provision");
6
+ const auth_1 = require("../modules/auth");
7
+ /**
8
+ * Exchange host authentication for a Long Tail JWT.
9
+ *
10
+ * Calls `sso.resolve(req)` to extract the host identity, JIT provisions
11
+ * the user in `lt_users`, and returns a signed JWT the dashboard can
12
+ * store for subsequent API calls.
13
+ *
14
+ * No request body required — the host's cookies/headers carry the auth.
15
+ */
16
+ async function exchangeSSO(req) {
17
+ try {
18
+ const ssoConfig = (0, sso_1.getSSOConfig)();
19
+ if (!ssoConfig) {
20
+ return { status: 404, error: 'SSO not configured' };
21
+ }
22
+ const identity = await ssoConfig.resolve(req);
23
+ if (!identity) {
24
+ return { status: 401, error: 'Host authentication required' };
25
+ }
26
+ const provisioned = await (0, sso_provision_1.ssoProvision)(identity, ssoConfig);
27
+ const highestType = provisioned.roles.some((r) => r.type === 'superadmin')
28
+ ? 'superadmin'
29
+ : provisioned.roles.some((r) => r.type === 'admin')
30
+ ? 'admin'
31
+ : 'member';
32
+ const token = (0, auth_1.signToken)({
33
+ userId: provisioned.userId,
34
+ role: highestType,
35
+ roles: provisioned.roles,
36
+ sso: true,
37
+ }, '24h');
38
+ return {
39
+ status: 200,
40
+ data: {
41
+ token,
42
+ user: {
43
+ id: provisioned.userId,
44
+ external_id: identity.externalId,
45
+ display_name: identity.displayName || identity.externalId,
46
+ roles: provisioned.roles,
47
+ },
48
+ },
49
+ };
50
+ }
51
+ catch (err) {
52
+ return { status: 500, error: err.message };
53
+ }
54
+ }
@@ -141,8 +141,8 @@ async function bulkAssign(input, auth) {
141
141
  if (!perm.allowed)
142
142
  return perm;
143
143
  // Non-superadmin: target user must hold each escalation's role
144
- const isSuperAdminUser = await userService.isSuperAdmin(auth.userId);
145
- if (!isSuperAdminUser) {
144
+ const hasGlobal = await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId);
145
+ if (!hasGlobal) {
146
146
  const roles = await escalationService.getEscalationRoles(ids);
147
147
  for (const role of roles) {
148
148
  const targetHasRole = await userService.hasRole(targetUserId, role);
@@ -37,7 +37,7 @@ exports.claimEscalation = claimEscalation;
37
37
  exports.releaseEscalation = releaseEscalation;
38
38
  const escalationService = __importStar(require("../../services/escalation"));
39
39
  const userService = __importStar(require("../../services/user"));
40
- const publish_1 = require("../../lib/events/publish");
40
+ const helpers_1 = require("./helpers");
41
41
  /**
42
42
  * Claim a pending escalation for the authenticated user.
43
43
  *
@@ -57,8 +57,8 @@ async function claimEscalation(input, auth) {
57
57
  if (!escalation) {
58
58
  return { status: 404, error: 'Escalation not found' };
59
59
  }
60
- const isSuperAdminUser = await userService.isSuperAdmin(auth.userId);
61
- if (!isSuperAdminUser) {
60
+ const hasGlobal = await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId);
61
+ if (!hasGlobal) {
62
62
  const userHasRole = await userService.hasRole(auth.userId, escalation.role);
63
63
  if (!userHasRole) {
64
64
  return {
@@ -94,16 +94,6 @@ async function releaseEscalation(input, auth) {
94
94
  if (!result) {
95
95
  return { status: 409, error: 'Escalation not found or not claimed by you' };
96
96
  }
97
- (0, publish_1.publishEscalationEvent)({
98
- type: 'escalation.released',
99
- source: 'api',
100
- workflowId: result.workflow_id || '',
101
- workflowName: result.workflow_type || '',
102
- taskQueue: result.task_queue || '',
103
- escalationId: input.id,
104
- status: 'released',
105
- data: { released_by: auth.userId },
106
- });
107
97
  return { status: 200, data: { escalation: result } };
108
98
  }
109
99
  catch (err) {
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.createEscalation = createEscalation;
37
37
  const escalationService = __importStar(require("../../services/escalation"));
38
38
  const userService = __importStar(require("../../services/user"));
39
+ const helpers_1 = require("./helpers");
39
40
  // ── Create ────────────────────────────────────────────────────────────────
40
41
  /**
41
42
  * Create a standalone escalation (not tied to a workflow).
@@ -65,8 +66,8 @@ async function createEscalation(input, auth) {
65
66
  return { status: 400, error: 'role is required' };
66
67
  }
67
68
  // RBAC: caller must hold the target role or be superadmin
68
- const isSuperAdminUser = await userService.isSuperAdmin(auth.userId);
69
- if (!isSuperAdminUser) {
69
+ const hasGlobal = await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId);
70
+ if (!hasGlobal) {
70
71
  const userHasRole = await userService.hasRole(auth.userId, role);
71
72
  if (!userHasRole) {
72
73
  return { status: 403, error: `You must hold the "${role}" role or be a superadmin to create escalations for it` };
@@ -1,3 +1,4 @@
1
+ export { hasGlobalEscalationAccess } from '../../services/user';
1
2
  export declare function getVisibleRoles(userId: string): Promise<string[] | undefined>;
2
3
  export declare function validateIds(ids: unknown): ids is string[];
3
4
  export declare function checkBulkPermission(userId: string, ids: string[]): Promise<{
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.hasGlobalEscalationAccess = void 0;
36
37
  exports.getVisibleRoles = getVisibleRoles;
37
38
  exports.validateIds = validateIds;
38
39
  exports.checkBulkPermission = checkBulkPermission;
@@ -42,9 +43,11 @@ const escalationService = __importStar(require("../../services/escalation"));
42
43
  const userService = __importStar(require("../../services/user"));
43
44
  const publish_1 = require("../../lib/events/publish");
44
45
  // ── Private helpers ────────────────────────────────────────────────────────
46
+ // Re-export from service layer for use by escalation API modules
47
+ var user_1 = require("../../services/user");
48
+ Object.defineProperty(exports, "hasGlobalEscalationAccess", { enumerable: true, get: function () { return user_1.hasGlobalEscalationAccess; } });
45
49
  async function getVisibleRoles(userId) {
46
- const isSuperAdminUser = await userService.isSuperAdmin(userId);
47
- if (isSuperAdminUser)
50
+ if (await userService.hasGlobalEscalationAccess(userId))
48
51
  return undefined;
49
52
  const userRoles = await userService.getUserRoles(userId);
50
53
  return userRoles.map((r) => r.role);
@@ -53,15 +56,15 @@ function validateIds(ids) {
53
56
  return Array.isArray(ids) && ids.length > 0;
54
57
  }
55
58
  async function checkBulkPermission(userId, ids) {
56
- const isSuperAdminUser = await userService.isSuperAdmin(userId);
57
- if (isSuperAdminUser)
59
+ if (await userService.hasGlobalEscalationAccess(userId))
58
60
  return { allowed: true };
59
61
  const roles = await escalationService.getEscalationRoles(ids);
60
- for (const role of roles) {
61
- const canManage = await userService.isGroupAdmin(userId, role);
62
- if (!canManage) {
63
- return { allowed: false, status: 403, error: `Insufficient permissions for role "${role}"` };
64
- }
62
+ if (!roles.length)
63
+ return { allowed: true };
64
+ // Single batched query instead of N+1 loop
65
+ const canManageAll = await userService.hasRolesAsAdmin(userId, roles);
66
+ if (!canManageAll) {
67
+ return { allowed: false, status: 403, error: 'Insufficient permissions for one or more escalation roles' };
65
68
  }
66
69
  return { allowed: true };
67
70
  }
@@ -24,6 +24,7 @@ export declare function listEscalations(input: {
24
24
  type?: string;
25
25
  subtype?: string;
26
26
  assigned_to?: string;
27
+ claimed?: boolean;
27
28
  priority?: number;
28
29
  limit?: number;
29
30
  offset?: number;
@@ -71,6 +71,7 @@ async function listEscalations(input, auth) {
71
71
  type: input.type,
72
72
  subtype: input.subtype,
73
73
  assigned_to: input.assigned_to,
74
+ claimed: input.claimed,
74
75
  priority: input.priority,
75
76
  limit: input.limit,
76
77
  offset: input.offset,
@@ -2,13 +2,8 @@ import type { LTApiAuth, LTApiResult } from '../../types/sdk';
2
2
  /**
3
3
  * Find escalations by a metadata key-value pair.
4
4
  *
5
- * Uses JSONB containment (`@>`) backed by a GIN index.
6
- * Results are RBAC-scoped to the caller's visible roles.
7
- *
8
- * @param input.key — metadata field name (e.g. `"orderId"`)
9
- * @param input.value — metadata field value (e.g. `"order-123"`)
10
- * @param input.status — optional status filter (e.g. `"pending"`)
11
- * @returns `{ status: 200, data: { escalations, total } }`
5
+ * Single query with window function for count. Results are
6
+ * RBAC-scoped to the caller's visible roles.
12
7
  */
13
8
  export declare function findByMetadata(input: {
14
9
  key: string;
@@ -20,15 +15,9 @@ export declare function findByMetadata(input: {
20
15
  /**
21
16
  * Claim an escalation by metadata key-value pair.
22
17
  *
23
- * Finds one available (pending + unassigned/expired) escalation matching
24
- * the metadata and claims it atomically. Optionally resolves an assignee
25
- * from an external_id.
26
- *
27
- * @param input.key — metadata field name
28
- * @param input.value — metadata field value
29
- * @param input.durationMinutes — claim duration (default 30)
30
- * @param input.assignee — optional external_id of the user to claim as
31
- * @returns `{ status: 200, data: { escalation, isExtension } }`
18
+ * Single atomic query. RBAC is enforced in the SQL WHERE clause —
19
+ * if the caller doesn't have an allowed role, zero rows match and
20
+ * the claim never happens. No pre-flight find, no TOCTOU.
32
21
  */
33
22
  export declare function claimByMetadata(input: {
34
23
  key: string;
@@ -40,14 +29,8 @@ export declare function claimByMetadata(input: {
40
29
  /**
41
30
  * Resolve an escalation by metadata key-value pair.
42
31
  *
43
- * Finds the pending escalation, auto-claims if unclaimed, then delegates
44
- * to the standard resolve logic (supports all 5 resolution paths).
45
- *
46
- * @param input.key — metadata field name
47
- * @param input.value — metadata field value
48
- * @param input.resolverPayload — resolution data for the workflow
49
- * @param input.assignee — optional external_id of the resolving user
50
- * @returns result from the standard resolve endpoint
32
+ * Single atomic CTE: find + claim + resolve in one query.
33
+ * RBAC is enforced in the SQL WHERE clause.
51
34
  */
52
35
  export declare function resolveByMetadata(input: {
53
36
  key: string;
@@ -42,13 +42,8 @@ const helpers_1 = require("./helpers");
42
42
  /**
43
43
  * Find escalations by a metadata key-value pair.
44
44
  *
45
- * Uses JSONB containment (`@>`) backed by a GIN index.
46
- * Results are RBAC-scoped to the caller's visible roles.
47
- *
48
- * @param input.key — metadata field name (e.g. `"orderId"`)
49
- * @param input.value — metadata field value (e.g. `"order-123"`)
50
- * @param input.status — optional status filter (e.g. `"pending"`)
51
- * @returns `{ status: 200, data: { escalations, total } }`
45
+ * Single query with window function for count. Results are
46
+ * RBAC-scoped to the caller's visible roles.
52
47
  */
53
48
  async function findByMetadata(input, auth) {
54
49
  try {
@@ -72,15 +67,9 @@ async function findByMetadata(input, auth) {
72
67
  /**
73
68
  * Claim an escalation by metadata key-value pair.
74
69
  *
75
- * Finds one available (pending + unassigned/expired) escalation matching
76
- * the metadata and claims it atomically. Optionally resolves an assignee
77
- * from an external_id.
78
- *
79
- * @param input.key — metadata field name
80
- * @param input.value — metadata field value
81
- * @param input.durationMinutes — claim duration (default 30)
82
- * @param input.assignee — optional external_id of the user to claim as
83
- * @returns `{ status: 200, data: { escalation, isExtension } }`
70
+ * Single atomic query. RBAC is enforced in the SQL WHERE clause —
71
+ * if the caller doesn't have an allowed role, zero rows match and
72
+ * the claim never happens. No pre-flight find, no TOCTOU.
84
73
  */
85
74
  async function claimByMetadata(input, auth) {
86
75
  try {
@@ -91,25 +80,17 @@ async function claimByMetadata(input, auth) {
91
80
  if ('error' in resolved)
92
81
  return resolved.error;
93
82
  const claimUserId = resolved.userId;
94
- // RBAC: find the candidate to check role membership before atomic claim
95
- const candidates = await escalationService.findByMetadata(input.key, input.value, 'pending', 1, 0);
96
- if (candidates.escalations.length === 0) {
83
+ // Resolve allowed roles: null = global access (no filter), string[] = scoped
84
+ const allowedRoles = await resolveAllowedRoles(auth.userId);
85
+ const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes, input.metadata, allowedRoles);
86
+ if (!result) {
87
+ // No rows matched. Check if candidates existed (role mismatch vs no match).
97
88
  return { status: 404, error: 'No pending escalation found for this metadata' };
98
89
  }
99
- const candidate = candidates.escalations[0];
100
- const isSuperAdmin = await userService.isSuperAdmin(auth.userId);
101
- if (!isSuperAdmin) {
102
- const userHasRole = await userService.hasRole(claimUserId, candidate.role);
103
- if (!userHasRole) {
104
- return { status: 403, error: `User must have the "${candidate.role}" role to claim this escalation` };
105
- }
90
+ if (result.candidatesExist > 0 && !result.escalation) {
91
+ return { status: 403, error: 'Escalation exists but your roles do not permit claiming it' };
106
92
  }
107
- const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes, input.metadata);
108
- if (!result) {
109
- return { status: 409, error: 'Escalation not available for claim' };
110
- }
111
- // Event published by service layer (services/escalation/crud.ts)
112
- return { status: 200, data: result };
93
+ return { status: 200, data: { escalation: result.escalation, isExtension: result.isExtension } };
113
94
  }
114
95
  catch (err) {
115
96
  return { status: 500, error: err.message };
@@ -118,14 +99,8 @@ async function claimByMetadata(input, auth) {
118
99
  /**
119
100
  * Resolve an escalation by metadata key-value pair.
120
101
  *
121
- * Finds the pending escalation, auto-claims if unclaimed, then delegates
122
- * to the standard resolve logic (supports all 5 resolution paths).
123
- *
124
- * @param input.key — metadata field name
125
- * @param input.value — metadata field value
126
- * @param input.resolverPayload — resolution data for the workflow
127
- * @param input.assignee — optional external_id of the resolving user
128
- * @returns result from the standard resolve endpoint
102
+ * Single atomic CTE: find + claim + resolve in one query.
103
+ * RBAC is enforced in the SQL WHERE clause.
129
104
  */
130
105
  async function resolveByMetadata(input, auth) {
131
106
  try {
@@ -135,38 +110,29 @@ async function resolveByMetadata(input, auth) {
135
110
  if (!input.resolverPayload) {
136
111
  return { status: 400, error: 'resolverPayload is required' };
137
112
  }
138
- const candidates = await escalationService.findByMetadata(input.key, input.value, 'pending', 1, 0);
139
- if (candidates.escalations.length === 0) {
140
- return { status: 404, error: 'No pending escalation found for this metadata' };
141
- }
142
- const escalation = candidates.escalations[0];
143
113
  const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth);
144
114
  if ('error' in resolved)
145
115
  return resolved.error;
146
116
  const resolveUserId = resolved.userId;
147
- const isSuperAdmin = await userService.isSuperAdmin(auth.userId);
148
- if (!isSuperAdmin) {
149
- const userHasRole = await userService.hasRole(resolveUserId, escalation.role);
150
- if (!userHasRole) {
151
- return { status: 403, error: `User must have the "${escalation.role}" role` };
152
- }
153
- }
154
- // Merge additional metadata if provided
155
- if (input.metadata && Object.keys(input.metadata).length > 0) {
156
- await escalationService.updateEscalationMetadata(escalation.id, input.metadata);
157
- }
158
- // Auto-claim if unclaimed or expired
159
- const isClaimed = escalation.assigned_to &&
160
- escalation.assigned_until &&
161
- new Date(escalation.assigned_until) > new Date();
162
- if (!isClaimed) {
163
- await escalationService.claimEscalation(escalation.id, resolveUserId, 5);
117
+ 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) {
120
+ return { status: 404, error: 'No pending escalation found for this metadata, or insufficient role permissions' };
164
121
  }
165
- // Delegate to the full resolve logic (handles all 5 resolution paths)
166
- const { resolveEscalation } = await Promise.resolve().then(() => __importStar(require('./resolve')));
167
- return resolveEscalation({ id: escalation.id, resolverPayload: input.resolverPayload }, auth);
122
+ return { status: 200, data: { escalation } };
168
123
  }
169
124
  catch (err) {
170
125
  return { status: 500, error: err.message };
171
126
  }
172
127
  }
128
+ // ── Helpers ──────────────────────────────────────────────────────────────────
129
+ /**
130
+ * Resolve the set of roles the caller is allowed to act on.
131
+ * Returns null for global access (superadmin/admin), or string[] for scoped users.
132
+ */
133
+ async function resolveAllowedRoles(userId) {
134
+ if (await userService.hasGlobalEscalationAccess(userId))
135
+ return null;
136
+ const userRoles = await userService.getUserRoles(userId);
137
+ return userRoles.map(r => r.role);
138
+ }
@@ -39,6 +39,7 @@ exports.escalateToRole = escalateToRole;
39
39
  const escalationService = __importStar(require("../../services/escalation"));
40
40
  const userService = __importStar(require("../../services/user"));
41
41
  const roleService = __importStar(require("../../services/role"));
42
+ const helpers_1 = require("./helpers");
42
43
  // ── Single-escalation routes ───────────────────────────────────────────────
43
44
  /**
44
45
  * Get a single escalation by ID.
@@ -55,8 +56,8 @@ async function getEscalation(input, auth) {
55
56
  if (!escalation) {
56
57
  return { status: 404, error: 'Escalation not found' };
57
58
  }
58
- const isSuperAdminUser = await userService.isSuperAdmin(auth.userId);
59
- if (!isSuperAdminUser) {
59
+ const hasGlobal = await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId);
60
+ if (!hasGlobal) {
60
61
  const userHasRole = await userService.hasRole(auth.userId, escalation.role);
61
62
  if (!userHasRole) {
62
63
  return { status: 403, error: 'Not authorized to view this escalation' };
@@ -7,6 +7,7 @@ const nats_1 = require("../lib/events/nats");
7
7
  const socketio_1 = require("../lib/events/socketio");
8
8
  const nats_ws_proxy_1 = require("../lib/events/nats-ws-proxy");
9
9
  const config_1 = require("../modules/config");
10
+ const sso_1 = require("../modules/sso");
10
11
  const defaults_1 = require("../modules/defaults");
11
12
  const llm_1 = require("../services/llm");
12
13
  /**
@@ -60,6 +61,10 @@ async function getSettings(req) {
60
61
  transport,
61
62
  natsWsUrl: natsAdapter ? resolveNatsWsUrl(natsAdapter, req) : null,
62
63
  },
64
+ auth: {
65
+ sso: (0, sso_1.isSSOEnabled)(),
66
+ ssoLogoutUrl: (0, sso_1.getSSOConfig)()?.logoutUrl ?? null,
67
+ },
63
68
  ai: {
64
69
  enabled: (0, llm_1.hasLLMApiKey)(),
65
70
  },
@@ -20,8 +20,17 @@ export declare function updateTopic(input: {
20
20
  export declare function deleteTopic(input: {
21
21
  topic: string;
22
22
  }): Promise<LTApiResult>;
23
+ /**
24
+ * Validate that a subject is a valid variant of a topic pattern.
25
+ * Each `*` in the pattern matches exactly one literal segment in the subject.
26
+ * Each `>` in the pattern matches one or more trailing segments.
27
+ * Literal segments must match exactly.
28
+ */
29
+ export declare function isValidVariant(pattern: string, subject: string): boolean;
23
30
  export declare function publishTopic(input: {
24
31
  topic: string;
32
+ subject?: string;
33
+ eventId?: string;
25
34
  data: Record<string, any>;
26
35
  source?: string;
27
36
  }): Promise<LTApiResult>;
@@ -38,6 +38,7 @@ exports.getTopic = getTopic;
38
38
  exports.createTopic = createTopic;
39
39
  exports.updateTopic = updateTopic;
40
40
  exports.deleteTopic = deleteTopic;
41
+ exports.isValidVariant = isValidVariant;
41
42
  exports.publishTopic = publishTopic;
42
43
  const topicService = __importStar(require("../services/topics"));
43
44
  const events_1 = require("../lib/events");
@@ -104,10 +105,38 @@ async function deleteTopic(input) {
104
105
  return { status: 500, error: err.message };
105
106
  }
106
107
  }
108
+ /**
109
+ * Validate that a subject is a valid variant of a topic pattern.
110
+ * Each `*` in the pattern matches exactly one literal segment in the subject.
111
+ * Each `>` in the pattern matches one or more trailing segments.
112
+ * Literal segments must match exactly.
113
+ */
114
+ function isValidVariant(pattern, subject) {
115
+ const patternParts = pattern.split('.');
116
+ const subjectParts = subject.split('.');
117
+ let pi = 0;
118
+ let si = 0;
119
+ while (pi < patternParts.length && si < subjectParts.length) {
120
+ const pp = patternParts[pi];
121
+ if (pp === '>')
122
+ return true; // match-rest: everything from here is valid
123
+ if (pp !== '*' && pp !== subjectParts[si])
124
+ return false;
125
+ pi++;
126
+ si++;
127
+ }
128
+ return pi === patternParts.length && si === subjectParts.length;
129
+ }
107
130
  async function publishTopic(input) {
108
131
  try {
132
+ const publishSubject = input.subject || input.topic;
133
+ // Validate subject is a valid variant of the topic pattern
134
+ if (input.subject && !isValidVariant(input.topic, input.subject)) {
135
+ return { status: 400, error: `Subject "${input.subject}" does not match topic pattern "${input.topic}"` };
136
+ }
109
137
  const event = {
110
- type: input.topic,
138
+ id: input.eventId,
139
+ type: publishSubject,
111
140
  source: input.source || 'dashboard',
112
141
  workflowId: '',
113
142
  workflowName: '',
@@ -116,7 +145,7 @@ async function publishTopic(input) {
116
145
  timestamp: new Date().toISOString(),
117
146
  };
118
147
  await events_1.eventRegistry.publish(event);
119
- return { status: 200, data: { published: true, topic: input.topic, timestamp: event.timestamp } };
148
+ return { status: 200, data: { published: true, topic: publishSubject, timestamp: event.timestamp } };
120
149
  }
121
150
  catch (err) {
122
151
  return { status: 500, error: err.message };
@@ -12,6 +12,7 @@ declare class LTEventRegistry {
12
12
  connect(): Promise<void>;
13
13
  /**
14
14
  * Publish an event to all registered adapters.
15
+ * Auto-assigns an idempotent event ID if not provided.
15
16
  * Best-effort: individual adapter failures are logged, not thrown.
16
17
  */
17
18
  publish(event: LTEvent): Promise<void>;
@@ -24,11 +24,15 @@ class LTEventRegistry {
24
24
  }
25
25
  /**
26
26
  * Publish an event to all registered adapters.
27
+ * Auto-assigns an idempotent event ID if not provided.
27
28
  * Best-effort: individual adapter failures are logged, not thrown.
28
29
  */
29
30
  async publish(event) {
30
31
  if (!this.adapters.length)
31
32
  return;
33
+ if (!event.id) {
34
+ event.id = `evt-${Date.now()}-${Math.random().toString(16).slice(2, 6)}`;
35
+ }
32
36
  await Promise.allSettled(this.adapters.map((a) => a.publish(event).catch((err) => {
33
37
  logger_1.loggerRegistry.error(`[lt-events] adapter publish failed: ${err?.message}`);
34
38
  })));
@@ -15,7 +15,8 @@ export declare function publishMilestoneEvent(params: {
15
15
  data?: Record<string, any>;
16
16
  }): Promise<void>;
17
17
  /**
18
- * Publish a task lifecycle event (created, started, completed, escalated, failed).
18
+ * Publish a task lifecycle event.
19
+ * Subject: system.task.{taskId}.{action}
19
20
  */
20
21
  export declare function publishTaskEvent(params: {
21
22
  type: 'task.created' | 'task.started' | 'task.completed' | 'task.escalated' | 'task.failed';
@@ -30,7 +31,8 @@ export declare function publishTaskEvent(params: {
30
31
  data?: Record<string, any>;
31
32
  }): Promise<void>;
32
33
  /**
33
- * Publish an escalation lifecycle event (created, resolved).
34
+ * Publish an escalation lifecycle event.
35
+ * Subject: system.escalation.{escalationId}.{action}
34
36
  */
35
37
  export declare function publishEscalationEvent(params: {
36
38
  type: 'escalation.created' | 'escalation.resolved' | 'escalation.claimed' | 'escalation.released';
@@ -46,7 +48,7 @@ export declare function publishEscalationEvent(params: {
46
48
  }): Promise<void>;
47
49
  /**
48
50
  * Publish an activity lifecycle event for YAML workflow steps.
49
- * Lightweight — no payload data, just progress signals.
51
+ * Subject: system.activity.{workflowId}.{activityName}.{action}
50
52
  */
51
53
  export declare function publishActivityEvent(params: {
52
54
  type: 'activity.started' | 'activity.completed' | 'activity.failed';
@@ -57,9 +59,8 @@ export declare function publishActivityEvent(params: {
57
59
  data?: Record<string, any>;
58
60
  }): Promise<void>;
59
61
  /**
60
- * Publish a knowledge lifecycle event (stored, deleted).
61
- * Lightweight — no workflow context required since knowledge writes
62
- * happen both inside and outside workflows.
62
+ * Publish a knowledge lifecycle event.
63
+ * Subject: system.knowledge.{domain}.{action}
63
64
  */
64
65
  export declare function publishKnowledgeEvent(params: {
65
66
  type: 'knowledge.stored' | 'knowledge.deleted';
@@ -67,8 +68,8 @@ export declare function publishKnowledgeEvent(params: {
67
68
  key: string;
68
69
  }): Promise<void>;
69
70
  /**
70
- * Publish a file storage event (stored, deleted).
71
- * Includes rich metadata: path, name, extension, mime type, size.
71
+ * Publish a file storage event.
72
+ * Subject: system.file.{action}
72
73
  */
73
74
  export declare function publishFileEvent(params: {
74
75
  type: 'file.stored' | 'file.deleted';
@@ -78,6 +79,7 @@ export declare function publishFileEvent(params: {
78
79
  }): Promise<void>;
79
80
  /**
80
81
  * Publish an agent lifecycle event.
82
+ * Subject: system.agent.{agentName}.{action}
81
83
  */
82
84
  export declare function publishAgentEvent(params: {
83
85
  type: 'agent.started' | 'agent.completed' | 'agent.failed' | 'agent.status_changed';
@@ -87,7 +89,8 @@ export declare function publishAgentEvent(params: {
87
89
  data?: Record<string, any>;
88
90
  }): Promise<void>;
89
91
  /**
90
- * Publish a workflow lifecycle event (started, completed, failed).
92
+ * Publish a workflow lifecycle event.
93
+ * Subject: system.workflow.{workflowId}.{action}
91
94
  */
92
95
  export declare function publishWorkflowEvent(params: {
93
96
  type: 'workflow.started' | 'workflow.completed' | 'workflow.failed';