@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
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.mayAdminister = mayAdminister;
37
+ exports.mayBuild = mayBuild;
38
+ exports.mayReadWorkflowRun = mayReadWorkflowRun;
39
+ exports.mayManageRoles = mayManageRoles;
40
+ exports.mayGrantRole = mayGrantRole;
41
+ exports.mayGrantRoles = mayGrantRoles;
42
+ exports.mayManageAccount = mayManageAccount;
43
+ exports.mayRevokeRole = mayRevokeRole;
44
+ exports.resolveCapabilities = resolveCapabilities;
45
+ exports.capabilityAccess = capabilityAccess;
46
+ const user_1 = require("../services/user");
47
+ const export_1 = require("../services/export");
48
+ const uuid_1 = require("../lib/uuid");
49
+ const BUILDER_ROLE = 'engineer';
50
+ async function hasBuilderRole(userId) {
51
+ const { hasRole } = await Promise.resolve().then(() => __importStar(require('../services/user/roles')));
52
+ return hasRole(userId, BUILDER_ROLE);
53
+ }
54
+ /** Admin or superadmin claim, or a superadmin in the database. */
55
+ async function mayAdminister(principal) {
56
+ if (!principal?.userId)
57
+ return false;
58
+ if (principal.role === 'admin' || principal.role === 'superadmin')
59
+ return true;
60
+ return (0, user_1.isSuperAdmin)(principal.userId);
61
+ }
62
+ /** Superadmin (claim or database), or holder of the engineer role. */
63
+ async function mayBuild(principal) {
64
+ if (!principal?.userId)
65
+ return false;
66
+ if (principal.role === 'superadmin')
67
+ return true;
68
+ if (await (0, user_1.isSuperAdmin)(principal.userId))
69
+ return true;
70
+ return hasBuilderRole(principal.userId);
71
+ }
72
+ /**
73
+ * Builder access, or the person a workflow run was started by or runs as,
74
+ * read from the run's own start envelope.
75
+ */
76
+ async function mayReadWorkflowRun(principal, workflowId) {
77
+ if (!principal?.userId)
78
+ return false;
79
+ if (await mayBuild(principal))
80
+ return true;
81
+ const started = await (0, export_1.getWorkflowStartIdentity)(workflowId);
82
+ return !!started && (started.userId === principal.userId || started.initiatedBy === principal.userId);
83
+ }
84
+ /** Anyone who may administer, plus holders of the engineer role. */
85
+ async function mayManageRoles(principal) {
86
+ if (!principal?.userId)
87
+ return false;
88
+ if (await mayAdminister(principal))
89
+ return true;
90
+ return hasBuilderRole(principal.userId);
91
+ }
92
+ /**
93
+ * Whether `granterId` may assign `grant` to a user.
94
+ *
95
+ * - superadmin: any role and type
96
+ * - engineer: any role, never the superadmin type
97
+ * - anyone else: only roles they hold, never the superadmin type
98
+ */
99
+ async function mayGrantRole(granterId, grant) {
100
+ if (await (0, user_1.isSuperAdmin)(granterId))
101
+ return { allowed: true };
102
+ if (grant.type === 'superadmin') {
103
+ return { allowed: false, error: 'Only superadmin can assign superadmin role type' };
104
+ }
105
+ if (await hasBuilderRole(granterId))
106
+ return { allowed: true };
107
+ const { hasRole } = await Promise.resolve().then(() => __importStar(require('../services/user/roles')));
108
+ if (await hasRole(granterId, grant.role))
109
+ return { allowed: true };
110
+ return { allowed: false, error: `You can only assign roles you hold. You do not have the '${grant.role}' role.` };
111
+ }
112
+ const ALLOWED = { allowed: true };
113
+ /** Whether `granterId` may assign every grant in a new account's role list. */
114
+ async function mayGrantRoles(granterId, grants) {
115
+ for (const grant of grants ?? []) {
116
+ const decision = await mayGrantRole(granterId, grant);
117
+ if (!decision.allowed)
118
+ return decision;
119
+ }
120
+ return ALLOWED;
121
+ }
122
+ /**
123
+ * Whether `callerId` may change, remove, or mint keys for an account. An
124
+ * account holding superadmin is a superadmin's to manage; any other account
125
+ * is left to the route's own gate.
126
+ */
127
+ async function mayManageAccount(callerId, targetId) {
128
+ if (await (0, user_1.isSuperAdmin)(callerId))
129
+ return ALLOWED;
130
+ if (!(0, uuid_1.isUuid)(targetId))
131
+ return ALLOWED;
132
+ if (await (0, user_1.isSuperAdmin)(targetId)) {
133
+ return { allowed: false, error: 'Only superadmin can change a superadmin account' };
134
+ }
135
+ return ALLOWED;
136
+ }
137
+ /** Removing a role follows the grant rule for the role as the account holds it. */
138
+ async function mayRevokeRole(callerId, targetId, role) {
139
+ const account = await mayManageAccount(callerId, targetId);
140
+ if (!account.allowed || !(0, uuid_1.isUuid)(targetId))
141
+ return account;
142
+ const { getUserRoles } = await Promise.resolve().then(() => __importStar(require('../services/user')));
143
+ const held = (await getUserRoles(targetId)).find((r) => r.role === role);
144
+ return held ? mayGrantRole(callerId, { role, type: held.type }) : ALLOWED;
145
+ }
146
+ /** Capabilities from memberships carried by the caller's token: the same outcomes, no lookup. */
147
+ function capabilitiesFromRoles(roles) {
148
+ const superadmin = roles.some((r) => r.type === 'superadmin');
149
+ const admin = superadmin || roles.some((r) => r.type === 'admin');
150
+ const engineer = roles.some((r) => r.role === BUILDER_ROLE);
151
+ return { caller: true, admin, builder: superadmin || engineer, roleManager: admin || engineer, superadmin };
152
+ }
153
+ const NO_CAPABILITIES = {
154
+ caller: false, admin: false, builder: false, roleManager: false, superadmin: false,
155
+ };
156
+ /**
157
+ * Every capability the principal holds, with the same outcomes as the
158
+ * predicates above. A superadmin claim costs no lookup; anyone else costs
159
+ * at most one superadmin lookup and one engineer-role lookup.
160
+ */
161
+ async function resolveCapabilities(principal) {
162
+ if (!principal?.userId)
163
+ return NO_CAPABILITIES;
164
+ if (principal.grantRoles)
165
+ return capabilitiesFromRoles(principal.grantRoles);
166
+ if (principal.role === 'superadmin' || (await (0, user_1.isSuperAdmin)(principal.userId))) {
167
+ return { caller: true, admin: true, builder: true, roleManager: true, superadmin: true };
168
+ }
169
+ const admin = principal.role === 'admin';
170
+ const engineer = await hasBuilderRole(principal.userId);
171
+ return { caller: true, admin, builder: engineer, roleManager: admin || engineer, superadmin: false };
172
+ }
173
+ /**
174
+ * Capability checks for one request. `caller` needs only an authenticated
175
+ * principal; any other gate resolves the principal's capabilities once, on
176
+ * first need, so a request that checks only `caller` gates makes no lookup.
177
+ */
178
+ function capabilityAccess(principal) {
179
+ let resolved;
180
+ return async (gate) => {
181
+ if (!principal?.userId)
182
+ return false;
183
+ if (gate === 'caller')
184
+ return true;
185
+ resolved ??= resolveCapabilities(principal);
186
+ return (await resolved)[gate];
187
+ };
188
+ }
@@ -8,9 +8,23 @@ export declare const config: {
8
8
  NATS_URL: string;
9
9
  NATS_WS_URL: string;
10
10
  NATS_TOKEN: string;
11
+ /** A subscribe-only NATS credential for browsers that connect without the proxy. */
12
+ NATS_DASHBOARD_TOKEN: string;
13
+ /** How long a browser's WebSocket proxy ticket admits an upgrade. The dashboard fetches one per attempt. */
14
+ NATS_WS_TICKET_TTL_SECONDS: number;
15
+ /**
16
+ * Dashboard reconnect: first backoff delay, delay cap, how long a drop lasts
17
+ * before the banner shows, and the window the first retry and catch-up
18
+ * refetch spread across.
19
+ */
20
+ NATS_RECONNECT_INITIAL_MS: number;
21
+ NATS_RECONNECT_MAX_MS: number;
22
+ NATS_LIVE_NOTICE_AFTER_MS: number;
23
+ NATS_RECONNECT_SPREAD_MS: number;
11
24
  PORT: number;
12
25
  NODE_ENV: string;
13
26
  JWT_SECRET: string;
27
+ LT_OAUTH_ISSUER: string;
14
28
  HONEYCOMB_API_KEY: string;
15
29
  ROLE_ENFORCEMENT_CACHE_TTL_MS: number;
16
30
  LT_ANALYTICS_MAX_GROUPS: number;
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.postgres_options = exports.config = void 0;
4
+ /** A positive integer from the environment, or the default when unset or malformed. */
5
+ function positiveInt(name, fallback) {
6
+ const value = Number(process.env[name]);
7
+ return Number.isInteger(value) && value > 0 ? value : fallback;
8
+ }
4
9
  exports.config = {
5
10
  POSTGRES_HOST: process.env.POSTGRES_HOST || 'localhost',
6
11
  POSTGRES_PORT: parseInt(process.env.POSTGRES_PORT || '5415', 10),
@@ -15,9 +20,24 @@ exports.config = {
15
20
  NATS_URL: process.env.NATS_URL || 'nats://localhost:4222',
16
21
  NATS_WS_URL: process.env.NATS_WS_URL || '',
17
22
  NATS_TOKEN: process.env.NATS_TOKEN || '',
23
+ /** A subscribe-only NATS credential for browsers that connect without the proxy. */
24
+ NATS_DASHBOARD_TOKEN: process.env.NATS_DASHBOARD_TOKEN || '',
25
+ /** How long a browser's WebSocket proxy ticket admits an upgrade. The dashboard fetches one per attempt. */
26
+ NATS_WS_TICKET_TTL_SECONDS: positiveInt('NATS_WS_TICKET_TTL_SECONDS', 300),
27
+ /**
28
+ * Dashboard reconnect: first backoff delay, delay cap, how long a drop lasts
29
+ * before the banner shows, and the window the first retry and catch-up
30
+ * refetch spread across.
31
+ */
32
+ NATS_RECONNECT_INITIAL_MS: positiveInt('NATS_RECONNECT_INITIAL_MS', 1000),
33
+ NATS_RECONNECT_MAX_MS: positiveInt('NATS_RECONNECT_MAX_MS', 60000),
34
+ NATS_LIVE_NOTICE_AFTER_MS: positiveInt('NATS_LIVE_NOTICE_AFTER_MS', 30000),
35
+ NATS_RECONNECT_SPREAD_MS: positiveInt('NATS_RECONNECT_SPREAD_MS', 5000),
18
36
  PORT: parseInt(process.env.PORT || '3000', 10),
19
37
  NODE_ENV: process.env.NODE_ENV || 'development',
20
38
  JWT_SECRET: process.env.JWT_SECRET || '',
39
+ // Enables the OAuth authorization server for /mcp when start() passes no auth.oauthServer.
40
+ LT_OAUTH_ISSUER: process.env.LT_OAUTH_ISSUER || '',
21
41
  HONEYCOMB_API_KEY: process.env.HONEYCOMB_API_KEY || '',
22
42
  // Resolver schema enforcement: TTL for the cached enforcing-role set and
23
43
  // latest role form schemas. Bounds cross-container staleness after a role
@@ -60,3 +60,13 @@ export declare const CLAIM_DURATION_OPTIONS: number[];
60
60
  export declare const STOP_WORDS: Set<string>;
61
61
  /** YAML dump line width. */
62
62
  export declare const YAML_LINE_WIDTH: number;
63
+ /** Access-token lifetime. Bounds how stale a token's roles can be when no revocation event arrives. */
64
+ export declare const OAUTH_ACCESS_TOKEN_TTL_SECONDS: number;
65
+ /** Refresh-token lifetime. Each refresh issues a new one. */
66
+ export declare const OAUTH_REFRESH_TOKEN_TTL_SECONDS: number;
67
+ /** Authorization-code lifetime, from consent to the client's token request. */
68
+ export declare const OAUTH_CODE_TTL_SECONDS: number;
69
+ /** Client registrations allowed per address in each window. */
70
+ export declare const OAUTH_REGISTRATIONS_PER_WINDOW: number;
71
+ /** Registration rate-limit window. */
72
+ export declare const OAUTH_REGISTRATION_WINDOW_SECONDS: number;
@@ -9,7 +9,7 @@
9
9
  * Grouped by domain so related knobs live together.
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.YAML_LINE_WIDTH = exports.STOP_WORDS = exports.CLAIM_DURATION_OPTIONS = exports.ESCALATION_BULK_RESOLVE_MAX = exports.YAML_VERSION_LIMIT = exports.YAML_LIST_LIMIT = exports.QUERY_LIMIT_MAX = exports.QUERY_LIMIT_DEFAULT = exports.CONFIG_CACHE_TTL_MS = exports.MCP_TOOL_TIMEOUT_MS = exports.WORKFLOW_SYNC_TIMEOUT_MS = exports.JOB_EXPIRE_SECS = exports.WORKFLOW_EXPIRE_SECS = exports.TOOL_ARG_LIMIT_CAP = exports.TOOL_ROUNDS_MCP_QUERY = exports.TOOL_ROUNDS_TRIAGE = exports.TOOL_RESULT_MAX_CHARS = exports.LLM_MAX_INPUT_CHARS = exports.LLM_MAX_ARRAY_ITEMS = exports.LLM_MAX_TOKENS_VISION = exports.LLM_MAX_TOKENS_JSON = exports.LLM_MAX_TOKENS_DEFAULT = exports.LLM_BASE_URL = exports.LLM_MODEL_SECONDARY = exports.LLM_MODEL_PRIMARY = void 0;
12
+ exports.OAUTH_REGISTRATION_WINDOW_SECONDS = exports.OAUTH_REGISTRATIONS_PER_WINDOW = exports.OAUTH_CODE_TTL_SECONDS = exports.OAUTH_REFRESH_TOKEN_TTL_SECONDS = exports.OAUTH_ACCESS_TOKEN_TTL_SECONDS = exports.YAML_LINE_WIDTH = exports.STOP_WORDS = exports.CLAIM_DURATION_OPTIONS = exports.ESCALATION_BULK_RESOLVE_MAX = exports.YAML_VERSION_LIMIT = exports.YAML_LIST_LIMIT = exports.QUERY_LIMIT_MAX = exports.QUERY_LIMIT_DEFAULT = exports.CONFIG_CACHE_TTL_MS = exports.MCP_TOOL_TIMEOUT_MS = exports.WORKFLOW_SYNC_TIMEOUT_MS = exports.JOB_EXPIRE_SECS = exports.WORKFLOW_EXPIRE_SECS = exports.TOOL_ARG_LIMIT_CAP = exports.TOOL_ROUNDS_MCP_QUERY = exports.TOOL_ROUNDS_TRIAGE = exports.TOOL_RESULT_MAX_CHARS = exports.LLM_MAX_INPUT_CHARS = exports.LLM_MAX_ARRAY_ITEMS = exports.LLM_MAX_TOKENS_VISION = exports.LLM_MAX_TOKENS_JSON = exports.LLM_MAX_TOKENS_DEFAULT = exports.LLM_BASE_URL = exports.LLM_MODEL_SECONDARY = exports.LLM_MODEL_PRIMARY = void 0;
13
13
  function envInt(key, fallback) {
14
14
  const v = process.env[key];
15
15
  if (v === undefined || v === '')
@@ -97,3 +97,14 @@ exports.STOP_WORDS = new Set([
97
97
  // ── Formatting ───────────────────────────────────────────────────────
98
98
  /** YAML dump line width. */
99
99
  exports.YAML_LINE_WIDTH = envInt('LT_YAML_LINE_WIDTH', 120);
100
+ // ── OAuth authorization server ───────────────────────────────────────
101
+ /** Access-token lifetime. Bounds how stale a token's roles can be when no revocation event arrives. */
102
+ exports.OAUTH_ACCESS_TOKEN_TTL_SECONDS = envInt('LT_OAUTH_ACCESS_TOKEN_TTL_SECONDS', 300);
103
+ /** Refresh-token lifetime. Each refresh issues a new one. */
104
+ exports.OAUTH_REFRESH_TOKEN_TTL_SECONDS = envInt('LT_OAUTH_REFRESH_TOKEN_TTL_SECONDS', 30 * 24 * 60 * 60);
105
+ /** Authorization-code lifetime, from consent to the client's token request. */
106
+ exports.OAUTH_CODE_TTL_SECONDS = envInt('LT_OAUTH_CODE_TTL_SECONDS', 60);
107
+ /** Client registrations allowed per address in each window. */
108
+ exports.OAUTH_REGISTRATIONS_PER_WINDOW = envInt('LT_OAUTH_REGISTRATIONS_PER_WINDOW', 20);
109
+ /** Registration rate-limit window. */
110
+ exports.OAUTH_REGISTRATION_WINDOW_SECONDS = envInt('LT_OAUTH_REGISTRATION_WINDOW_SECONDS', 600);
@@ -0,0 +1,11 @@
1
+ import type { RequestHandler } from '../lib/http';
2
+ /**
3
+ * Authentication for `/mcp`. Only a credential the request carries itself
4
+ * authenticates: the host's SSO cookie fallback never applies here, since a
5
+ * cookie rides along on a request any page the person visits can send. With
6
+ * the OAuth server configured, an access token for this resource
7
+ * authenticates the request while its grant is live, and every 401 carries
8
+ * the RFC 9728 challenge so MCP clients can discover how to sign in. Any other
9
+ * credential goes through the configured auth adapter unchanged.
10
+ */
11
+ export declare const requireMcpAuth: RequestHandler;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.requireMcpAuth = void 0;
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const auth_1 = require("./auth");
9
+ const oauth_server_1 = require("./oauth-server");
10
+ const oauth_server_2 = require("../services/auth/oauth-server");
11
+ const CHALLENGE_HEADER = 'WWW-Authenticate';
12
+ function bearerToken(req) {
13
+ const header = req.headers.authorization;
14
+ return header?.startsWith('Bearer ') ? header.slice(7) : null;
15
+ }
16
+ function isAccessToken(token) {
17
+ const decoded = jsonwebtoken_1.default.decode(token, { complete: true });
18
+ return decoded?.header?.typ === oauth_server_2.ACCESS_TOKEN_TYPE;
19
+ }
20
+ function challenge(settings, error) {
21
+ const base = `Bearer resource_metadata="${settings.resourceMetadataUrl}"`;
22
+ return error ? `${base}, error="${error}"` : base;
23
+ }
24
+ /**
25
+ * Authentication for `/mcp`. Only a credential the request carries itself
26
+ * authenticates: the host's SSO cookie fallback never applies here, since a
27
+ * cookie rides along on a request any page the person visits can send. With
28
+ * the OAuth server configured, an access token for this resource
29
+ * authenticates the request while its grant is live, and every 401 carries
30
+ * the RFC 9728 challenge so MCP clients can discover how to sign in. Any other
31
+ * credential goes through the configured auth adapter unchanged.
32
+ */
33
+ const requireMcpAuth = async (req, res, next) => {
34
+ const settings = (0, oauth_server_1.getOAuthServerSettings)();
35
+ if (!settings)
36
+ return (0, auth_1.requireCredentialAuth)(req, res, next);
37
+ const token = bearerToken(req);
38
+ if (token && isAccessToken(token)) {
39
+ const claims = (0, oauth_server_2.verifyAccessToken)(token, { issuer: settings.issuer, audience: settings.resource });
40
+ const live = claims ? await (0, oauth_server_2.getLiveGrant)(claims.gid, claims.sub) : null;
41
+ if (!claims || !live || live.client_id !== claims.client_id) {
42
+ res.setHeader(CHALLENGE_HEADER, challenge(settings, 'invalid_token'));
43
+ res.status(401).json({ error: 'invalid_token' });
44
+ return;
45
+ }
46
+ req.auth = (0, oauth_server_2.accessTokenPrincipal)(claims, live);
47
+ next();
48
+ return;
49
+ }
50
+ res.setHeader(CHALLENGE_HEADER, challenge(settings));
51
+ return (0, auth_1.requireCredentialAuth)(req, res, (err) => {
52
+ res.removeHeader(CHALLENGE_HEADER);
53
+ next(err);
54
+ });
55
+ };
56
+ exports.requireMcpAuth = requireMcpAuth;
@@ -0,0 +1,18 @@
1
+ import type { LTOAuthServerConfig } from '../types/oauth-server';
2
+ /** The configured authorization server, with the URLs derived from its issuer. */
3
+ export interface OAuthServerSettings {
4
+ issuer: string;
5
+ /** The protected resource, and the audience of its access tokens. */
6
+ resource: string;
7
+ /** RFC 9728 protected-resource metadata URL for `resource`. */
8
+ resourceMetadataUrl: string;
9
+ /** Canonical https redirect URIs allowed beyond loopback. */
10
+ allowedRedirectUris: string[];
11
+ }
12
+ /** An https URI in canonical form, or null when it is not one (a malformed entry never matches). */
13
+ export declare function canonicalHttpsUri(uri: string): string | null;
14
+ export declare function setOAuthServerConfig(config: LTOAuthServerConfig): void;
15
+ /** Read per request: routers may be mounted before start() configures the server. */
16
+ export declare function getOAuthServerSettings(): OAuthServerSettings | null;
17
+ /** Reset. Used by tests. */
18
+ export declare function clearOAuthServerConfig(): void;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canonicalHttpsUri = canonicalHttpsUri;
4
+ exports.setOAuthServerConfig = setOAuthServerConfig;
5
+ exports.getOAuthServerSettings = getOAuthServerSettings;
6
+ exports.clearOAuthServerConfig = clearOAuthServerConfig;
7
+ /** An https URI in canonical form, or null when it is not one (a malformed entry never matches). */
8
+ function canonicalHttpsUri(uri) {
9
+ try {
10
+ const url = new URL(uri);
11
+ if (url.protocol !== 'https:' || url.username || url.password || url.hash)
12
+ return null;
13
+ return url.href;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ let settings = null;
20
+ function setOAuthServerConfig(config) {
21
+ const issuer = config.issuer.replace(/\/+$/, '');
22
+ const resource = `${issuer}/mcp`;
23
+ const url = new URL(resource);
24
+ settings = {
25
+ issuer,
26
+ resource,
27
+ resourceMetadataUrl: `${url.origin}/.well-known/oauth-protected-resource${url.pathname}`,
28
+ allowedRedirectUris: (config.allowedRedirectUris ?? [])
29
+ .map(canonicalHttpsUri)
30
+ .filter((uri) => uri !== null),
31
+ };
32
+ }
33
+ /** Read per request: routers may be mounted before start() configures the server. */
34
+ function getOAuthServerSettings() {
35
+ return settings;
36
+ }
37
+ /** Reset. Used by tests. */
38
+ function clearOAuthServerConfig() {
39
+ settings = null;
40
+ }
@@ -33,10 +33,26 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const express_1 = require("express");
36
+ const http_1 = require("../lib/http");
37
37
  const api = __importStar(require("../api/agents"));
38
38
  const subApi = __importStar(require("../api/agent-subscriptions"));
39
- const router = (0, express_1.Router)();
39
+ const auth_1 = require("../modules/auth");
40
+ const authority_1 = require("../services/agent/authority");
41
+ const workflow_invocation_1 = require("../services/workflow-invocation");
42
+ const router = (0, http_1.Router)();
43
+ /** Run an authority check; answer its refusal and return false when it refuses. */
44
+ async function authorized(check, res) {
45
+ try {
46
+ await check();
47
+ return true;
48
+ }
49
+ catch (err) {
50
+ if (!(err instanceof workflow_invocation_1.InvocationError))
51
+ throw err;
52
+ res.status(err.statusCode).json({ error: err.message });
53
+ return false;
54
+ }
55
+ }
40
56
  /**
41
57
  * GET /api/agents
42
58
  * List agents with optional filters.
@@ -63,12 +79,14 @@ router.get('/:id', async (req, res) => {
63
79
  * POST /api/agents
64
80
  * Create a new agent.
65
81
  */
66
- router.post('/', async (req, res) => {
82
+ router.post('/', auth_1.requireBuilder, async (req, res) => {
67
83
  const { id } = req.body;
68
84
  if (!id) {
69
85
  res.status(400).json({ error: 'id is required (kebab-case agent name, e.g. "content-triage")' });
70
86
  return;
71
87
  }
88
+ if (!(await authorized(() => (0, authority_1.assertMayConfigureAgent)(req.auth.userId, { ...req.body, id: undefined }), res)))
89
+ return;
72
90
  const auth = { userId: req.userId, roles: req.roles };
73
91
  const result = await api.createAgent(req.body, auth);
74
92
  res.status(result.status).json(result.data ?? { error: result.error });
@@ -77,16 +95,19 @@ router.post('/', async (req, res) => {
77
95
  * PUT /api/agents/:id
78
96
  * Update an existing agent.
79
97
  */
80
- router.put('/:id', async (req, res) => {
81
- const result = await api.updateAgent({ id: req.params.id, ...req.body });
98
+ router.put('/:id', auth_1.requireBuilder, async (req, res) => {
99
+ const id = String(req.params.id);
100
+ if (!(await authorized(() => (0, authority_1.assertMayConfigureAgent)(req.auth.userId, { ...req.body, id }), res)))
101
+ return;
102
+ const result = await api.updateAgent({ ...req.body, id });
82
103
  res.status(result.status).json(result.data ?? { error: result.error });
83
104
  });
84
105
  /**
85
106
  * DELETE /api/agents/:id
86
107
  * Delete an agent.
87
108
  */
88
- router.delete('/:id', async (req, res) => {
89
- const result = await api.deleteAgent({ id: req.params.id });
109
+ router.delete('/:id', auth_1.requireBuilder, async (req, res) => {
110
+ const result = await api.deleteAgent({ id: String(req.params.id) });
90
111
  res.status(result.status).json(result.data ?? { error: result.error });
91
112
  });
92
113
  // ── Subscription routes (nested under agent) ─────────────────────────────────
@@ -102,29 +123,40 @@ router.get('/:agentId/subscriptions', async (req, res) => {
102
123
  * POST /api/agents/:agentId/subscriptions
103
124
  * Create an event subscription for an agent.
104
125
  */
105
- router.post('/:agentId/subscriptions', async (req, res) => {
106
- const { topic, reaction_type } = req.body;
126
+ router.post('/:agentId/subscriptions', auth_1.requireBuilder, async (req, res) => {
127
+ const { topic, reaction_type, execute_as } = req.body;
107
128
  if (!topic || !reaction_type) {
108
129
  res.status(400).json({ error: 'topic and reaction_type are required' });
109
130
  return;
110
131
  }
111
- const result = await subApi.createSubscription({ agentId: req.params.agentId, ...req.body });
132
+ const agentId = String(req.params.agentId);
133
+ const check = () => (0, authority_1.assertMayConfigureSubscription)(req.auth.userId, { agentId, reaction_type, execute_as });
134
+ if (!(await authorized(check, res)))
135
+ return;
136
+ const result = await subApi.createSubscription({ ...req.body, agentId });
112
137
  res.status(result.status).json(result.data ?? { error: result.error });
113
138
  });
114
139
  /**
115
140
  * PUT /api/agents/:agentId/subscriptions/:subId
116
141
  * Update an event subscription.
117
142
  */
118
- router.put('/:agentId/subscriptions/:subId', async (req, res) => {
119
- const result = await subApi.updateSubscription({ id: req.params.subId, ...req.body });
143
+ router.put('/:agentId/subscriptions/:subId', auth_1.requireBuilder, async (req, res) => {
144
+ const agentId = String(req.params.agentId);
145
+ const id = String(req.params.subId);
146
+ const check = () => (0, authority_1.assertMayConfigureSubscription)(req.auth.userId, {
147
+ agentId, subscriptionId: id, reaction_type: req.body?.reaction_type, execute_as: req.body?.execute_as,
148
+ });
149
+ if (!(await authorized(check, res)))
150
+ return;
151
+ const result = await subApi.updateSubscription({ ...req.body, id });
120
152
  res.status(result.status).json(result.data ?? { error: result.error });
121
153
  });
122
154
  /**
123
155
  * DELETE /api/agents/:agentId/subscriptions/:subId
124
156
  * Delete an event subscription.
125
157
  */
126
- router.delete('/:agentId/subscriptions/:subId', async (req, res) => {
127
- const result = await subApi.deleteSubscription({ id: req.params.subId });
158
+ router.delete('/:agentId/subscriptions/:subId', auth_1.requireBuilder, async (req, res) => {
159
+ const result = await subApi.deleteSubscription({ id: String(req.params.subId) });
128
160
  res.status(result.status).json(result.data ?? { error: result.error });
129
161
  });
130
162
  exports.default = router;
@@ -33,10 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const express_1 = require("express");
36
+ const http_1 = require("../lib/http");
37
37
  const api = __importStar(require("../api/announcements"));
38
38
  const auth_1 = require("../modules/auth");
39
- const router = (0, express_1.Router)();
39
+ const router = (0, http_1.Router)();
40
40
  /**
41
41
  * Dashboard announcements. Publishing and removal are role-manager acts
42
42
  * (superadmin, admin type, or engineer); any authenticated user reads their
@@ -33,9 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const express_1 = require("express");
36
+ const http_1 = require("../lib/http");
37
37
  const api = __importStar(require("../api/auth-sso"));
38
- const router = (0, express_1.Router)();
38
+ const router = (0, http_1.Router)();
39
39
  /**
40
40
  * POST /api/auth/sso
41
41
  * Exchange host authentication for a Long Tail JWT.
@@ -33,9 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const express_1 = require("express");
36
+ const http_1 = require("../lib/http");
37
37
  const api = __importStar(require("../api/auth"));
38
- const router = (0, express_1.Router)();
38
+ const router = (0, http_1.Router)();
39
39
  /**
40
40
  * POST /api/auth/login
41
41
  * Authenticate with username (external_id) and password.
@@ -33,10 +33,18 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const express_1 = require("express");
36
+ const http_1 = require("../lib/http");
37
37
  const auth_1 = require("../modules/auth");
38
+ const capabilities_1 = require("../modules/capabilities");
38
39
  const api = __importStar(require("../api/bot-accounts"));
39
- const router = (0, express_1.Router)();
40
+ const router = (0, http_1.Router)();
41
+ /** Answer a refused decision with 403; true when the request may go on. */
42
+ function allowed(decision, res) {
43
+ if (decision.allowed)
44
+ return true;
45
+ res.status(403).json({ error: decision.error });
46
+ return false;
47
+ }
40
48
  // All bot account routes require admin access
41
49
  router.use(auth_1.requireBuilder);
42
50
  // ── Bot CRUD ─────────────────────────────────────────────────────────────────
@@ -69,6 +77,8 @@ router.get('/:id', async (req, res) => {
69
77
  */
70
78
  router.post('/', async (req, res) => {
71
79
  const { name, description, display_name, roles } = req.body || {};
80
+ if (!allowed(await (0, capabilities_1.mayGrantRoles)(req.auth.userId, roles), res))
81
+ return;
72
82
  const result = await api.createBot({ name, description, display_name, roles }, req.auth ? { userId: req.auth.userId } : undefined);
73
83
  res.status(result.status).json(result.data ?? { error: result.error });
74
84
  });
@@ -78,6 +88,8 @@ router.post('/', async (req, res) => {
78
88
  * Body: { display_name?, description?, status? }
79
89
  */
80
90
  router.put('/:id', async (req, res) => {
91
+ if (!allowed(await (0, capabilities_1.mayManageAccount)(req.auth.userId, String(req.params.id)), res))
92
+ return;
81
93
  const result = await api.updateBot({ id: req.params.id, ...(req.body || {}) });
82
94
  res.status(result.status).json(result.data ?? { error: result.error });
83
95
  });
@@ -86,6 +98,8 @@ router.put('/:id', async (req, res) => {
86
98
  * Delete a bot account.
87
99
  */
88
100
  router.delete('/:id', async (req, res) => {
101
+ if (!allowed(await (0, capabilities_1.mayManageAccount)(req.auth.userId, String(req.params.id)), res))
102
+ return;
89
103
  const result = await api.deleteBot({ id: req.params.id });
90
104
  res.status(result.status).json(result.data ?? { error: result.error });
91
105
  });
@@ -105,6 +119,8 @@ router.get('/:id/roles', async (req, res) => {
105
119
  */
106
120
  router.post('/:id/roles', async (req, res) => {
107
121
  const { role, type } = req.body || {};
122
+ if (!allowed(await (0, capabilities_1.mayGrantRole)(req.auth.userId, { role, type }), res))
123
+ return;
108
124
  const result = await api.addBotRole({ id: req.params.id, role, type });
109
125
  res.status(result.status).json(result.data ?? { error: result.error });
110
126
  });
@@ -113,6 +129,8 @@ router.post('/:id/roles', async (req, res) => {
113
129
  * Remove a role from a bot.
114
130
  */
115
131
  router.delete('/:id/roles/:role', async (req, res) => {
132
+ if (!allowed(await (0, capabilities_1.mayRevokeRole)(req.auth.userId, String(req.params.id), String(req.params.role)), res))
133
+ return;
116
134
  const result = await api.removeBotRole({ id: req.params.id, role: req.params.role });
117
135
  res.status(result.status).json(result.data ?? { error: result.error });
118
136
  });
@@ -132,6 +150,8 @@ router.get('/:id/api-keys', async (req, res) => {
132
150
  * Returns the raw key ONCE — it cannot be retrieved again.
133
151
  */
134
152
  router.post('/:id/api-keys', async (req, res) => {
153
+ if (!allowed(await (0, capabilities_1.mayManageAccount)(req.auth.userId, String(req.params.id)), res))
154
+ return;
135
155
  const { name, scopes, expires_at } = req.body || {};
136
156
  const result = await api.createBotKey({
137
157
  id: req.params.id,
@@ -146,7 +166,10 @@ router.post('/:id/api-keys', async (req, res) => {
146
166
  * Revoke (delete) a bot API key.
147
167
  */
148
168
  router.delete('/:id/api-keys/:keyId', async (req, res) => {
149
- const result = await api.revokeBotKey({ keyId: req.params.keyId });
169
+ const botId = String(req.params.id);
170
+ if (!allowed(await (0, capabilities_1.mayManageAccount)(req.auth.userId, botId), res))
171
+ return;
172
+ const result = await api.revokeBotKey({ keyId: String(req.params.keyId), botId });
150
173
  res.status(result.status).json(result.data ?? { error: result.error });
151
174
  });
152
175
  exports.default = router;