@hotmeshio/long-tail 0.23.2 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/build/adapters/express.d.ts +9 -1
  2. package/build/adapters/express.js +32 -41
  3. package/build/api/auth-sso.d.ts +1 -1
  4. package/build/api/bot-accounts.d.ts +2 -0
  5. package/build/api/bot-accounts.js +4 -0
  6. package/build/api/capabilities.d.ts +7 -2
  7. package/build/api/capabilities.js +13 -2
  8. package/build/api/escalations/analytics.js +5 -0
  9. package/build/api/escalations/bulk.d.ts +2 -0
  10. package/build/api/escalations/bulk.js +9 -4
  11. package/build/api/escalations/helpers.d.ts +5 -0
  12. package/build/api/escalations/helpers.js +7 -0
  13. package/build/api/escalations/metadata.js +3 -0
  14. package/build/api/escalations/single.d.ts +3 -2
  15. package/build/api/escalations/single.js +8 -3
  16. package/build/api/mcp/tools.d.ts +12 -0
  17. package/build/api/mcp/tools.js +113 -9
  18. package/build/api/scan-codes/choice.js +31 -7
  19. package/build/api/settings.js +9 -0
  20. package/build/api/tasks.d.ts +3 -3
  21. package/build/api/tasks.js +30 -7
  22. package/build/api/workflows/input-lookups.js +1 -1
  23. package/build/api/workflows/invocable.js +2 -2
  24. package/build/api/workflows/invocation.js +1 -1
  25. package/build/api/yaml-workflows/deploy.d.ts +10 -2
  26. package/build/api/yaml-workflows/deploy.js +42 -2
  27. package/build/lib/db/schemas/038_oauth_server.sql +46 -0
  28. package/build/lib/events/browser-view.d.ts +15 -0
  29. package/build/lib/events/browser-view.js +101 -0
  30. package/build/lib/events/nats-ws-filter.d.ts +29 -0
  31. package/build/lib/events/nats-ws-filter.js +94 -0
  32. package/build/lib/events/nats-ws-proxy.d.ts +2 -0
  33. package/build/lib/events/nats-ws-proxy.js +39 -5
  34. package/build/lib/events/nats-ws-server-filter.d.ts +16 -0
  35. package/build/lib/events/nats-ws-server-filter.js +56 -0
  36. package/build/lib/events/nats-ws-ticket.d.ts +10 -0
  37. package/build/lib/events/nats-ws-ticket.js +42 -0
  38. package/build/lib/events/socketio.d.ts +10 -1
  39. package/build/lib/events/socketio.js +10 -3
  40. package/build/lib/http/index.d.ts +27 -0
  41. package/build/lib/http/index.js +55 -0
  42. package/build/modules/auth.d.ts +15 -24
  43. package/build/modules/auth.js +43 -126
  44. package/build/modules/capabilities.d.ts +62 -0
  45. package/build/modules/capabilities.js +188 -0
  46. package/build/modules/config.d.ts +14 -0
  47. package/build/modules/config.js +20 -0
  48. package/build/modules/defaults.d.ts +10 -0
  49. package/build/modules/defaults.js +12 -1
  50. package/build/modules/mcp-auth.d.ts +11 -0
  51. package/build/modules/mcp-auth.js +56 -0
  52. package/build/modules/oauth-server.d.ts +18 -0
  53. package/build/modules/oauth-server.js +40 -0
  54. package/build/routes/agents.js +46 -14
  55. package/build/routes/announcements.js +2 -2
  56. package/build/routes/auth-sso.js +2 -2
  57. package/build/routes/auth.js +2 -2
  58. package/build/routes/bot-accounts.js +26 -3
  59. package/build/routes/capabilities.js +4 -4
  60. package/build/routes/controlplane.js +2 -2
  61. package/build/routes/dba.js +2 -2
  62. package/build/routes/delegation.js +2 -2
  63. package/build/routes/diagnostics.js +2 -2
  64. package/build/routes/docs.js +2 -2
  65. package/build/routes/domain.js +2 -2
  66. package/build/routes/escalations/accumulate.d.ts +1 -1
  67. package/build/routes/escalations/acting.d.ts +1 -1
  68. package/build/routes/escalations/analytics.d.ts +1 -1
  69. package/build/routes/escalations/bulk.d.ts +1 -1
  70. package/build/routes/escalations/facets.d.ts +1 -1
  71. package/build/routes/escalations/index.js +2 -2
  72. package/build/routes/escalations/list.d.ts +1 -1
  73. package/build/routes/escalations/metadata.d.ts +1 -1
  74. package/build/routes/escalations/related.d.ts +1 -1
  75. package/build/routes/escalations/resolve.d.ts +1 -1
  76. package/build/routes/escalations/single.d.ts +1 -1
  77. package/build/routes/escalations/single.js +1 -1
  78. package/build/routes/exports.js +14 -13
  79. package/build/routes/file-browser.js +9 -8
  80. package/build/routes/files.js +2 -2
  81. package/build/routes/index.js +4 -2
  82. package/build/routes/insight.js +5 -4
  83. package/build/routes/knowledge.js +2 -2
  84. package/build/routes/maintenance.js +2 -2
  85. package/build/routes/mcp-endpoint.d.ts +3 -1
  86. package/build/routes/mcp-endpoint.js +18 -8
  87. package/build/routes/mcp.js +35 -15
  88. package/build/routes/me.js +2 -2
  89. package/build/routes/namespaces.js +4 -3
  90. package/build/routes/nats-credentials.js +27 -3
  91. package/build/routes/oauth-server/authorize.d.ts +2 -0
  92. package/build/routes/oauth-server/authorize.js +108 -0
  93. package/build/routes/oauth-server/grants.d.ts +2 -0
  94. package/build/routes/oauth-server/grants.js +35 -0
  95. package/build/routes/oauth-server/index.d.ts +8 -0
  96. package/build/routes/oauth-server/index.js +52 -0
  97. package/build/routes/oauth-server/registration.d.ts +2 -0
  98. package/build/routes/oauth-server/registration.js +38 -0
  99. package/build/routes/oauth-server/token.d.ts +2 -0
  100. package/build/routes/oauth-server/token.js +100 -0
  101. package/build/routes/oauth-well-known.d.ts +8 -0
  102. package/build/routes/oauth-well-known.js +31 -0
  103. package/build/routes/oauth.js +2 -2
  104. package/build/routes/overview.js +2 -2
  105. package/build/routes/personas.js +2 -2
  106. package/build/routes/pipelines.js +6 -5
  107. package/build/routes/roles.js +2 -2
  108. package/build/routes/scan-codes.js +2 -2
  109. package/build/routes/settings.js +2 -2
  110. package/build/routes/tasks.js +5 -5
  111. package/build/routes/topics.js +21 -9
  112. package/build/routes/users.js +25 -22
  113. package/build/routes/workflow-sets.js +13 -12
  114. package/build/routes/workflows/config.js +15 -2
  115. package/build/routes/workflows/discovery.js +2 -2
  116. package/build/routes/workflows/index.js +2 -2
  117. package/build/routes/workflows/invocation.js +11 -10
  118. package/build/routes/yaml-workflows/cron.js +19 -6
  119. package/build/routes/yaml-workflows/crud.js +13 -12
  120. package/build/routes/yaml-workflows/deployment.js +11 -10
  121. package/build/routes/yaml-workflows/index.js +2 -2
  122. package/build/routes/yaml-workflows/versions.js +2 -2
  123. package/build/services/agent/authority.d.ts +14 -0
  124. package/build/services/agent/authority.js +53 -0
  125. package/build/services/auth/bot-api-key.d.ts +2 -0
  126. package/build/services/auth/bot-api-key.js +10 -0
  127. package/build/services/auth/oauth-server/access-token.d.ts +36 -0
  128. package/build/services/auth/oauth-server/access-token.js +80 -0
  129. package/build/services/auth/oauth-server/authorization.d.ts +47 -0
  130. package/build/services/auth/oauth-server/authorization.js +54 -0
  131. package/build/services/auth/oauth-server/constants.d.ts +11 -0
  132. package/build/services/auth/oauth-server/constants.js +16 -0
  133. package/build/services/auth/oauth-server/index.d.ts +3 -0
  134. package/build/services/auth/oauth-server/index.js +26 -0
  135. package/build/services/auth/oauth-server/metadata.d.ts +21 -0
  136. package/build/services/auth/oauth-server/metadata.js +53 -0
  137. package/build/services/auth/oauth-server/registration.d.ts +42 -0
  138. package/build/services/auth/oauth-server/registration.js +134 -0
  139. package/build/services/auth/oauth-server/sql.d.ts +34 -0
  140. package/build/services/auth/oauth-server/sql.js +123 -0
  141. package/build/services/auth/oauth-server/store.d.ts +74 -0
  142. package/build/services/auth/oauth-server/store.js +151 -0
  143. package/build/services/auth/sql.d.ts +1 -0
  144. package/build/services/auth/sql.js +3 -1
  145. package/build/services/escalation/queries.js +7 -2
  146. package/build/services/export/index.d.ts +10 -0
  147. package/build/services/export/index.js +27 -0
  148. package/build/services/invocation-access.d.ts +25 -4
  149. package/build/services/invocation-access.js +39 -7
  150. package/build/services/mcp/client/connection-dispatch.d.ts +6 -1
  151. package/build/services/mcp/client/connection-dispatch.js +3 -2
  152. package/build/services/mcp/client/connection-lifecycle.d.ts +10 -2
  153. package/build/services/mcp/client/connection-lifecycle.js +45 -7
  154. package/build/services/mcp/client/connection-test.js +2 -6
  155. package/build/services/mcp/client/connection.d.ts +1 -1
  156. package/build/services/mcp/client/connection.js +3 -1
  157. package/build/services/mcp/client/index.d.ts +2 -2
  158. package/build/services/mcp/client/index.js +4 -1
  159. package/build/services/mcp/client/network-transport.d.ts +12 -0
  160. package/build/services/mcp/client/network-transport.js +20 -0
  161. package/build/services/mcp/client/tools.d.ts +13 -0
  162. package/build/services/mcp/client/tools.js +18 -0
  163. package/build/services/mcp/db-server/index.js +2 -1
  164. package/build/services/mcp/external-server.d.ts +9 -4
  165. package/build/services/mcp/external-server.js +34 -11
  166. package/build/services/mcp/playwright-server/index.js +2 -1
  167. package/build/services/mcp/registered-tools.d.ts +3 -0
  168. package/build/services/mcp/registered-tools.js +7 -0
  169. package/build/services/mcp/server-lifecycle.js +2 -1
  170. package/build/services/workflow-invocation.d.ts +16 -3
  171. package/build/services/workflow-invocation.js +42 -10
  172. package/build/services/yaml-workflow/deployer.d.ts +10 -2
  173. package/build/services/yaml-workflow/deployer.js +17 -5
  174. package/build/services/yaml-workflow/invoke.js +27 -26
  175. package/build/start/config.js +7 -0
  176. package/build/start/index.js +4 -22
  177. package/build/start/server.d.ts +6 -4
  178. package/build/start/server.js +11 -35
  179. package/build/start/socket-auth.js +2 -1
  180. package/build/start/workers.js +1 -1
  181. package/build/system/mcp-servers/admin/agent-subscriptions.js +24 -1
  182. package/build/system/mcp-servers/admin/agents.js +25 -2
  183. package/build/system/mcp-servers/admin/announcements.js +3 -2
  184. package/build/system/mcp-servers/admin/bot-accounts.js +37 -5
  185. package/build/system/mcp-servers/admin/escalations.d.ts +3 -5
  186. package/build/system/mcp-servers/admin/escalations.js +74 -70
  187. package/build/system/mcp-servers/admin/exports.js +7 -1
  188. package/build/system/mcp-servers/admin/index.js +24 -25
  189. package/build/system/mcp-servers/admin/overview.d.ts +2 -2
  190. package/build/system/mcp-servers/admin/run-read.d.ts +2 -0
  191. package/build/system/mcp-servers/admin/run-read.js +5 -0
  192. package/build/system/mcp-servers/admin/scan-codes.d.ts +2 -2
  193. package/build/system/mcp-servers/admin/scan-codes.js +5 -11
  194. package/build/system/mcp-servers/admin/schemas.d.ts +20 -20
  195. package/build/system/mcp-servers/admin/tasks.js +7 -2
  196. package/build/system/mcp-servers/admin/users.js +31 -4
  197. package/build/system/mcp-servers/admin/workflow-config.js +12 -1
  198. package/build/system/mcp-servers/admin/workflows.js +27 -5
  199. package/build/system/mcp-servers/admin/yaml-workflows.js +7 -1
  200. package/build/system/mcp-servers/caller-auth.d.ts +18 -0
  201. package/build/system/mcp-servers/caller-auth.js +29 -0
  202. package/build/system/mcp-servers/claude-code.js +2 -1
  203. package/build/system/mcp-servers/db-query/index.js +2 -1
  204. package/build/system/mcp-servers/file-storage.js +2 -1
  205. package/build/system/mcp-servers/http-fetch.js +2 -1
  206. package/build/system/mcp-servers/human-queue.js +7 -3
  207. package/build/system/mcp-servers/oauth.js +31 -4
  208. package/build/system/mcp-servers/schema-exchange.js +2 -1
  209. package/build/system/mcp-servers/vision.d.ts +1 -0
  210. package/build/system/mcp-servers/vision.js +17 -7
  211. package/build/system/seed/tool-manifests-admin.d.ts +2 -17985
  212. package/build/system/seed/tool-manifests-admin.js +121 -121
  213. package/build/system/seed/tool-manifests-data.d.ts +8 -374
  214. package/build/system/seed/tool-manifests-data.js +22 -4
  215. package/build/system/seed/tool-manifests-escalation.d.ts +2 -352
  216. package/build/system/seed/tool-manifests-escalation.js +11 -1
  217. package/build/system/seed/tool-manifests-events.d.ts +2 -116
  218. package/build/system/seed/tool-manifests-events.js +6 -2
  219. package/build/system/seed/tool-manifests-knowledge.d.ts +2 -221
  220. package/build/system/seed/tool-manifests-knowledge.js +41 -1
  221. package/build/system/seed/tool-manifests-workflows.d.ts +2 -71
  222. package/build/system/seed/tool-manifests-workflows.js +3 -1
  223. package/build/system/workflows/shared/principal-tools.d.ts +20 -0
  224. package/build/system/workflows/shared/principal-tools.js +64 -0
  225. package/build/system/workflows/shared/tool-executor.js +21 -11
  226. package/build/system/workflows/shared/tool-loader.js +8 -1
  227. package/build/tsconfig.tsbuildinfo +1 -1
  228. package/build/types/auth.d.ts +1 -1
  229. package/build/types/capability.d.ts +14 -0
  230. package/build/types/capability.js +2 -0
  231. package/build/types/events.d.ts +1 -1
  232. package/build/types/index.d.ts +3 -1
  233. package/build/types/mcp.d.ts +3 -1
  234. package/build/types/oauth-server.d.ts +52 -0
  235. package/build/types/oauth-server.js +2 -0
  236. package/build/types/startup.d.ts +15 -7
  237. package/build/vitest.config.js +2 -1
  238. package/build/vitest.fast.config.d.ts +2 -0
  239. package/build/vitest.fast.config.js +20 -0
  240. package/build/vitest.llm.config.d.ts +2 -0
  241. package/build/vitest.llm.config.js +16 -0
  242. package/dashboard/dist/assets/{AdminDashboard-BPWsgMfZ.js → AdminDashboard-B3mkMIOT.js} +2 -2
  243. package/dashboard/dist/assets/{AdminDashboard-BPWsgMfZ.js.map → AdminDashboard-B3mkMIOT.js.map} +1 -1
  244. package/dashboard/dist/assets/{AgentConfigPage-De9imyo5.js → AgentConfigPage-CQj2B678.js} +2 -2
  245. package/dashboard/dist/assets/{AgentConfigPage-De9imyo5.js.map → AgentConfigPage-CQj2B678.js.map} +1 -1
  246. package/dashboard/dist/assets/{AgentDetailPage-B6o96Y5G.js → AgentDetailPage-CzrD8JJI.js} +3 -3
  247. package/dashboard/dist/assets/{AgentDetailPage-B6o96Y5G.js.map → AgentDetailPage-CzrD8JJI.js.map} +1 -1
  248. package/dashboard/dist/assets/{AgentsPage-DMEmiK_W.js → AgentsPage-jg2OFwyW.js} +2 -2
  249. package/dashboard/dist/assets/{AgentsPage-DMEmiK_W.js.map → AgentsPage-jg2OFwyW.js.map} +1 -1
  250. package/dashboard/dist/assets/{AvailableEscalationsPage-DeYMngwE.js → AvailableEscalationsPage-IS28XBRe.js} +2 -2
  251. package/dashboard/dist/assets/{AvailableEscalationsPage-DeYMngwE.js.map → AvailableEscalationsPage-IS28XBRe.js.map} +1 -1
  252. package/dashboard/dist/assets/{BotPicker-DDmpgGHZ.js → BotPicker-DvEJFpwS.js} +2 -2
  253. package/dashboard/dist/assets/{BotPicker-DDmpgGHZ.js.map → BotPicker-DvEJFpwS.js.map} +1 -1
  254. package/dashboard/dist/assets/{BulkAssignModal-BqlklomG.js → BulkAssignModal-BoQCi-YC.js} +2 -2
  255. package/dashboard/dist/assets/{BulkAssignModal-BqlklomG.js.map → BulkAssignModal-BoQCi-YC.js.map} +1 -1
  256. package/dashboard/dist/assets/{CapabilitiesPage-DOtjDTbK.js → CapabilitiesPage-kwlrcb_t.js} +2 -2
  257. package/dashboard/dist/assets/{CapabilitiesPage-DOtjDTbK.js.map → CapabilitiesPage-kwlrcb_t.js.map} +1 -1
  258. package/dashboard/dist/assets/{CollapsibleSection-CLr8LP0V.js → CollapsibleSection-UMIV4KIj.js} +2 -2
  259. package/dashboard/dist/assets/{CollapsibleSection-CLr8LP0V.js.map → CollapsibleSection-UMIV4KIj.js.map} +1 -1
  260. package/dashboard/dist/assets/ConfirmDeleteModal-C5puwMg7.js +2 -0
  261. package/dashboard/dist/assets/ConfirmDeleteModal-C5puwMg7.js.map +1 -0
  262. package/dashboard/dist/assets/ConnectedAppsPage-drZa65kP.js +2 -0
  263. package/dashboard/dist/assets/ConnectedAppsPage-drZa65kP.js.map +1 -0
  264. package/dashboard/dist/assets/{CountdownTimer-DxX72PwV.js → CountdownTimer-LG03dVgR.js} +2 -2
  265. package/dashboard/dist/assets/{CountdownTimer-DxX72PwV.js.map → CountdownTimer-LG03dVgR.js.map} +1 -1
  266. package/dashboard/dist/assets/{CredentialsPage-CObc9Rs5.js → CredentialsPage-CaFQ6vLb.js} +2 -2
  267. package/dashboard/dist/assets/{CredentialsPage-CObc9Rs5.js.map → CredentialsPage-CaFQ6vLb.js.map} +1 -1
  268. package/dashboard/dist/assets/{CronLabel-Bb8GoNY5.js → CronLabel-Co5j7tzW.js} +2 -2
  269. package/dashboard/dist/assets/{CronLabel-Bb8GoNY5.js.map → CronLabel-Co5j7tzW.js.map} +1 -1
  270. package/dashboard/dist/assets/{ElapsedCell-CmGhVlYl.js → ElapsedCell-WJyE9G0T.js} +2 -2
  271. package/dashboard/dist/assets/{ElapsedCell-CmGhVlYl.js.map → ElapsedCell-WJyE9G0T.js.map} +1 -1
  272. package/dashboard/dist/assets/{EntityTimelinePanel-B4Jwy1w3.js → EntityTimelinePanel-CDFFfX9d.js} +2 -2
  273. package/dashboard/dist/assets/{EntityTimelinePanel-B4Jwy1w3.js.map → EntityTimelinePanel-CDFFfX9d.js.map} +1 -1
  274. package/dashboard/dist/assets/{EscalationListSchemaPage-CZZbZ4Aa.js → EscalationListSchemaPage-CMrUlaKI.js} +3 -3
  275. package/dashboard/dist/assets/{EscalationListSchemaPage-CZZbZ4Aa.js.map → EscalationListSchemaPage-CMrUlaKI.js.map} +1 -1
  276. package/dashboard/dist/assets/{EscalationSchemaPage-D0ko59_S.js → EscalationSchemaPage-Dx2Lyfrz.js} +2 -2
  277. package/dashboard/dist/assets/{EscalationSchemaPage-D0ko59_S.js.map → EscalationSchemaPage-Dx2Lyfrz.js.map} +1 -1
  278. package/dashboard/dist/assets/{EscalationTimeline-BcnJEKFD.js → EscalationTimeline-d3nvshOk.js} +2 -2
  279. package/dashboard/dist/assets/{EscalationTimeline-BcnJEKFD.js.map → EscalationTimeline-d3nvshOk.js.map} +1 -1
  280. package/dashboard/dist/assets/{EscalationTitleSelect-P0q5sck4.js → EscalationTitleSelect-DWQieOM9.js} +2 -2
  281. package/dashboard/dist/assets/{EscalationTitleSelect-P0q5sck4.js.map → EscalationTitleSelect-DWQieOM9.js.map} +1 -1
  282. package/dashboard/dist/assets/{EscalationsOverview-BLPmh4AF.js → EscalationsOverview-BX8Cpi0X.js} +2 -2
  283. package/dashboard/dist/assets/{EscalationsOverview-BLPmh4AF.js.map → EscalationsOverview-BX8Cpi0X.js.map} +1 -1
  284. package/dashboard/dist/assets/{EventTable-gBzi5tIS.js → EventTable-D1-ITVXS.js} +2 -2
  285. package/dashboard/dist/assets/{EventTable-gBzi5tIS.js.map → EventTable-D1-ITVXS.js.map} +1 -1
  286. package/dashboard/dist/assets/{FilterBar-BulSsWb2.js → FilterBar-ABC9ctin.js} +2 -2
  287. package/dashboard/dist/assets/{FilterBar-BulSsWb2.js.map → FilterBar-ABC9ctin.js.map} +1 -1
  288. package/dashboard/dist/assets/{FormattedValue-BMHRrvrL.js → FormattedValue-k27T4bG7.js} +2 -2
  289. package/dashboard/dist/assets/{FormattedValue-BMHRrvrL.js.map → FormattedValue-k27T4bG7.js.map} +1 -1
  290. package/dashboard/dist/assets/{GraphInvokePage--997yNRr.js → GraphInvokePage-DKUErxWc.js} +2 -2
  291. package/dashboard/dist/assets/{GraphInvokePage--997yNRr.js.map → GraphInvokePage-DKUErxWc.js.map} +1 -1
  292. package/dashboard/dist/assets/{HomePage-CwXFz--v.js → HomePage-C6u9dIpR.js} +2 -2
  293. package/dashboard/dist/assets/{HomePage-CwXFz--v.js.map → HomePage-C6u9dIpR.js.map} +1 -1
  294. package/dashboard/dist/assets/{ListToolbar-Df4qZryJ.js → ListToolbar-gA5rFzkz.js} +2 -2
  295. package/dashboard/dist/assets/{ListToolbar-Df4qZryJ.js.map → ListToolbar-gA5rFzkz.js.map} +1 -1
  296. package/dashboard/dist/assets/{McpOverview-DrogIAKJ.js → McpOverview-BOPo3J_i.js} +2 -2
  297. package/dashboard/dist/assets/{McpOverview-DrogIAKJ.js.map → McpOverview-BOPo3J_i.js.map} +1 -1
  298. package/dashboard/dist/assets/{McpQueryDetailPage-CJmvCAE6.js → McpQueryDetailPage-BRVVi0Zh.js} +2 -2
  299. package/dashboard/dist/assets/{McpQueryDetailPage-CJmvCAE6.js.map → McpQueryDetailPage-BRVVi0Zh.js.map} +1 -1
  300. package/dashboard/dist/assets/{McpQueryPage-lygo4Yq0.js → McpQueryPage-Dmbb6SAc.js} +2 -2
  301. package/dashboard/dist/assets/{McpQueryPage-lygo4Yq0.js.map → McpQueryPage-Dmbb6SAc.js.map} +1 -1
  302. package/dashboard/dist/assets/{McpRunDetailPage-hvns2sCm.js → McpRunDetailPage-bMXNO-6V.js} +2 -2
  303. package/dashboard/dist/assets/{McpRunDetailPage-hvns2sCm.js.map → McpRunDetailPage-bMXNO-6V.js.map} +1 -1
  304. package/dashboard/dist/assets/{McpRunsPage-C2_7spTX.js → McpRunsPage-Bi9AMWja.js} +2 -2
  305. package/dashboard/dist/assets/{McpRunsPage-C2_7spTX.js.map → McpRunsPage-Bi9AMWja.js.map} +1 -1
  306. package/dashboard/dist/assets/{OperationsPage-BlK8WlsY.js → OperationsPage-CvR74ZUJ.js} +3 -3
  307. package/dashboard/dist/assets/{OperationsPage-BlK8WlsY.js.map → OperationsPage-CvR74ZUJ.js.map} +1 -1
  308. package/dashboard/dist/assets/{OperatorDashboard-BeWBiMGX.js → OperatorDashboard-DctmZw10.js} +2 -2
  309. package/dashboard/dist/assets/{OperatorDashboard-BeWBiMGX.js.map → OperatorDashboard-DctmZw10.js.map} +1 -1
  310. package/dashboard/dist/assets/{PersonaDetailPage-CNHpsX_i.js → PersonaDetailPage-Ubqm2rQH.js} +2 -2
  311. package/dashboard/dist/assets/{PersonaDetailPage-CNHpsX_i.js.map → PersonaDetailPage-Ubqm2rQH.js.map} +1 -1
  312. package/dashboard/dist/assets/{PersonasPage-ChASEZRg.js → PersonasPage-BpFL2rpo.js} +2 -2
  313. package/dashboard/dist/assets/{PersonasPage-ChASEZRg.js.map → PersonasPage-BpFL2rpo.js.map} +1 -1
  314. package/dashboard/dist/assets/{PortalPage-D5Lk-PKF.js → PortalPage-Dfc_Q02R.js} +2 -2
  315. package/dashboard/dist/assets/{PortalPage-D5Lk-PKF.js.map → PortalPage-Dfc_Q02R.js.map} +1 -1
  316. package/dashboard/dist/assets/ProcessDetailPage-liJspvQh.js +2 -0
  317. package/dashboard/dist/assets/{ProcessDetailPage-DNgCIwRl.js.map → ProcessDetailPage-liJspvQh.js.map} +1 -1
  318. package/dashboard/dist/assets/{ProcessesListPage-pRjWuWlH.js → ProcessesListPage-C3OM5ZUy.js} +2 -2
  319. package/dashboard/dist/assets/{ProcessesListPage-pRjWuWlH.js.map → ProcessesListPage-C3OM5ZUy.js.map} +1 -1
  320. package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js +8 -0
  321. package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js.map +1 -0
  322. package/dashboard/dist/assets/{RoleDetailPage-Bh_UcfYY.js → RoleDetailPage-CrlYCh-R.js} +2 -2
  323. package/dashboard/dist/assets/{RoleDetailPage-Bh_UcfYY.js.map → RoleDetailPage-CrlYCh-R.js.map} +1 -1
  324. package/dashboard/dist/assets/{RolesPage-CK17N7zz.js → RolesPage-BaazL_pt.js} +2 -2
  325. package/dashboard/dist/assets/{RolesPage-CK17N7zz.js.map → RolesPage-BaazL_pt.js.map} +1 -1
  326. package/dashboard/dist/assets/{RunAsSelector-BEKUP0p2.js → RunAsSelector-DxuV0fa1.js} +2 -2
  327. package/dashboard/dist/assets/{RunAsSelector-BEKUP0p2.js.map → RunAsSelector-DxuV0fa1.js.map} +1 -1
  328. package/dashboard/dist/assets/{ScanCodesPage-Bd0Pflqx.js → ScanCodesPage-C0mvmYTq.js} +2 -2
  329. package/dashboard/dist/assets/{ScanCodesPage-Bd0Pflqx.js.map → ScanCodesPage-C0mvmYTq.js.map} +1 -1
  330. package/dashboard/dist/assets/{ScanSchemeDetailPage-CnuhozmJ.js → ScanSchemeDetailPage-CiJgt5dZ.js} +2 -2
  331. package/dashboard/dist/assets/{ScanSchemeDetailPage-CnuhozmJ.js.map → ScanSchemeDetailPage-CiJgt5dZ.js.map} +1 -1
  332. package/dashboard/dist/assets/{ScanStationPage-CoLc-q3h.js → ScanStationPage-DzGaXc40.js} +2 -2
  333. package/dashboard/dist/assets/{ScanStationPage-CoLc-q3h.js.map → ScanStationPage-DzGaXc40.js.map} +1 -1
  334. package/dashboard/dist/assets/{StickyPagination-COrfvkBi.js → StickyPagination-CqbjVY6T.js} +2 -2
  335. package/dashboard/dist/assets/{StickyPagination-COrfvkBi.js.map → StickyPagination-CqbjVY6T.js.map} +1 -1
  336. package/dashboard/dist/assets/{StreamMessageDetail-Cif2egLy.js → StreamMessageDetail-wX3i0aqs.js} +2 -2
  337. package/dashboard/dist/assets/{StreamMessageDetail-Cif2egLy.js.map → StreamMessageDetail-wX3i0aqs.js.map} +1 -1
  338. package/dashboard/dist/assets/{SwimlaneTimeline-BnZYTrAh.js → SwimlaneTimeline-C50PsFoV.js} +2 -2
  339. package/dashboard/dist/assets/{SwimlaneTimeline-BnZYTrAh.js.map → SwimlaneTimeline-C50PsFoV.js.map} +1 -1
  340. package/dashboard/dist/assets/{TaskDetailPage-DEz_dqyR.js → TaskDetailPage-bbNSv4Ae.js} +2 -2
  341. package/dashboard/dist/assets/{TaskDetailPage-DEz_dqyR.js.map → TaskDetailPage-bbNSv4Ae.js.map} +1 -1
  342. package/dashboard/dist/assets/{TasksListPage-oEfEGj0_.js → TasksListPage-CDWnm_d9.js} +2 -2
  343. package/dashboard/dist/assets/{TasksListPage-oEfEGj0_.js.map → TasksListPage-CDWnm_d9.js.map} +1 -1
  344. package/dashboard/dist/assets/{TimeAgo-Dz5TgZZZ.js → TimeAgo-BLjqlfoX.js} +2 -2
  345. package/dashboard/dist/assets/{TimeAgo-Dz5TgZZZ.js.map → TimeAgo-BLjqlfoX.js.map} +1 -1
  346. package/dashboard/dist/assets/{TimestampCell-BUTgE244.js → TimestampCell-CnW0ENb5.js} +2 -2
  347. package/dashboard/dist/assets/{TimestampCell-BUTgE244.js.map → TimestampCell-CnW0ENb5.js.map} +1 -1
  348. package/dashboard/dist/assets/{ToolTestPanel-BS4g6vt-.js → ToolTestPanel-DkMgCB-k.js} +2 -2
  349. package/dashboard/dist/assets/{ToolTestPanel-BS4g6vt-.js.map → ToolTestPanel-DkMgCB-k.js.map} +1 -1
  350. package/dashboard/dist/assets/{TopicDetailPage-C_I6JIVD.js → TopicDetailPage-g3pljKKX.js} +2 -2
  351. package/dashboard/dist/assets/{TopicDetailPage-C_I6JIVD.js.map → TopicDetailPage-g3pljKKX.js.map} +1 -1
  352. package/dashboard/dist/assets/{TopicsPage-Cr6-wfhJ.js → TopicsPage-CVcCYdy-.js} +2 -2
  353. package/dashboard/dist/assets/{TopicsPage-Cr6-wfhJ.js.map → TopicsPage-CVcCYdy-.js.map} +1 -1
  354. package/dashboard/dist/assets/{UserName-ZFpWMaFF.js → UserName-D6zGIK2i.js} +2 -2
  355. package/dashboard/dist/assets/{UserName-ZFpWMaFF.js.map → UserName-D6zGIK2i.js.map} +1 -1
  356. package/dashboard/dist/assets/{WorkflowExecutionPage-ByPixDZW.js → WorkflowExecutionPage-B8g81FCJ.js} +2 -2
  357. package/dashboard/dist/assets/{WorkflowExecutionPage-ByPixDZW.js.map → WorkflowExecutionPage-B8g81FCJ.js.map} +1 -1
  358. package/dashboard/dist/assets/{WorkflowsDashboard-CWsJdMdR.js → WorkflowsDashboard-nxT3bv6W.js} +2 -2
  359. package/dashboard/dist/assets/{WorkflowsDashboard-CWsJdMdR.js.map → WorkflowsDashboard-nxT3bv6W.js.map} +1 -1
  360. package/dashboard/dist/assets/{WorkflowsOverview-Dk9gyqZN.js → WorkflowsOverview-grI-KAI2.js} +2 -2
  361. package/dashboard/dist/assets/{WorkflowsOverview-Dk9gyqZN.js.map → WorkflowsOverview-grI-KAI2.js.map} +1 -1
  362. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CHwcrsaT.js → YamlWorkflowDetailPage-BoZ-hfBE.js} +2 -2
  363. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CHwcrsaT.js.map → YamlWorkflowDetailPage-BoZ-hfBE.js.map} +1 -1
  364. package/dashboard/dist/assets/{YamlWorkflowsPage-B5jRX2Ph.js → YamlWorkflowsPage-Bf04rwRv.js} +2 -2
  365. package/dashboard/dist/assets/{YamlWorkflowsPage-B5jRX2Ph.js.map → YamlWorkflowsPage-Bf04rwRv.js.map} +1 -1
  366. package/dashboard/dist/assets/{agents-Dd7E-27d.js → agents-Dphpdi8l.js} +2 -2
  367. package/dashboard/dist/assets/{agents-Dd7E-27d.js.map → agents-Dphpdi8l.js.map} +1 -1
  368. package/dashboard/dist/assets/{bots-CpaYjZTk.js → bots-DIFE298x.js} +2 -2
  369. package/dashboard/dist/assets/{bots-CpaYjZTk.js.map → bots-DIFE298x.js.map} +1 -1
  370. package/dashboard/dist/assets/{capabilities-CNjg_qv1.js → capabilities-D7Y7LClY.js} +2 -2
  371. package/dashboard/dist/assets/{capabilities-CNjg_qv1.js.map → capabilities-D7Y7LClY.js.map} +1 -1
  372. package/dashboard/dist/assets/{controlplane-DgmvnAtU.js → controlplane-D1TGcYsS.js} +2 -2
  373. package/dashboard/dist/assets/{controlplane-DgmvnAtU.js.map → controlplane-D1TGcYsS.js.map} +1 -1
  374. package/dashboard/dist/assets/{escalation-columns-Uj4U9g5H.js → escalation-columns-cwZE6xyo.js} +2 -2
  375. package/dashboard/dist/assets/{escalation-columns-Uj4U9g5H.js.map → escalation-columns-cwZE6xyo.js.map} +1 -1
  376. package/dashboard/dist/assets/{index-x5z73M9N.js → index-BzYcUPdD.js} +2 -2
  377. package/dashboard/dist/assets/{index-x5z73M9N.js.map → index-BzYcUPdD.js.map} +1 -1
  378. package/dashboard/dist/assets/index-CeCtqujG.js +67 -0
  379. package/dashboard/dist/assets/index-CeCtqujG.js.map +1 -0
  380. package/dashboard/dist/assets/{index-RIFT3RlO.js → index-ChV7pBjM.js} +2 -2
  381. package/dashboard/dist/assets/{index-RIFT3RlO.js.map → index-ChV7pBjM.js.map} +1 -1
  382. package/dashboard/dist/assets/{index-OfO0173w.js → index-CniRa65p.js} +2 -2
  383. package/dashboard/dist/assets/{index-OfO0173w.js.map → index-CniRa65p.js.map} +1 -1
  384. package/dashboard/dist/assets/{index-ByBy9M3L.js → index-CxdjT1Yk.js} +2 -2
  385. package/dashboard/dist/assets/{index-ByBy9M3L.js.map → index-CxdjT1Yk.js.map} +1 -1
  386. package/dashboard/dist/assets/{index-C_K7OlzT.js → index-DAvi5_2T.js} +2 -2
  387. package/dashboard/dist/assets/{index-C_K7OlzT.js.map → index-DAvi5_2T.js.map} +1 -1
  388. package/dashboard/dist/assets/{index-BrwqtXRh.js → index-DN-kX7hL.js} +2 -2
  389. package/dashboard/dist/assets/{index-BrwqtXRh.js.map → index-DN-kX7hL.js.map} +1 -1
  390. package/dashboard/dist/assets/index-Dl_8hbYI.js +2 -0
  391. package/dashboard/dist/assets/index-Dl_8hbYI.js.map +1 -0
  392. package/dashboard/dist/assets/{index-D4Dlznn9.js → index-DpKOr311.js} +2 -2
  393. package/dashboard/dist/assets/{index-D4Dlznn9.js.map → index-DpKOr311.js.map} +1 -1
  394. package/dashboard/dist/assets/{index-CnOvJz6U.js → index-Dy1wWu2e.js} +2 -2
  395. package/dashboard/dist/assets/{index-CnOvJz6U.js.map → index-Dy1wWu2e.js.map} +1 -1
  396. package/dashboard/dist/assets/{index-BT1Ms5Q5.js → index-HLu98Sqh.js} +2 -2
  397. package/dashboard/dist/assets/{index-BT1Ms5Q5.js.map → index-HLu98Sqh.js.map} +1 -1
  398. package/dashboard/dist/assets/{index-BFASQ7_X.js → index-ag2pCAPu.js} +2 -2
  399. package/dashboard/dist/assets/{index-BFASQ7_X.js.map → index-ag2pCAPu.js.map} +1 -1
  400. package/dashboard/dist/assets/{index-BsHVgWH6.js → index-gkxPN7Vx.js} +2 -2
  401. package/dashboard/dist/assets/{index-BsHVgWH6.js.map → index-gkxPN7Vx.js.map} +1 -1
  402. package/dashboard/dist/assets/index-m9A3UYst.css +1 -0
  403. package/dashboard/dist/assets/{knowledge-Cci_r6Kl.js → knowledge-DnMs-SOJ.js} +2 -2
  404. package/dashboard/dist/assets/{knowledge-Cci_r6Kl.js.map → knowledge-DnMs-SOJ.js.map} +1 -1
  405. package/dashboard/dist/assets/{mcp-NY4iL0L-.js → mcp-CwW-K3r4.js} +2 -2
  406. package/dashboard/dist/assets/{mcp-NY4iL0L-.js.map → mcp-CwW-K3r4.js.map} +1 -1
  407. package/dashboard/dist/assets/{mcp-query-CbvZo_I_.js → mcp-query-BZt5e8_Q.js} +2 -2
  408. package/dashboard/dist/assets/{mcp-query-CbvZo_I_.js.map → mcp-query-BZt5e8_Q.js.map} +1 -1
  409. package/dashboard/dist/assets/{personas-Fy-f7QQd.js → personas-UA-Xn60f.js} +2 -2
  410. package/dashboard/dist/assets/{personas-Fy-f7QQd.js.map → personas-UA-Xn60f.js.map} +1 -1
  411. package/dashboard/dist/assets/{pipelines-DKiuozxV.js → pipelines-Cu3PARum.js} +2 -2
  412. package/dashboard/dist/assets/{pipelines-DKiuozxV.js.map → pipelines-Cu3PARum.js.map} +1 -1
  413. package/dashboard/dist/assets/{tasks-CdM1Rkk9.js → tasks-BO6h8GJE.js} +2 -2
  414. package/dashboard/dist/assets/{tasks-CdM1Rkk9.js.map → tasks-BO6h8GJE.js.map} +1 -1
  415. package/dashboard/dist/assets/{topics-XNy2mf3n.js → topics-CWjCR-17.js} +2 -2
  416. package/dashboard/dist/assets/{topics-XNy2mf3n.js.map → topics-CWjCR-17.js.map} +1 -1
  417. package/dashboard/dist/assets/{useDebouncedValue-CyGcU3_S.js → useDebouncedValue-6t0jx1RB.js} +2 -2
  418. package/dashboard/dist/assets/{useDebouncedValue-CyGcU3_S.js.map → useDebouncedValue-6t0jx1RB.js.map} +1 -1
  419. package/dashboard/dist/assets/{useNamespace-C2RIh_IN.js → useNamespace-CqpoQx6D.js} +2 -2
  420. package/dashboard/dist/assets/{useNamespace-C2RIh_IN.js.map → useNamespace-CqpoQx6D.js.map} +1 -1
  421. package/dashboard/dist/assets/{useYamlActivityEvents-CDiV5fjf.js → useYamlActivityEvents-hmCQQwzB.js} +2 -2
  422. package/dashboard/dist/assets/{useYamlActivityEvents-CDiV5fjf.js.map → useYamlActivityEvents-hmCQQwzB.js.map} +1 -1
  423. package/dashboard/dist/assets/{validate-DcGWN82Y.js → validate-BIRn4a6d.js} +2 -2
  424. package/dashboard/dist/assets/{validate-DcGWN82Y.js.map → validate-BIRn4a6d.js.map} +1 -1
  425. package/dashboard/dist/assets/{yaml-workflows-CH8UrouH.js → yaml-workflows-ziUdZhKY.js} +2 -2
  426. package/dashboard/dist/assets/{yaml-workflows-CH8UrouH.js.map → yaml-workflows-ziUdZhKY.js.map} +1 -1
  427. package/dashboard/dist/index.html +2 -2
  428. package/docs/agents.md +3 -1
  429. package/docs/api/http/agents.md +15 -1
  430. package/docs/api/http/escalations.md +3 -3
  431. package/docs/api/http/exports.md +3 -1
  432. package/docs/api/http/file-browser.md +3 -1
  433. package/docs/api/http/mcp-endpoint.md +5 -2
  434. package/docs/api/http/mcp-servers.md +34 -4
  435. package/docs/api/http/namespaces.md +2 -0
  436. package/docs/api/http/pipelines.md +2 -0
  437. package/docs/api/http/roles.md +11 -8
  438. package/docs/api/http/service-accounts.md +8 -2
  439. package/docs/api/http/settings.md +29 -2
  440. package/docs/api/http/tasks.md +3 -1
  441. package/docs/api/http/topics.md +7 -1
  442. package/docs/api/http/users.md +8 -2
  443. package/docs/api/http/workflows.md +25 -10
  444. package/docs/api/http/yaml-workflows.md +21 -0
  445. package/docs/api/mcp/admin.md +409 -49
  446. package/docs/api/mcp/file-storage.md +4 -0
  447. package/docs/api/mcp/http-fetch.md +6 -2
  448. package/docs/api/mcp/human-queue.md +53 -0
  449. package/docs/api/mcp/index.md +13 -10
  450. package/docs/api/mcp/knowledge.md +34 -0
  451. package/docs/api/mcp/oauth.md +1 -1
  452. package/docs/api/mcp/ortho.md +113 -0
  453. package/docs/api/mcp/vision.md +1 -1
  454. package/docs/api/sdk/bot-accounts.md +1 -0
  455. package/docs/api/sdk/escalations.md +2 -2
  456. package/docs/api/sdk/mcp.md +2 -2
  457. package/docs/api/sdk/settings.md +1 -1
  458. package/docs/api/sdk/tasks.md +2 -2
  459. package/docs/api/sdk/workflows.md +2 -2
  460. package/docs/api/sdk/yaml-workflows.md +1 -1
  461. package/docs/architecture.md +3 -1
  462. package/docs/auth.md +3 -2
  463. package/docs/cloud.md +7 -2
  464. package/docs/dashboard.md +16 -7
  465. package/docs/data.md +1 -1
  466. package/docs/escalation-strategies.md +9 -20
  467. package/docs/events.md +6 -0
  468. package/docs/iam.md +7 -5
  469. package/docs/mcp.md +159 -210
  470. package/docs/oauth-and-delegation.md +32 -21
  471. package/docs/topics.md +2 -0
  472. package/docs/workflows.md +14 -112
  473. package/package.json +5 -3
  474. package/dashboard/dist/assets/ConfirmDeleteModal-DW4DrPur.js +0 -2
  475. package/dashboard/dist/assets/ConfirmDeleteModal-DW4DrPur.js.map +0 -1
  476. package/dashboard/dist/assets/ProcessDetailPage-DNgCIwRl.js +0 -2
  477. package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js +0 -8
  478. package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js.map +0 -1
  479. package/dashboard/dist/assets/index-CtlBjl8o.js +0 -2
  480. package/dashboard/dist/assets/index-CtlBjl8o.js.map +0 -1
  481. package/dashboard/dist/assets/index-LRYC__mE.js +0 -67
  482. package/dashboard/dist/assets/index-LRYC__mE.js.map +0 -1
  483. package/dashboard/dist/assets/index-MYI2_Xb3.css +0 -1
@@ -53,7 +53,20 @@ export declare class InvocationError extends Error {
53
53
  */
54
54
  export declare function invokeWorkflow(input: InvokeWorkflowInput): Promise<InvokeWorkflowResult>;
55
55
  /**
56
- * Check invocation_roles when present on a workflow config.
57
- * Throws InvocationError if the user lacks the required role.
56
+ * Check a caller against the workflow's invocation rules, from the caller's
57
+ * live grants rather than any role claim a token carries. A workflow with no
58
+ * invocation roles is open, except a system-authority workflow, which needs a
59
+ * superadmin.
58
60
  */
59
- export declare function checkInvocationRoles(workflowType: string, userId: string, authRole?: string): Promise<void>;
61
+ export declare function checkInvocationRoles(workflowType: string, userId: string): Promise<void>;
62
+ /** Refuse an execute_as override that would exceed the caller's own authority. */
63
+ export declare function assertMayActAs(userId: string, executeAs: string): Promise<void>;
64
+ /**
65
+ * Authorize an invocation that arrives from outside the process (REST, /mcp):
66
+ * the workflow's invocation rules, then any execute_as override.
67
+ */
68
+ export declare function authorizeInvocation(input: {
69
+ workflowType: string;
70
+ userId: string;
71
+ executeAs?: string;
72
+ }): Promise<void>;
@@ -45,8 +45,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.InvocationError = void 0;
46
46
  exports.invokeWorkflow = invokeWorkflow;
47
47
  exports.checkInvocationRoles = checkInvocationRoles;
48
+ exports.assertMayActAs = assertMayActAs;
49
+ exports.authorizeInvocation = authorizeInvocation;
48
50
  const hotmesh_1 = require("@hotmeshio/hotmesh");
49
51
  const invocation_access_1 = require("./invocation-access");
52
+ const uuid_1 = require("../lib/uuid");
50
53
  const workers_1 = require("../workers");
51
54
  const configService = __importStar(require("./config"));
52
55
  const userService = __importStar(require("./user"));
@@ -138,26 +141,55 @@ async function resolveTaskQueue(workflowType) {
138
141
  }
139
142
  return worker.taskQueue;
140
143
  }
144
+ /** A principal's grants by uuid or external_id, or null when no such user exists. */
145
+ async function grantsOf(identifier) {
146
+ const user = (0, uuid_1.isUuid)(identifier)
147
+ ? await userService.getUser(identifier)
148
+ : await userService.getUserByExternalId(identifier);
149
+ return user ? user.roles.map((r) => ({ role: r.role, type: r.type })) : null;
150
+ }
141
151
  /**
142
- * Check invocation_roles when present on a workflow config.
143
- * Throws InvocationError if the user lacks the required role.
152
+ * Check a caller against the workflow's invocation rules, from the caller's
153
+ * live grants rather than any role claim a token carries. A workflow with no
154
+ * invocation roles is open, except a system-authority workflow, which needs a
155
+ * superadmin.
144
156
  */
145
- async function checkInvocationRoles(workflowType, userId, authRole) {
157
+ async function checkInvocationRoles(workflowType, userId) {
146
158
  const wfConfig = await configService.getWorkflowConfig(workflowType);
147
- if (!wfConfig || wfConfig.invocation_roles.length === 0)
148
- return;
149
- // Superadmin from JWT bypasses all invocation role checks
150
- if (authRole === 'superadmin')
159
+ const systemAuthority = invocation_access_1.SYSTEM_AUTHORITY_WORKFLOWS.has(workflowType);
160
+ if (!systemAuthority && (!wfConfig || wfConfig.invocation_roles.length === 0))
151
161
  return;
152
- const user = await userService.getUser(userId);
153
- if (!user) {
162
+ const roles = await grantsOf(userId);
163
+ if (!roles) {
154
164
  throw new InvocationError('User not registered', 403);
155
165
  }
156
166
  // invocable is resolveTaskQueue's concern; this gate decides roles only.
157
- if (!(0, invocation_access_1.canInvokeWorkflow)({ ...wfConfig, invocable: true }, user.roles, authRole)) {
167
+ const rules = { workflow_type: workflowType, invocation_roles: wfConfig?.invocation_roles ?? [], invocable: true };
168
+ if (!(0, invocation_access_1.canInvokeWorkflow)(rules, roles)) {
158
169
  throw new InvocationError('Insufficient role for invocation', 403);
159
170
  }
160
171
  }
172
+ /** Refuse an execute_as override that would exceed the caller's own authority. */
173
+ async function assertMayActAs(userId, executeAs) {
174
+ const caller = await grantsOf(userId);
175
+ if (!caller)
176
+ throw new InvocationError('User not registered', 403);
177
+ const target = await grantsOf(executeAs);
178
+ if (!target)
179
+ throw new InvocationError(`execute_as principal "${executeAs}" not found`, 404);
180
+ if (!(0, invocation_access_1.mayActAs)(caller, target)) {
181
+ throw new InvocationError('execute_as may not exceed your own authority', 403);
182
+ }
183
+ }
184
+ /**
185
+ * Authorize an invocation that arrives from outside the process (REST, /mcp):
186
+ * the workflow's invocation rules, then any execute_as override.
187
+ */
188
+ async function authorizeInvocation(input) {
189
+ await checkInvocationRoles(input.workflowType, input.userId);
190
+ if (input.executeAs)
191
+ await assertMayActAs(input.userId, input.executeAs);
192
+ }
161
193
  /**
162
194
  * Build the LTEnvelope with IAM context.
163
195
  */
@@ -27,10 +27,18 @@ export declare function deployYamlWorkflow(appId: string, yamlContent: string):
27
27
  * Activate a deployed version of a YAML workflow.
28
28
  */
29
29
  export declare function activateYamlWorkflow(appId: string, version: string): Promise<boolean>;
30
+ /** The key compiled workflow activities read their identity context from. */
31
+ export declare const SCOPE_KEY = "_scope";
32
+ /**
33
+ * The trigger data a compiled workflow starts with. Identity context is never
34
+ * taken from the data a caller supplied: any `_scope` there is dropped, and
35
+ * only the scope the server resolved is set.
36
+ */
37
+ export declare function withTrustedScope(data: Record<string, unknown>, scope?: Record<string, unknown>): Record<string, unknown>;
30
38
  /**
31
39
  * Invoke a YAML workflow (fire-and-forget). Returns the job ID.
32
40
  */
33
- export declare function invokeYamlWorkflow(appId: string, topic: string, data: Record<string, unknown>, entity?: string, context?: Record<string, any>): Promise<string>;
41
+ export declare function invokeYamlWorkflow(appId: string, topic: string, data: Record<string, unknown>, entity?: string, context?: Record<string, any>, scope?: Record<string, unknown>): Promise<string>;
34
42
  /**
35
43
  * Invoke a YAML workflow and wait for the result.
36
44
  *
@@ -40,7 +48,7 @@ export declare function invokeYamlWorkflow(appId: string, topic: string, data: R
40
48
  *
41
49
  * Source: @hotmeshio/hotmesh engine/index.js pubsub()
42
50
  */
43
- export declare function invokeYamlWorkflowSync(appId: string, topic: string, data: Record<string, unknown>, timeout?: number, entity?: string): Promise<{
51
+ export declare function invokeYamlWorkflowSync(appId: string, topic: string, data: Record<string, unknown>, timeout?: number, entity?: string, scope?: Record<string, unknown>): Promise<{
44
52
  job_id: string;
45
53
  result: Record<string, unknown>;
46
54
  }>;
@@ -33,11 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.buildMergedYaml = void 0;
36
+ exports.SCOPE_KEY = exports.buildMergedYaml = void 0;
37
37
  exports.getEngine = getEngine;
38
38
  exports.deployAppId = deployAppId;
39
39
  exports.deployYamlWorkflow = deployYamlWorkflow;
40
40
  exports.activateYamlWorkflow = activateYamlWorkflow;
41
+ exports.withTrustedScope = withTrustedScope;
41
42
  exports.invokeYamlWorkflow = invokeYamlWorkflow;
42
43
  exports.invokeYamlWorkflowSync = invokeYamlWorkflowSync;
43
44
  exports.stopEngine = stopEngine;
@@ -142,12 +143,23 @@ async function activateYamlWorkflow(appId, version) {
142
143
  logger_1.loggerRegistry.info(`[yaml-workflow] activated ${appId} v${version}`);
143
144
  return result;
144
145
  }
146
+ /** The key compiled workflow activities read their identity context from. */
147
+ exports.SCOPE_KEY = '_scope';
148
+ /**
149
+ * The trigger data a compiled workflow starts with. Identity context is never
150
+ * taken from the data a caller supplied: any `_scope` there is dropped, and
151
+ * only the scope the server resolved is set.
152
+ */
153
+ function withTrustedScope(data, scope) {
154
+ const { [exports.SCOPE_KEY]: _dropped, ...rest } = data ?? {};
155
+ return scope ? { ...rest, [exports.SCOPE_KEY]: scope } : rest;
156
+ }
145
157
  /**
146
158
  * Invoke a YAML workflow (fire-and-forget). Returns the job ID.
147
159
  */
148
- async function invokeYamlWorkflow(appId, topic, data, entity, context) {
160
+ async function invokeYamlWorkflow(appId, topic, data, entity, context, scope) {
149
161
  const engine = await getEngine(appId);
150
- return engine.pub(topic, data, context, entity ? { entity } : undefined);
162
+ return engine.pub(topic, withTrustedScope(data, scope), context, entity ? { entity } : undefined);
151
163
  }
152
164
  /**
153
165
  * Invoke a YAML workflow and wait for the result.
@@ -158,7 +170,7 @@ async function invokeYamlWorkflow(appId, topic, data, entity, context) {
158
170
  *
159
171
  * Source: @hotmeshio/hotmesh engine/index.js pubsub()
160
172
  */
161
- async function invokeYamlWorkflowSync(appId, topic, data, timeout, entity) {
173
+ async function invokeYamlWorkflowSync(appId, topic, data, timeout, entity, scope) {
162
174
  const hotmesh = await getEngine(appId);
163
175
  const engine = hotmesh.engine;
164
176
  const timeoutMs = timeout ?? defaults_1.WORKFLOW_SYNC_TIMEOUT_MS;
@@ -171,7 +183,7 @@ async function invokeYamlWorkflowSync(appId, topic, data, timeout, entity) {
171
183
  };
172
184
  // Publish with entity via extended param
173
185
  const extended = entity ? { entity } : undefined;
174
- const jobId = await engine.pub(topic, data, context, extended);
186
+ const jobId = await engine.pub(topic, withTrustedScope(data, scope), context, extended);
175
187
  return new Promise((resolve, reject) => {
176
188
  engine.registerJobCallback(jobId, (_topic, output) => {
177
189
  if (output.metadata.err) {
@@ -37,36 +37,37 @@ exports.invokeYamlWorkflow = invokeYamlWorkflow;
37
37
  const yamlDeployer = __importStar(require("./deployer"));
38
38
  const principal_1 = require("../iam/principal");
39
39
  const publish_1 = require("../../lib/events/publish");
40
+ /**
41
+ * The identity context compiled workflow activities run under, from the
42
+ * server-side identity: execute_as with the invoker as initiator, else the
43
+ * invoker. Never read from the caller's data.
44
+ */
45
+ async function resolveScope(executeAs, userId) {
46
+ if (executeAs) {
47
+ const [botPrincipal, invokerPrincipal] = await Promise.all([
48
+ (0, principal_1.resolvePrincipal)(executeAs),
49
+ userId ? (0, principal_1.resolvePrincipal)(userId) : Promise.resolve(null),
50
+ ]);
51
+ if (!botPrincipal)
52
+ return undefined;
53
+ return {
54
+ principal: botPrincipal,
55
+ scopes: ['mcp:tool:call'],
56
+ ...(invokerPrincipal ? { initiatedBy: userId, initiatingPrincipal: invokerPrincipal } : {}),
57
+ };
58
+ }
59
+ if (!userId)
60
+ return undefined;
61
+ const principal = await (0, principal_1.resolvePrincipal)(userId);
62
+ return principal ? { principal, scopes: ['mcp:tool:call'] } : undefined;
63
+ }
40
64
  /**
41
65
  * Invoke a YAML workflow with scope injection.
42
66
  * Shared by HTTP route and cron callback.
43
67
  */
44
68
  async function invokeYamlWorkflow(wf, options = {}) {
45
69
  const data = { ...(options.data || {}) };
46
- // Inject _scope so compiled workflow activities have identity context
47
- if (!data._scope) {
48
- const executeAs = options.execute_as;
49
- const userId = options.userId;
50
- if (executeAs) {
51
- const [botPrincipal, invokerPrincipal] = await Promise.all([
52
- (0, principal_1.resolvePrincipal)(executeAs),
53
- userId ? (0, principal_1.resolvePrincipal)(userId) : Promise.resolve(null),
54
- ]);
55
- if (botPrincipal) {
56
- data._scope = {
57
- principal: botPrincipal,
58
- scopes: ['mcp:tool:call'],
59
- ...(invokerPrincipal ? { initiatedBy: userId, initiatingPrincipal: invokerPrincipal } : {}),
60
- };
61
- }
62
- }
63
- else if (userId) {
64
- const principal = await (0, principal_1.resolvePrincipal)(userId);
65
- if (principal) {
66
- data._scope = { principal, scopes: ['mcp:tool:call'] };
67
- }
68
- }
69
- }
70
+ const scope = await resolveScope(options.execute_as, options.userId);
70
71
  if (options.source) {
71
72
  if (!data._metadata)
72
73
  data._metadata = {};
@@ -85,7 +86,7 @@ async function invokeYamlWorkflow(wf, options = {}) {
85
86
  status: 'running',
86
87
  });
87
88
  try {
88
- const { job_id, result } = await yamlDeployer.invokeYamlWorkflowSync(wf.app_id, wf.graph_topic, data, options.timeout, wf.graph_topic);
89
+ const { job_id, result } = await yamlDeployer.invokeYamlWorkflowSync(wf.app_id, wf.graph_topic, data, options.timeout, wf.graph_topic, scope);
89
90
  (0, publish_1.publishWorkflowEvent)({
90
91
  type: 'workflow.completed',
91
92
  source: 'graph',
@@ -121,7 +122,7 @@ async function invokeYamlWorkflow(wf, options = {}) {
121
122
  },
122
123
  }
123
124
  : undefined;
124
- const jobId = await yamlDeployer.invokeYamlWorkflow(wf.app_id, wf.graph_topic, data, wf.graph_topic, context);
125
+ const jobId = await yamlDeployer.invokeYamlWorkflow(wf.app_id, wf.graph_topic, data, wf.graph_topic, context, scope);
125
126
  (0, publish_1.publishWorkflowEvent)({
126
127
  type: 'workflow.started',
127
128
  source: 'graph',
@@ -100,6 +100,13 @@ async function applyServerAuthConfig(startConfig) {
100
100
  baseUrl: startConfig.auth.oauth.baseUrl,
101
101
  });
102
102
  }
103
+ const oauthServer = startConfig.auth?.oauthServer
104
+ ?? (config_1.config.LT_OAUTH_ISSUER ? { issuer: config_1.config.LT_OAUTH_ISSUER } : undefined);
105
+ if (oauthServer) {
106
+ const { setOAuthServerConfig } = await Promise.resolve().then(() => __importStar(require('../modules/oauth-server')));
107
+ setOAuthServerConfig(oauthServer);
108
+ logger_1.loggerRegistry.info(`[long-tail] OAuth authorization server enabled — issuer ${oauthServer.issuer}`);
109
+ }
103
110
  // SSO — store config for requireAuth fallback and /api/auth/sso exchange
104
111
  if (startConfig.auth?.sso) {
105
112
  const { setSSOConfig } = await Promise.resolve().then(() => __importStar(require('../modules/sso')));
@@ -13,10 +13,8 @@ const config_1 = require("./config");
13
13
  const adapters_1 = require("./adapters");
14
14
  const workers_1 = require("./workers");
15
15
  const server_1 = require("./server");
16
- const socketio_1 = require("../lib/events/socketio");
16
+ const express_1 = require("../adapters/express");
17
17
  const system_events_1 = require("../lib/events/system-events");
18
- const nats_1 = require("../lib/events/nats");
19
- const nats_ws_proxy_1 = require("../lib/events/nats-ws-proxy");
20
18
  /**
21
19
  * Start Long Tail with a declarative configuration.
22
20
  *
@@ -75,25 +73,9 @@ async function start(startConfig) {
75
73
  const serverEnabled = startConfig.server?.enabled !== false;
76
74
  let httpServer = null;
77
75
  if (serverEnabled) {
78
- httpServer = (0, server_1.startServer)();
79
- // Attach socket.io adapter to the HTTP server (if registered)
80
- const socketAdapter = events_1.eventRegistry.getAdapter(socketio_1.SocketIOEventAdapter);
81
- if (socketAdapter && httpServer) {
82
- socketAdapter.attachServer(httpServer);
83
- await socketAdapter.connect();
84
- }
85
- // Attach NATS WebSocket proxy (if configured)
86
- const natsAdapter = events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
87
- if (natsAdapter?.wsProxyTarget && httpServer) {
88
- (0, nats_ws_proxy_1.attachNatsWsProxy)(httpServer, natsAdapter.wsProxyTarget, {
89
- onWsUrlDerived: (url) => {
90
- // Auto-set wsUrl if not explicitly configured
91
- if (!natsAdapter.wsUrl) {
92
- natsAdapter.setWsUrl(url);
93
- }
94
- },
95
- });
96
- }
76
+ const adapter = new express_1.LTExpressAdapter();
77
+ httpServer = (0, server_1.startServer)(adapter);
78
+ await adapter.attachServer(httpServer);
97
79
  }
98
80
  // 7. Return instance
99
81
  const connection = (0, workers_1.buildConnection)();
@@ -1,6 +1,8 @@
1
- import express from 'express';
1
+ import type { Server } from 'http';
2
+ import { LTExpressAdapter } from '../adapters/express';
2
3
  /**
3
- * Create and start the embedded Express server with health check,
4
- * API routes, and optional dashboard static assets.
4
+ * Create and start the standalone server. It owns its app and mounts the
5
+ * same router an embedding host mounts, at the root, so standalone and
6
+ * embedded deployments serve one surface.
5
7
  */
6
- export declare function startServer(): ReturnType<typeof express.application.listen>;
8
+ export declare function startServer(adapter: LTExpressAdapter): Server;
@@ -1,52 +1,28 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.startServer = startServer;
7
- const fs_1 = require("fs");
8
- const path_1 = __importDefault(require("path"));
9
- const express_1 = __importDefault(require("express"));
4
+ const http_1 = require("../lib/http");
10
5
  const config_1 = require("../modules/config");
11
6
  const logger_1 = require("../lib/logger");
12
- const routes_1 = __importDefault(require("../routes"));
13
- const mcp_endpoint_1 = __importDefault(require("../routes/mcp-endpoint"));
14
7
  /**
15
- * Create and start the embedded Express server with health check,
16
- * API routes, and optional dashboard static assets.
8
+ * Create and start the standalone server. It owns its app and mounts the
9
+ * same router an embedding host mounts, at the root, so standalone and
10
+ * embedded deployments serve one surface.
17
11
  */
18
- function startServer() {
19
- const app = (0, express_1.default)();
12
+ function startServer(adapter) {
13
+ const app = (0, http_1.createApp)();
20
14
  if (process.env.NODE_ENV !== 'production') {
21
15
  app.disable('etag');
22
16
  }
23
- app.use(express_1.default.json());
24
- app.get('/health', (_req, res) => {
25
- res.json({ status: 'ok', timestamp: new Date().toISOString() });
26
- });
27
- app.use('/api', routes_1.default);
28
- app.use('/mcp', mcp_endpoint_1.default);
29
- // Serve dashboard static assets
30
- // Resolves correctly in both dev (ts-node from root) and prod (node build/)
31
- const devDist = path_1.default.join(__dirname, '..', 'dashboard', 'dist');
32
- const prodDist = path_1.default.join(__dirname, '..', '..', 'dashboard', 'dist');
33
- const dashboardDist = (0, fs_1.existsSync)(devDist) ? devDist : prodDist;
34
- if ((0, fs_1.existsSync)(dashboardDist)) {
35
- app.use(express_1.default.static(dashboardDist, { index: false }));
36
- // SPA fallback — inject <base href="/"> so relative asset paths
37
- // resolve from root regardless of route depth (e.g. /admin/users).
38
- // Read on each request so dashboard rebuilds take effect without restart.
39
- const indexPath = path_1.default.join(dashboardDist, 'index.html');
40
- app.get('/{*splat}', (_req, res) => {
41
- const html = (0, fs_1.readFileSync)(indexPath, 'utf-8').replace('<head>', '<head><base href="/">');
42
- res.type('html').send(html);
43
- });
44
- logger_1.loggerRegistry.info(`[long-tail] Dashboard: http://localhost:${config_1.config.PORT}/`);
45
- }
17
+ app.use(adapter.getWellKnownRouter());
18
+ app.use(adapter.getRouter());
46
19
  const httpServer = app.listen(config_1.config.PORT, () => {
47
20
  logger_1.loggerRegistry.info(`[long-tail] server running on port ${config_1.config.PORT}`);
48
21
  logger_1.loggerRegistry.info(`[long-tail] API: http://localhost:${config_1.config.PORT}/api`);
49
22
  logger_1.loggerRegistry.info(`[long-tail] Health: http://localhost:${config_1.config.PORT}/health`);
23
+ if (adapter.hasDashboard()) {
24
+ logger_1.loggerRegistry.info(`[long-tail] Dashboard: http://localhost:${config_1.config.PORT}/`);
25
+ }
50
26
  });
51
27
  return httpServer;
52
28
  }
@@ -23,7 +23,8 @@ function createSocketIOAuthenticator(startConfig) {
23
23
  return (token) => {
24
24
  try {
25
25
  const payload = jsonwebtoken_1.default.verify(token, secret);
26
- return !!(payload && typeof payload === 'object' && payload.userId);
26
+ const userId = payload && typeof payload === 'object' ? payload.userId : undefined;
27
+ return typeof userId === 'string' && userId ? { userId } : false;
27
28
  }
28
29
  catch {
29
30
  return false;
@@ -315,7 +315,7 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
315
315
  };
316
316
  // 1. Register all factories (runtime — always applied)
317
317
  for (const [name, entry] of Object.entries(allFactories)) {
318
- registerBuiltinServer(name, entry.factory);
318
+ registerBuiltinServer(name, entry.factory, entry.config?.toolManifest);
319
319
  }
320
320
  logger_1.loggerRegistry.info(`[long-tail] ${Object.keys(allFactories).length} MCP server factories registered`);
321
321
  // Set exposure config for the /mcp endpoint
@@ -35,7 +35,22 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerAgentSubscriptionTools = registerAgentSubscriptionTools;
37
37
  const api = __importStar(require("../../../api/agent-subscriptions"));
38
+ const authority_1 = require("../../../services/agent/authority");
39
+ const workflow_invocation_1 = require("../../../services/workflow-invocation");
40
+ const caller_auth_1 = require("../caller-auth");
38
41
  const schemas_1 = require("./schemas");
42
+ /** An MCP error for a refused authority check; null when the call may go on. */
43
+ async function refusal(check) {
44
+ try {
45
+ await check();
46
+ return null;
47
+ }
48
+ catch (err) {
49
+ if (!(err instanceof workflow_invocation_1.InvocationError))
50
+ throw err;
51
+ return { content: [{ type: 'text', text: JSON.stringify({ error: err.message }) }], isError: true };
52
+ }
53
+ }
39
54
  function registerAgentSubscriptionTools(server) {
40
55
  // mirrors GET /api/agents/:agentId/subscriptions
41
56
  server.registerTool('list_agent_subscriptions', {
@@ -55,8 +70,16 @@ function registerAgentSubscriptionTools(server) {
55
70
  description: 'Create an event subscription for an agent. When events match the ' +
56
71
  'topic pattern, the configured reaction is triggered.',
57
72
  inputSchema: schemas_1.createAgentSubscriptionSchema,
58
- }, async (args) => {
73
+ }, async (args, extra) => {
59
74
  const { agent_id, ...body } = args;
75
+ const caller = (0, caller_auth_1.externalCaller)(extra);
76
+ const refused = caller
77
+ ? await refusal(() => (0, authority_1.assertMayConfigureSubscription)(caller.userId, {
78
+ agentId: agent_id, reaction_type: body.reaction_type, execute_as: body.execute_as,
79
+ }))
80
+ : null;
81
+ if (refused)
82
+ return refused;
60
83
  const result = await api.createSubscription({ agentId: agent_id, ...body });
61
84
  if (result.error) {
62
85
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -35,7 +35,22 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerAgentTools = registerAgentTools;
37
37
  const api = __importStar(require("../../../api/agents"));
38
+ const authority_1 = require("../../../services/agent/authority");
39
+ const workflow_invocation_1 = require("../../../services/workflow-invocation");
40
+ const caller_auth_1 = require("../caller-auth");
38
41
  const schemas_1 = require("./schemas");
42
+ /** An MCP error for a refused authority check; null when the call may go on. */
43
+ async function refusal(check) {
44
+ try {
45
+ await check();
46
+ return null;
47
+ }
48
+ catch (err) {
49
+ if (!(err instanceof workflow_invocation_1.InvocationError))
50
+ throw err;
51
+ return { content: [{ type: 'text', text: JSON.stringify({ error: err.message }) }], isError: true };
52
+ }
53
+ }
39
54
  function registerAgentTools(server) {
40
55
  // mirrors GET /api/agents
41
56
  server.registerTool('list_agents', {
@@ -69,7 +84,11 @@ function registerAgentTools(server) {
69
84
  description: 'Create a new agent automation with identity, goals, rules, ' +
70
85
  'optional schedules, and event subscriptions.',
71
86
  inputSchema: schemas_1.createAgentSchema,
72
- }, async (args) => {
87
+ }, async (args, extra) => {
88
+ const caller = (0, caller_auth_1.externalCaller)(extra);
89
+ const refused = caller ? await refusal(() => (0, authority_1.assertMayConfigureAgent)(caller.userId, { ...args, id: undefined })) : null;
90
+ if (refused)
91
+ return refused;
73
92
  const result = await api.createAgent(args);
74
93
  if (result.error) {
75
94
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -81,7 +100,11 @@ function registerAgentTools(server) {
81
100
  title: 'Update Agent',
82
101
  description: 'Update an existing agent automation.',
83
102
  inputSchema: schemas_1.updateAgentSchema,
84
- }, async (args) => {
103
+ }, async (args, extra) => {
104
+ const caller = (0, caller_auth_1.externalCaller)(extra);
105
+ const refused = caller ? await refusal(() => (0, authority_1.assertMayConfigureAgent)(caller.userId, args)) : null;
106
+ if (refused)
107
+ return refused;
85
108
  const result = await api.updateAgent(args);
86
109
  if (result.error) {
87
110
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerAnnouncementTools = registerAnnouncementTools;
37
37
  const zod_1 = require("zod");
38
38
  const api = __importStar(require("../../../api/announcements"));
39
+ const caller_auth_1 = require("../caller-auth");
39
40
  const publishAnnouncementSchema = zod_1.z.object({
40
41
  body: zod_1.z.string().describe('Markdown body — the only required field.'),
41
42
  title: zod_1.z.string().optional().describe('Headline shown on the collapsed banner.'),
@@ -53,14 +54,14 @@ function registerAnnouncementTools(server) {
53
54
  '(default 24h) are optional. Bodies broadcast to all authenticated ' +
54
55
  'subscribers — never include secrets.',
55
56
  inputSchema: publishAnnouncementSchema,
56
- }, async (args) => {
57
+ }, async (args, extra) => {
57
58
  const result = await api.createAnnouncement({
58
59
  body: args.body,
59
60
  title: args.title,
60
61
  layout: args.layout,
61
62
  roles: args.roles,
62
63
  expiresAt: args.expires_at,
63
- }, { userId: 'lt-system', role: 'superadmin' });
64
+ }, (0, caller_auth_1.externalCaller)(extra) ?? { userId: 'lt-system', role: 'superadmin' });
64
65
  if (result.error) {
65
66
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
66
67
  }
@@ -35,7 +35,23 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerBotAccountTools = registerBotAccountTools;
37
37
  const api = __importStar(require("../../../api/bot-accounts"));
38
+ const bot_api_key_1 = require("../../../services/auth/bot-api-key");
39
+ const capabilities_1 = require("../../../modules/capabilities");
40
+ const caller_auth_1 = require("../caller-auth");
38
41
  const schemas_1 = require("./schemas");
42
+ /** An MCP error for a refused decision; null when the call may go on. */
43
+ function refusal(decision) {
44
+ if (decision.allowed)
45
+ return null;
46
+ return { content: [{ type: 'text', text: JSON.stringify({ error: decision.error }) }], isError: true };
47
+ }
48
+ /** For a /mcp caller, the account rule on `botId`; internal calls act as lt-system. */
49
+ async function accountRefusal(extra, botId) {
50
+ const caller = (0, caller_auth_1.externalCaller)(extra);
51
+ if (!caller || !botId)
52
+ return null;
53
+ return refusal(await (0, capabilities_1.mayManageAccount)(caller.userId, botId));
54
+ }
39
55
  function registerBotAccountTools(server) {
40
56
  // mirrors GET /api/bot-accounts
41
57
  server.registerTool('list_bot_accounts', {
@@ -67,7 +83,11 @@ function registerBotAccountTools(server) {
67
83
  description: 'Create a new bot (service) account with optional roles. ' +
68
84
  'Bot accounts can run workflows and hold API keys.',
69
85
  inputSchema: schemas_1.createBotSchema,
70
- }, async (args) => {
86
+ }, async (args, extra) => {
87
+ const caller = (0, caller_auth_1.externalCaller)(extra);
88
+ const refused = caller ? refusal(await (0, capabilities_1.mayGrantRoles)(caller.userId, args.roles)) : null;
89
+ if (refused)
90
+ return refused;
71
91
  const result = await api.createBot(args);
72
92
  if (result.error) {
73
93
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -79,7 +99,10 @@ function registerBotAccountTools(server) {
79
99
  title: 'Update Bot Account',
80
100
  description: 'Update a bot account (display name, description, status).',
81
101
  inputSchema: schemas_1.updateBotSchema,
82
- }, async (args) => {
102
+ }, async (args, extra) => {
103
+ const refused = await accountRefusal(extra, args.id);
104
+ if (refused)
105
+ return refused;
83
106
  const result = await api.updateBot(args);
84
107
  if (result.error) {
85
108
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -91,7 +114,10 @@ function registerBotAccountTools(server) {
91
114
  title: 'Delete Bot Account',
92
115
  description: 'Delete a bot account and all its API keys.',
93
116
  inputSchema: schemas_1.deleteBotSchema,
94
- }, async (args) => {
117
+ }, async (args, extra) => {
118
+ const refused = await accountRefusal(extra, args.id);
119
+ if (refused)
120
+ return refused;
95
121
  const result = await api.deleteBot(args);
96
122
  if (result.error) {
97
123
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -104,7 +130,10 @@ function registerBotAccountTools(server) {
104
130
  description: 'Generate a new API key for a bot account. Returns the raw key ' +
105
131
  'ONCE — it cannot be retrieved again.',
106
132
  inputSchema: schemas_1.createBotApiKeySchema,
107
- }, async (args) => {
133
+ }, async (args, extra) => {
134
+ const refused = await accountRefusal(extra, args.id);
135
+ if (refused)
136
+ return refused;
108
137
  const result = await api.createBotKey(args);
109
138
  if (result.error) {
110
139
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -116,7 +145,10 @@ function registerBotAccountTools(server) {
116
145
  title: 'Revoke Bot API Key',
117
146
  description: 'Revoke (delete) an API key for a bot account.',
118
147
  inputSchema: schemas_1.revokeBotKeySchema,
119
- }, async (args) => {
148
+ }, async (args, extra) => {
149
+ const refused = (0, caller_auth_1.externalCaller)(extra) ? await accountRefusal(extra, await (0, bot_api_key_1.getBotApiKeyOwner)(args.key_id)) : null;
150
+ if (refused)
151
+ return refused;
120
152
  const result = await api.revokeBotKey({ keyId: args.key_id });
121
153
  if (result.error) {
122
154
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -1,11 +1,9 @@
1
1
  /**
2
2
  * Escalation tools — mirrors routes/escalations/
3
3
  *
4
- * Every tool runs as the `lt-system` bot. The escalation RBAC helpers
5
- * (getVisibleRoles / getUserRoles / hasGlobalEscalationAccess) query a uuid
6
- * column, so the bot's external_id string ('lt-system') would blow up with
7
- * `invalid input syntax for type uuid`. `systemAuth()` resolves the bot's real
8
- * UUID once and caches it; that UUID (a superadmin) is passed as the principal.
4
+ * A call that arrived at `/mcp` runs as its caller, so the escalation RBAC in
5
+ * api/ applies to them exactly as it does over REST. Internal calls from
6
+ * workflows and agents run as the `lt-system` bot.
9
7
  */
10
8
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
9
  export declare function registerEscalationTools(server: McpServer): void;