@hotmeshio/long-tail 0.5.11 → 0.6.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 (350) hide show
  1. package/README.md +1 -0
  2. package/build/api/diagnostics.d.ts +5 -0
  3. package/build/api/diagnostics.js +5 -1
  4. package/build/api/escalations/bulk.js +9 -1
  5. package/build/api/escalations/cancel.js +5 -7
  6. package/build/api/escalations/claim.js +18 -15
  7. package/build/api/escalations/create.d.ts +6 -0
  8. package/build/api/escalations/create.js +11 -8
  9. package/build/api/escalations/facets.d.ts +18 -0
  10. package/build/api/escalations/facets.js +115 -0
  11. package/build/api/escalations/helpers.d.ts +70 -1
  12. package/build/api/escalations/helpers.js +101 -7
  13. package/build/api/escalations/index.d.ts +3 -2
  14. package/build/api/escalations/index.js +7 -1
  15. package/build/api/escalations/list.d.ts +23 -2
  16. package/build/api/escalations/list.js +111 -10
  17. package/build/api/escalations/metadata.js +22 -27
  18. package/build/api/escalations/resolve.d.ts +19 -1
  19. package/build/api/escalations/resolve.js +111 -26
  20. package/build/api/escalations/single.js +8 -8
  21. package/build/api/settings.d.ts +1 -1
  22. package/build/api/settings.js +3 -1
  23. package/build/api/users.d.ts +6 -0
  24. package/build/api/users.js +29 -1
  25. package/build/api/workflows/invocation.d.ts +6 -0
  26. package/build/api/workflows/invocation.js +6 -2
  27. package/build/bin/ltc.js +40 -0
  28. package/build/lib/cli/commands/escalations.d.ts +36 -0
  29. package/build/lib/cli/commands/escalations.js +98 -0
  30. package/build/lib/db/schemas/001_schema.sql +10 -5
  31. package/build/lib/db/schemas/012_lt_tasks_workflow_id_unique.sql +20 -0
  32. package/build/lib/db/schemas/013_role_scope.sql +37 -0
  33. package/build/modules/features.d.ts +19 -0
  34. package/build/modules/features.js +16 -0
  35. package/build/modules/version.d.ts +10 -5
  36. package/build/modules/version.js +27 -11
  37. package/build/routes/diagnostics.js +15 -2
  38. package/build/routes/escalations/facets.d.ts +7 -0
  39. package/build/routes/escalations/facets.js +81 -0
  40. package/build/routes/escalations/index.js +3 -0
  41. package/build/routes/escalations/list.js +48 -0
  42. package/build/routes/escalations/resolve.js +22 -4
  43. package/build/routes/users.js +9 -5
  44. package/build/routes/workflows/invocation.js +12 -4
  45. package/build/sdk/index.d.ts +35 -2
  46. package/build/sdk/index.js +7 -0
  47. package/build/services/diagnostics/index.d.ts +40 -6
  48. package/build/services/diagnostics/index.js +54 -5
  49. package/build/services/escalation/crud.d.ts +56 -6
  50. package/build/services/escalation/crud.js +102 -31
  51. package/build/services/escalation/facet-sql.d.ts +18 -0
  52. package/build/services/escalation/facet-sql.js +118 -0
  53. package/build/services/escalation/facets.d.ts +45 -0
  54. package/build/services/escalation/facets.js +218 -0
  55. package/build/services/escalation/index.d.ts +1 -0
  56. package/build/services/escalation/index.js +8 -1
  57. package/build/services/escalation/queries.d.ts +47 -0
  58. package/build/services/escalation/queries.js +185 -2
  59. package/build/services/escalation/sql.d.ts +15 -2
  60. package/build/services/escalation/sql.js +80 -3
  61. package/build/services/interceptor/activities/escalation.d.ts +2 -0
  62. package/build/services/interceptor/activities/escalation.js +1 -1
  63. package/build/services/interceptor/lifecycle.js +4 -0
  64. package/build/services/mcp/server-tools.js +10 -4
  65. package/build/services/orchestrator/condition.js +6 -2
  66. package/build/services/role/index.js +2 -3
  67. package/build/services/role/sql.d.ts +8 -0
  68. package/build/services/role/sql.js +17 -1
  69. package/build/services/task/crud.js +22 -14
  70. package/build/services/task/process.js +3 -21
  71. package/build/services/task/resolve.d.ts +5 -3
  72. package/build/services/task/resolve.js +9 -6
  73. package/build/services/task/sql.d.ts +30 -2
  74. package/build/services/task/sql.js +72 -2
  75. package/build/services/user/crud.d.ts +1 -0
  76. package/build/services/user/crud.js +29 -11
  77. package/build/services/user/index.d.ts +2 -1
  78. package/build/services/user/index.js +12 -1
  79. package/build/services/user/rbac.d.ts +18 -0
  80. package/build/services/user/rbac.js +27 -0
  81. package/build/services/user/roles.d.ts +7 -2
  82. package/build/services/user/roles.js +21 -5
  83. package/build/services/user/scope.d.ts +22 -0
  84. package/build/services/user/scope.js +50 -0
  85. package/build/services/user/seed-admin.js +34 -17
  86. package/build/services/user/sql.d.ts +18 -7
  87. package/build/services/user/sql.js +38 -13
  88. package/build/services/user/sso-provision.js +41 -24
  89. package/build/services/user/types.d.ts +9 -5
  90. package/build/start/adapters.js +3 -0
  91. package/build/system/mcp-servers/admin/diagnostics.d.ts +5 -4
  92. package/build/system/mcp-servers/admin/diagnostics.js +12 -10
  93. package/build/system/mcp-servers/admin/escalations.d.ts +6 -0
  94. package/build/system/mcp-servers/admin/escalations.js +247 -54
  95. package/build/system/mcp-servers/admin/index.js +3 -3
  96. package/build/system/mcp-servers/admin/schemas.d.ts +417 -3
  97. package/build/system/mcp-servers/admin/schemas.js +101 -5
  98. package/build/system/mcp-servers/admin/users.js +28 -2
  99. package/build/system/mcp-servers/admin/workflows.js +23 -12
  100. package/build/system/seed/tool-manifests-admin.d.ts +1324 -562
  101. package/build/system/seed/tool-manifests-admin.js +10 -2
  102. package/build/tsconfig.tsbuildinfo +1 -1
  103. package/build/types/envelope.d.ts +7 -0
  104. package/build/types/facets.d.ts +60 -0
  105. package/build/types/facets.js +10 -0
  106. package/build/types/index.d.ts +2 -1
  107. package/build/types/startup.d.ts +9 -0
  108. package/build/types/user.d.ts +11 -0
  109. package/dashboard/dist/assets/AdminDashboard-2CZ8py9X.js +2 -0
  110. package/dashboard/dist/assets/{AdminDashboard-DZpduYdW.js.map → AdminDashboard-2CZ8py9X.js.map} +1 -1
  111. package/dashboard/dist/assets/{AgentConfigPage-SFnHMIP6.js → AgentConfigPage-D68sodgo.js} +7 -7
  112. package/dashboard/dist/assets/{AgentConfigPage-SFnHMIP6.js.map → AgentConfigPage-D68sodgo.js.map} +1 -1
  113. package/dashboard/dist/assets/AgentDetailPage-BmhuWbKi.js +4 -0
  114. package/dashboard/dist/assets/AgentDetailPage-BmhuWbKi.js.map +1 -0
  115. package/dashboard/dist/assets/AgentsPage-C4SKQVeU.js +2 -0
  116. package/dashboard/dist/assets/AgentsPage-C4SKQVeU.js.map +1 -0
  117. package/dashboard/dist/assets/AvailableEscalationsPage-9RBEYwkt.js +2 -0
  118. package/dashboard/dist/assets/AvailableEscalationsPage-9RBEYwkt.js.map +1 -0
  119. package/dashboard/dist/assets/{BotPicker-Dse2jW4b.js → BotPicker-D-FvXJOM.js} +2 -2
  120. package/dashboard/dist/assets/{BotPicker-Dse2jW4b.js.map → BotPicker-D-FvXJOM.js.map} +1 -1
  121. package/dashboard/dist/assets/CapabilitiesPage-ByDf6WJr.js +2 -0
  122. package/dashboard/dist/assets/{CapabilitiesPage-DTfKCzBQ.js.map → CapabilitiesPage-ByDf6WJr.js.map} +1 -1
  123. package/dashboard/dist/assets/{CollapsibleSection-8vf38J6K.js → CollapsibleSection-BjGNYEvh.js} +2 -2
  124. package/dashboard/dist/assets/{CollapsibleSection-8vf38J6K.js.map → CollapsibleSection-BjGNYEvh.js.map} +1 -1
  125. package/dashboard/dist/assets/CopyableId-blg-gZvT.js +2 -0
  126. package/dashboard/dist/assets/CopyableId-blg-gZvT.js.map +1 -0
  127. package/dashboard/dist/assets/{CredentialsPage-7C4M-hrH.js → CredentialsPage-DvCA-wQN.js} +2 -2
  128. package/dashboard/dist/assets/{CredentialsPage-7C4M-hrH.js.map → CredentialsPage-DvCA-wQN.js.map} +1 -1
  129. package/dashboard/dist/assets/{CronLabel-DrGWtaSY.js → CronLabel-DBMurd_c.js} +2 -2
  130. package/dashboard/dist/assets/{CronLabel-DrGWtaSY.js.map → CronLabel-DBMurd_c.js.map} +1 -1
  131. package/dashboard/dist/assets/{CustomDurationPicker-Vcmr4LiR.js → CustomDurationPicker-DHflFoEa.js} +2 -2
  132. package/dashboard/dist/assets/{CustomDurationPicker-Vcmr4LiR.js.map → CustomDurationPicker-DHflFoEa.js.map} +1 -1
  133. package/dashboard/dist/assets/{DropZone-Dwpgbueb.js → DropZone-CUtdp99Z.js} +2 -2
  134. package/dashboard/dist/assets/{DropZone-Dwpgbueb.js.map → DropZone-CUtdp99Z.js.map} +1 -1
  135. package/dashboard/dist/assets/{ElapsedCell-BNexhR5d.js → ElapsedCell-CSjcVOpo.js} +2 -2
  136. package/dashboard/dist/assets/{ElapsedCell-BNexhR5d.js.map → ElapsedCell-CSjcVOpo.js.map} +1 -1
  137. package/dashboard/dist/assets/{EscalationsOverview-BI3DEwYP.js → EscalationsOverview-BUqRNJbK.js} +2 -2
  138. package/dashboard/dist/assets/{EscalationsOverview-BI3DEwYP.js.map → EscalationsOverview-BUqRNJbK.js.map} +1 -1
  139. package/dashboard/dist/assets/{EventTable-CwvX_L9t.js → EventTable-Chz-6XPE.js} +2 -2
  140. package/dashboard/dist/assets/{EventTable-CwvX_L9t.js.map → EventTable-Chz-6XPE.js.map} +1 -1
  141. package/dashboard/dist/assets/{GraphInvokePage-C-3b8WK0.js → GraphInvokePage-BXdgciWg.js} +2 -2
  142. package/dashboard/dist/assets/{GraphInvokePage-C-3b8WK0.js.map → GraphInvokePage-BXdgciWg.js.map} +1 -1
  143. package/dashboard/dist/assets/{HomePage-BS_-jcHr.js → HomePage-CEMxnk0r.js} +2 -2
  144. package/dashboard/dist/assets/{HomePage-BS_-jcHr.js.map → HomePage-CEMxnk0r.js.map} +1 -1
  145. package/dashboard/dist/assets/{ListToolbar-BH9rwQVE.js → ListToolbar-_73JCdbB.js} +2 -2
  146. package/dashboard/dist/assets/{ListToolbar-BH9rwQVE.js.map → ListToolbar-_73JCdbB.js.map} +1 -1
  147. package/dashboard/dist/assets/{McpOverview-C9iOdE7E.js → McpOverview-DfdqxhSz.js} +2 -2
  148. package/dashboard/dist/assets/{McpOverview-C9iOdE7E.js.map → McpOverview-DfdqxhSz.js.map} +1 -1
  149. package/dashboard/dist/assets/{McpQueryDetailPage-DMN-yqvJ.js → McpQueryDetailPage-DPAljieY.js} +2 -2
  150. package/dashboard/dist/assets/{McpQueryDetailPage-DMN-yqvJ.js.map → McpQueryDetailPage-DPAljieY.js.map} +1 -1
  151. package/dashboard/dist/assets/McpQueryPage-D5cSziYS.js +2 -0
  152. package/dashboard/dist/assets/McpQueryPage-D5cSziYS.js.map +1 -0
  153. package/dashboard/dist/assets/{McpRunDetailPage-Wb47sRvo.js → McpRunDetailPage-DwNb9wZg.js} +2 -2
  154. package/dashboard/dist/assets/{McpRunDetailPage-Wb47sRvo.js.map → McpRunDetailPage-DwNb9wZg.js.map} +1 -1
  155. package/dashboard/dist/assets/McpRunsPage-O5H6yStl.js +2 -0
  156. package/dashboard/dist/assets/McpRunsPage-O5H6yStl.js.map +1 -0
  157. package/dashboard/dist/assets/{NamespacePill-DnJl4Lre.js → NamespacePill-uW-xOedj.js} +2 -2
  158. package/dashboard/dist/assets/{NamespacePill-DnJl4Lre.js.map → NamespacePill-uW-xOedj.js.map} +1 -1
  159. package/dashboard/dist/assets/OperatorDashboard-DYw9Ekv5.js +2 -0
  160. package/dashboard/dist/assets/OperatorDashboard-DYw9Ekv5.js.map +1 -0
  161. package/dashboard/dist/assets/PageHeader-DVOZjBfL.js +2 -0
  162. package/dashboard/dist/assets/PageHeader-DVOZjBfL.js.map +1 -0
  163. package/dashboard/dist/assets/{PageHeaderWithStats-BuKc9MKt.js → PageHeaderWithStats-DtTpDHOd.js} +2 -2
  164. package/dashboard/dist/assets/{PageHeaderWithStats-BuKc9MKt.js.map → PageHeaderWithStats-DtTpDHOd.js.map} +1 -1
  165. package/dashboard/dist/assets/PriorityBadge-B4ykBH7f.js +2 -0
  166. package/dashboard/dist/assets/PriorityBadge-B4ykBH7f.js.map +1 -0
  167. package/dashboard/dist/assets/{ProcessDetailPage-CvPx-h8y.js → ProcessDetailPage-B0Dokcx9.js} +2 -2
  168. package/dashboard/dist/assets/{ProcessDetailPage-CvPx-h8y.js.map → ProcessDetailPage-B0Dokcx9.js.map} +1 -1
  169. package/dashboard/dist/assets/ProcessesListPage-Cc87WIjL.js +2 -0
  170. package/dashboard/dist/assets/ProcessesListPage-Cc87WIjL.js.map +1 -0
  171. package/dashboard/dist/assets/RolePill-BaW-30TC.js +2 -0
  172. package/dashboard/dist/assets/RolePill-BaW-30TC.js.map +1 -0
  173. package/dashboard/dist/assets/{RolesPage-W5ZjOHpg.js → RolesPage-cp6PiF08.js} +2 -2
  174. package/dashboard/dist/assets/{RolesPage-W5ZjOHpg.js.map → RolesPage-cp6PiF08.js.map} +1 -1
  175. package/dashboard/dist/assets/RowActions-BA9L9djf.js +2 -0
  176. package/dashboard/dist/assets/RowActions-BA9L9djf.js.map +1 -0
  177. package/dashboard/dist/assets/{RunAsSelector-CvxGTNGT.js → RunAsSelector-2LWkjSnO.js} +2 -2
  178. package/dashboard/dist/assets/{RunAsSelector-CvxGTNGT.js.map → RunAsSelector-2LWkjSnO.js.map} +1 -1
  179. package/dashboard/dist/assets/{StickyPagination-BWhFSr2d.js → StickyPagination-BQEm--kI.js} +2 -2
  180. package/dashboard/dist/assets/{StickyPagination-BWhFSr2d.js.map → StickyPagination-BQEm--kI.js.map} +1 -1
  181. package/dashboard/dist/assets/StreamMessageDetail-BTtw3GjX.js +2 -0
  182. package/dashboard/dist/assets/{StreamMessageDetail-BF0tM0cd.js.map → StreamMessageDetail-BTtw3GjX.js.map} +1 -1
  183. package/dashboard/dist/assets/{SwimlaneTimeline-Bv-KHY9s.js → SwimlaneTimeline-DdXxP4fO.js} +2 -2
  184. package/dashboard/dist/assets/{SwimlaneTimeline-Bv-KHY9s.js.map → SwimlaneTimeline-DdXxP4fO.js.map} +1 -1
  185. package/dashboard/dist/assets/{TagInput-B00uqhjX.js → TagInput-x9XTuqMb.js} +2 -2
  186. package/dashboard/dist/assets/{TagInput-B00uqhjX.js.map → TagInput-x9XTuqMb.js.map} +1 -1
  187. package/dashboard/dist/assets/{TaskDetailPage-Bzb_fuLy.js → TaskDetailPage-B8veYG4X.js} +2 -2
  188. package/dashboard/dist/assets/{TaskDetailPage-Bzb_fuLy.js.map → TaskDetailPage-B8veYG4X.js.map} +1 -1
  189. package/dashboard/dist/assets/{TaskQueuePill-CUsofm0X.js → TaskQueuePill-DSEQZ-HT.js} +2 -2
  190. package/dashboard/dist/assets/{TaskQueuePill-CUsofm0X.js.map → TaskQueuePill-DSEQZ-HT.js.map} +1 -1
  191. package/dashboard/dist/assets/{TasksListPage-CBezWaZL.js → TasksListPage-CsN1gZj5.js} +2 -2
  192. package/dashboard/dist/assets/{TasksListPage-CBezWaZL.js.map → TasksListPage-CsN1gZj5.js.map} +1 -1
  193. package/dashboard/dist/assets/{TimeAgo-CKHfTzat.js → TimeAgo-n182EcLx.js} +2 -2
  194. package/dashboard/dist/assets/{TimeAgo-CKHfTzat.js.map → TimeAgo-n182EcLx.js.map} +1 -1
  195. package/dashboard/dist/assets/{TimestampCell-Dsje8GH-.js → TimestampCell-2dlcQAfX.js} +2 -2
  196. package/dashboard/dist/assets/{TimestampCell-Dsje8GH-.js.map → TimestampCell-2dlcQAfX.js.map} +1 -1
  197. package/dashboard/dist/assets/{ToolPill-DjvedZSn.js → ToolPill-B_e4eT77.js} +2 -2
  198. package/dashboard/dist/assets/{ToolPill-DjvedZSn.js.map → ToolPill-B_e4eT77.js.map} +1 -1
  199. package/dashboard/dist/assets/{ToolTestPanel-3OcG18e5.js → ToolTestPanel-Bhnncc6M.js} +2 -2
  200. package/dashboard/dist/assets/{ToolTestPanel-3OcG18e5.js.map → ToolTestPanel-Bhnncc6M.js.map} +1 -1
  201. package/dashboard/dist/assets/{TopicDetailPage-DCtv91hH.js → TopicDetailPage-29lsNsqI.js} +3 -3
  202. package/dashboard/dist/assets/{TopicDetailPage-DCtv91hH.js.map → TopicDetailPage-29lsNsqI.js.map} +1 -1
  203. package/dashboard/dist/assets/{TopicsPage-DVGSNc_E.js → TopicsPage-KJ7_LAvo.js} +2 -2
  204. package/dashboard/dist/assets/{TopicsPage-DVGSNc_E.js.map → TopicsPage-KJ7_LAvo.js.map} +1 -1
  205. package/dashboard/dist/assets/{UserName-xHAgkk8M.js → UserName-CMoFi9zb.js} +2 -2
  206. package/dashboard/dist/assets/{UserName-xHAgkk8M.js.map → UserName-CMoFi9zb.js.map} +1 -1
  207. package/dashboard/dist/assets/{WorkflowExecutionPage-CWNxsS8a.js → WorkflowExecutionPage-Cymfx-Bp.js} +2 -2
  208. package/dashboard/dist/assets/{WorkflowExecutionPage-CWNxsS8a.js.map → WorkflowExecutionPage-Cymfx-Bp.js.map} +1 -1
  209. package/dashboard/dist/assets/{WorkflowPill-F1oKUzmc.js → WorkflowPill-B66_AnaY.js} +2 -2
  210. package/dashboard/dist/assets/{WorkflowPill-F1oKUzmc.js.map → WorkflowPill-B66_AnaY.js.map} +1 -1
  211. package/dashboard/dist/assets/WorkflowsDashboard-CqLN8spd.js +2 -0
  212. package/dashboard/dist/assets/WorkflowsDashboard-CqLN8spd.js.map +1 -0
  213. package/dashboard/dist/assets/{WorkflowsOverview-e7jWSj_n.js → WorkflowsOverview-0Rc2WT6q.js} +2 -2
  214. package/dashboard/dist/assets/{WorkflowsOverview-e7jWSj_n.js.map → WorkflowsOverview-0Rc2WT6q.js.map} +1 -1
  215. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CdAeam76.js → YamlWorkflowDetailPage-CARQ7_LN.js} +2 -2
  216. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CdAeam76.js.map → YamlWorkflowDetailPage-CARQ7_LN.js.map} +1 -1
  217. package/dashboard/dist/assets/{YamlWorkflowsPage-S_gKs2Di.js → YamlWorkflowsPage-B-7sz1nf.js} +2 -2
  218. package/dashboard/dist/assets/{YamlWorkflowsPage-S_gKs2Di.js.map → YamlWorkflowsPage-B-7sz1nf.js.map} +1 -1
  219. package/dashboard/dist/assets/{agents-JE4aL07D.js → agents-zM43d5Yf.js} +2 -2
  220. package/dashboard/dist/assets/{agents-JE4aL07D.js.map → agents-zM43d5Yf.js.map} +1 -1
  221. package/dashboard/dist/assets/api-path-u2Jf9QXS.js +2 -0
  222. package/dashboard/dist/assets/api-path-u2Jf9QXS.js.map +1 -0
  223. package/dashboard/dist/assets/{bots-cAzKkDtQ.js → bots-D5BasOGz.js} +2 -2
  224. package/dashboard/dist/assets/{bots-cAzKkDtQ.js.map → bots-D5BasOGz.js.map} +1 -1
  225. package/dashboard/dist/assets/{capabilities-RBFXLAXF.js → capabilities-BT3PW9CZ.js} +2 -2
  226. package/dashboard/dist/assets/{capabilities-RBFXLAXF.js.map → capabilities-BT3PW9CZ.js.map} +1 -1
  227. package/dashboard/dist/assets/{controlplane-DGhv3rwI.js → controlplane-NpJr49rN.js} +2 -2
  228. package/dashboard/dist/assets/{controlplane-DGhv3rwI.js.map → controlplane-NpJr49rN.js.map} +1 -1
  229. package/dashboard/dist/assets/{escalation-ne7dIaPa.js → escalation-DrzQolPG.js} +2 -2
  230. package/dashboard/dist/assets/{escalation-ne7dIaPa.js.map → escalation-DrzQolPG.js.map} +1 -1
  231. package/dashboard/dist/assets/escalation-columns-QzwmtD60.js +2 -0
  232. package/dashboard/dist/assets/escalation-columns-QzwmtD60.js.map +1 -0
  233. package/dashboard/dist/assets/index-B5w4Gjyk.js +6 -0
  234. package/dashboard/dist/assets/index-B5w4Gjyk.js.map +1 -0
  235. package/dashboard/dist/assets/{index-CByjpYlU.js → index-BCT4kqGR.js} +2 -2
  236. package/dashboard/dist/assets/{index-CByjpYlU.js.map → index-BCT4kqGR.js.map} +1 -1
  237. package/dashboard/dist/assets/{index-CgyucK0e.js → index-C69XvBfg.js} +2 -2
  238. package/dashboard/dist/assets/{index-CgyucK0e.js.map → index-C69XvBfg.js.map} +1 -1
  239. package/dashboard/dist/assets/index-CHw4Fl0t.css +1 -0
  240. package/dashboard/dist/assets/index-C_NwHTMh.js +2 -0
  241. package/dashboard/dist/assets/index-C_NwHTMh.js.map +1 -0
  242. package/dashboard/dist/assets/{index-DgzgRTNg.js → index-Cq0trGqf.js} +2 -2
  243. package/dashboard/dist/assets/{index-DgzgRTNg.js.map → index-Cq0trGqf.js.map} +1 -1
  244. package/dashboard/dist/assets/{index-DPJW96d2.js → index-DE0r9SEX.js} +26 -26
  245. package/dashboard/dist/assets/index-DE0r9SEX.js.map +1 -0
  246. package/dashboard/dist/assets/{index-BTqhAT6p.js → index-DH_CiD0W.js} +2 -2
  247. package/dashboard/dist/assets/{index-BTqhAT6p.js.map → index-DH_CiD0W.js.map} +1 -1
  248. package/dashboard/dist/assets/{index-C2l4GcZ7.js → index-K23FdS-T.js} +3 -3
  249. package/dashboard/dist/assets/{index-C2l4GcZ7.js.map → index-K23FdS-T.js.map} +1 -1
  250. package/dashboard/dist/assets/index-f6K1UNrn.js +2 -0
  251. package/dashboard/dist/assets/index-f6K1UNrn.js.map +1 -0
  252. package/dashboard/dist/assets/{index-BbJuC9kg.js → index-qr1fndqM.js} +2 -2
  253. package/dashboard/dist/assets/{index-BbJuC9kg.js.map → index-qr1fndqM.js.map} +1 -1
  254. package/dashboard/dist/assets/index-vKTvJ_li.js +2 -0
  255. package/dashboard/dist/assets/index-vKTvJ_li.js.map +1 -0
  256. package/dashboard/dist/assets/{index-CQDn-bLr.js → index-y-3ODtEE.js} +2 -2
  257. package/dashboard/dist/assets/{index-CQDn-bLr.js.map → index-y-3ODtEE.js.map} +1 -1
  258. package/dashboard/dist/assets/{index-QxAYCJ1S.js → index-y56Ds-LB.js} +2 -2
  259. package/dashboard/dist/assets/{index-QxAYCJ1S.js.map → index-y56Ds-LB.js.map} +1 -1
  260. package/dashboard/dist/assets/{knowledge-DzRpsm3D.js → knowledge-DSSATOTX.js} +2 -2
  261. package/dashboard/dist/assets/{knowledge-DzRpsm3D.js.map → knowledge-DSSATOTX.js.map} +1 -1
  262. package/dashboard/dist/assets/{mcp-B1lc6nL4.js → mcp-CfJFVo5k.js} +2 -2
  263. package/dashboard/dist/assets/{mcp-B1lc6nL4.js.map → mcp-CfJFVo5k.js.map} +1 -1
  264. package/dashboard/dist/assets/{mcp-query-CXuweaN3.js → mcp-query-DKVx2Q-X.js} +2 -2
  265. package/dashboard/dist/assets/{mcp-query-CXuweaN3.js.map → mcp-query-DKVx2Q-X.js.map} +1 -1
  266. package/dashboard/dist/assets/{pipelines-D4VLWDvu.js → pipelines-BSWzE-6M.js} +2 -2
  267. package/dashboard/dist/assets/{pipelines-D4VLWDvu.js.map → pipelines-BSWzE-6M.js.map} +1 -1
  268. package/dashboard/dist/assets/{roles-CSpHRRu8.js → roles-t9HzhI5N.js} +2 -2
  269. package/dashboard/dist/assets/{roles-CSpHRRu8.js.map → roles-t9HzhI5N.js.map} +1 -1
  270. package/dashboard/dist/assets/{tasks-CWUsKhM4.js → tasks-B7rUihoH.js} +2 -2
  271. package/dashboard/dist/assets/{tasks-CWUsKhM4.js.map → tasks-B7rUihoH.js.map} +1 -1
  272. package/dashboard/dist/assets/{topics-BXwstrzB.js → topics-PC2fEiyD.js} +2 -2
  273. package/dashboard/dist/assets/{topics-BXwstrzB.js.map → topics-PC2fEiyD.js.map} +1 -1
  274. package/dashboard/dist/assets/useDebouncedValue-BA5S7V54.js +2 -0
  275. package/dashboard/dist/assets/useDebouncedValue-BA5S7V54.js.map +1 -0
  276. package/dashboard/dist/assets/{useEventHooks-CjygrbYy.js → useEventHooks-DK9mw1cI.js} +2 -2
  277. package/dashboard/dist/assets/{useEventHooks-CjygrbYy.js.map → useEventHooks-DK9mw1cI.js.map} +1 -1
  278. package/dashboard/dist/assets/{useNamespace-CsepDyR5.js → useNamespace-3IjtUtAw.js} +2 -2
  279. package/dashboard/dist/assets/{useNamespace-CsepDyR5.js.map → useNamespace-3IjtUtAw.js.map} +1 -1
  280. package/dashboard/dist/assets/{useYamlActivityEvents-gWIG6akB.js → useYamlActivityEvents-uxukp3gO.js} +2 -2
  281. package/dashboard/dist/assets/{useYamlActivityEvents-gWIG6akB.js.map → useYamlActivityEvents-uxukp3gO.js.map} +1 -1
  282. package/dashboard/dist/assets/users-CC4B5Fm5.js +2 -0
  283. package/dashboard/dist/assets/users-CC4B5Fm5.js.map +1 -0
  284. package/dashboard/dist/assets/{vendor-icons-Dj2F0Jrb.js → vendor-icons-Dy5Jpknf.js} +114 -109
  285. package/dashboard/dist/assets/vendor-icons-Dy5Jpknf.js.map +1 -0
  286. package/dashboard/dist/assets/{workflows-C7Cam2Ok.js → workflows-S7MF1nNk.js} +2 -2
  287. package/dashboard/dist/assets/{workflows-C7Cam2Ok.js.map → workflows-S7MF1nNk.js.map} +1 -1
  288. package/dashboard/dist/assets/{yaml-workflows-ChUOE22W.js → yaml-workflows-WfdaMHNn.js} +2 -2
  289. package/dashboard/dist/assets/{yaml-workflows-ChUOE22W.js.map → yaml-workflows-WfdaMHNn.js.map} +1 -1
  290. package/dashboard/dist/index.html +3 -3
  291. package/docs/api/http/escalations.md +131 -10
  292. package/docs/api/http/roles.md +44 -9
  293. package/docs/api/http/users.md +15 -6
  294. package/docs/api/mcp/admin.md +164 -14
  295. package/docs/api/mcp/human-queue.md +34 -2
  296. package/docs/api/sdk/escalations.md +155 -2
  297. package/docs/api/sdk/roles.md +11 -0
  298. package/docs/api/sdk/users.md +26 -1
  299. package/docs/auth.md +1 -1
  300. package/docs/dashboard.md +5 -4
  301. package/docs/data.md +9 -2
  302. package/docs/faceted-routing.md +221 -0
  303. package/docs/hitl-guide.md +50 -0
  304. package/docs/iam.md +31 -0
  305. package/docs/mcp.md +8 -0
  306. package/package.json +2 -2
  307. package/dashboard/dist/assets/AdminDashboard-DZpduYdW.js +0 -2
  308. package/dashboard/dist/assets/AgentDetailPage-C-2iSaDs.js +0 -4
  309. package/dashboard/dist/assets/AgentDetailPage-C-2iSaDs.js.map +0 -1
  310. package/dashboard/dist/assets/AgentsPage-C3FztFd_.js +0 -2
  311. package/dashboard/dist/assets/AgentsPage-C3FztFd_.js.map +0 -1
  312. package/dashboard/dist/assets/AvailableEscalationsPage-DIqdBCwe.js +0 -2
  313. package/dashboard/dist/assets/AvailableEscalationsPage-DIqdBCwe.js.map +0 -1
  314. package/dashboard/dist/assets/CapabilitiesPage-DTfKCzBQ.js +0 -2
  315. package/dashboard/dist/assets/CopyableId-DaT0ZRHg.js +0 -2
  316. package/dashboard/dist/assets/CopyableId-DaT0ZRHg.js.map +0 -1
  317. package/dashboard/dist/assets/McpQueryPage-Db1LUKVs.js +0 -2
  318. package/dashboard/dist/assets/McpQueryPage-Db1LUKVs.js.map +0 -1
  319. package/dashboard/dist/assets/McpRunsPage--tgT5uo7.js +0 -2
  320. package/dashboard/dist/assets/McpRunsPage--tgT5uo7.js.map +0 -1
  321. package/dashboard/dist/assets/OperatorDashboard-BWVUbJkZ.js +0 -2
  322. package/dashboard/dist/assets/OperatorDashboard-BWVUbJkZ.js.map +0 -1
  323. package/dashboard/dist/assets/PageHeader-Bnt2iQQa.js +0 -2
  324. package/dashboard/dist/assets/PageHeader-Bnt2iQQa.js.map +0 -1
  325. package/dashboard/dist/assets/PriorityBadge-DfQY9St9.js +0 -2
  326. package/dashboard/dist/assets/PriorityBadge-DfQY9St9.js.map +0 -1
  327. package/dashboard/dist/assets/ProcessesListPage-CWiRM_h3.js +0 -2
  328. package/dashboard/dist/assets/ProcessesListPage-CWiRM_h3.js.map +0 -1
  329. package/dashboard/dist/assets/RolePill-DQTT1s9v.js +0 -2
  330. package/dashboard/dist/assets/RolePill-DQTT1s9v.js.map +0 -1
  331. package/dashboard/dist/assets/RowActions-Dg-Fsm5O.js +0 -2
  332. package/dashboard/dist/assets/RowActions-Dg-Fsm5O.js.map +0 -1
  333. package/dashboard/dist/assets/StreamMessageDetail-BF0tM0cd.js +0 -2
  334. package/dashboard/dist/assets/WorkflowsDashboard-M13lIaw7.js +0 -2
  335. package/dashboard/dist/assets/WorkflowsDashboard-M13lIaw7.js.map +0 -1
  336. package/dashboard/dist/assets/escalation-columns-DqTkKbCv.js +0 -2
  337. package/dashboard/dist/assets/escalation-columns-DqTkKbCv.js.map +0 -1
  338. package/dashboard/dist/assets/index-CEpw_Fh8.js +0 -2
  339. package/dashboard/dist/assets/index-CEpw_Fh8.js.map +0 -1
  340. package/dashboard/dist/assets/index-ClvYSNZd.css +0 -1
  341. package/dashboard/dist/assets/index-CucXk58o.js +0 -6
  342. package/dashboard/dist/assets/index-CucXk58o.js.map +0 -1
  343. package/dashboard/dist/assets/index-DPJW96d2.js.map +0 -1
  344. package/dashboard/dist/assets/index-DeZhNCf5.js +0 -2
  345. package/dashboard/dist/assets/index-DeZhNCf5.js.map +0 -1
  346. package/dashboard/dist/assets/index-Do8Xp3pa.js +0 -2
  347. package/dashboard/dist/assets/index-Do8Xp3pa.js.map +0 -1
  348. package/dashboard/dist/assets/users-DvhHbR0R.js +0 -2
  349. package/dashboard/dist/assets/users-DvhHbR0R.js.map +0 -1
  350. package/dashboard/dist/assets/vendor-icons-Dj2F0Jrb.js.map +0 -1
@@ -11,7 +11,8 @@
11
11
  // `hmsh_escalations` here rather than composed from generic SDK calls.
12
12
  // ---------------------------------------------------------------------------
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.RESOLVE_BY_METADATA_ATOMIC = exports.RELEASE_EXPIRED_CLAIMS = void 0;
14
+ exports.RESOLVE_BY_METADATA_ATOMIC = exports.COUNT_SEARCH_ESCALATIONS = exports.RELEASE_EXPIRED_CLAIMS = void 0;
15
+ exports.searchEscalationsQuery = searchEscalationsQuery;
15
16
  /**
16
17
  * Sweep expired claims back to the available pool.
17
18
  *
@@ -31,6 +32,72 @@ SET assigned_to = NULL,
31
32
  WHERE status = 'pending'
32
33
  AND assigned_to IS NOT NULL
33
34
  AND assigned_until <= NOW()`;
35
+ /**
36
+ * Free-text escalation search.
37
+ *
38
+ * The SDK's `client.list()` filters by structured columns only — it has no
39
+ * free-text predicate. Long-tail's contract needs a search box that matches a
40
+ * correlation key (order id, ticket id) or any visible field across the WHOLE
41
+ * result set, not just the current page. That is server-side SQL here (over the
42
+ * `lt_escalations` view, which adds the computed `available` flag), following the
43
+ * same raw-SQL-on-the-shared-table pattern as the atomic resolve below — so the
44
+ * filter flows SQL→service→API→route→dashboard rather than being faked client-side.
45
+ *
46
+ * All structured filters are optional and combine with the search term (AND).
47
+ * `metadata::text ILIKE` scans the JSONB as text (the GIN index is containment-only
48
+ * and cannot serve ILIKE) — bounded in practice by the other filters and the page.
49
+ *
50
+ * Role-scope visibility ($3 allRoles, $10 selfRoles, $11 meUserId):
51
+ * - global access → $3 NULL and $10 NULL → no role filter (sees everything)
52
+ * - read_all roles → row.role ∈ $3
53
+ * - read_self roles → row.role ∈ $10 AND row.assigned_to = $11 (only the user's own)
54
+ * The branches union, so a user with mixed scope (read_all on some roles, read_self
55
+ * on others) is filtered correctly in one pass. `assigned_to` is indexed
56
+ * (idx_lt_escalations_assigned), so the self-branch is index-served at scale.
57
+ *
58
+ * $1 status, $2 role, $3 allRoles (text[]), $4 type, $5 subtype, $6 priority,
59
+ * $7 assigned_to, $8 available (bool), $9 search, $10 selfRoles (text[]),
60
+ * $11 meUserId, $12 metadata (jsonb containment, GIN-served). The list query
61
+ * adds $13 limit, $14 offset.
62
+ *
63
+ * `metadata @> $12` is exact JSONB containment (the GIN index serves it) — this is
64
+ * how findByMetadata routes through the scoped query so its role-scope filter and
65
+ * count run in SQL (no client-side filtering), the same as free-text/self-scope.
66
+ */
67
+ const SEARCH_ESCALATIONS_WHERE = `\
68
+ FROM public.lt_escalations
69
+ WHERE ($1::text IS NULL OR status = $1)
70
+ AND ($2::text IS NULL OR role = $2)
71
+ AND (
72
+ ($3::text[] IS NULL AND $10::text[] IS NULL)
73
+ OR ($3::text[] IS NOT NULL AND role = ANY($3))
74
+ OR ($10::text[] IS NOT NULL AND role = ANY($10) AND assigned_to = $11)
75
+ )
76
+ AND ($4::text IS NULL OR type = $4)
77
+ AND ($5::text IS NULL OR subtype = $5)
78
+ AND ($6::int IS NULL OR priority = $6)
79
+ AND ($7::text IS NULL OR assigned_to = $7)
80
+ AND ($8::boolean IS NULL OR available = $8)
81
+ AND ($12::jsonb IS NULL OR metadata @> $12)
82
+ AND ($9::text IS NULL OR (
83
+ description ILIKE '%' || $9 || '%'
84
+ OR type ILIKE '%' || $9 || '%'
85
+ OR subtype ILIKE '%' || $9 || '%'
86
+ OR role ILIKE '%' || $9 || '%'
87
+ OR workflow_id ILIKE '%' || $9 || '%'
88
+ OR origin_id ILIKE '%' || $9 || '%'
89
+ OR id::text ILIKE '%' || $9 || '%'
90
+ OR metadata::text ILIKE '%' || $9 || '%'
91
+ ))`;
92
+ /** Count matching the search WHERE (params $1–$12). */
93
+ exports.COUNT_SEARCH_ESCALATIONS = `SELECT COUNT(*)::int AS total\n${SEARCH_ESCALATIONS_WHERE}`;
94
+ /**
95
+ * Build the search SELECT. `orderBy` is composed from a whitelist by the caller
96
+ * (never raw user input), so it is safe to interpolate; everything else is bound.
97
+ */
98
+ function searchEscalationsQuery(orderBy) {
99
+ return `SELECT *\n${SEARCH_ESCALATIONS_WHERE}\n ORDER BY ${orderBy}\n LIMIT $13 OFFSET $14`;
100
+ }
34
101
  /**
35
102
  * Atomic resolve by metadata with signal guard.
36
103
  *
@@ -51,7 +118,13 @@ WHERE status = 'pending'
51
118
  * The `resolved` CTE still skips signal_id rows — the workflow resolves durably.
52
119
  *
53
120
  * $1 = metadata filter (jsonb), $2 = userId, $3 = resolver_payload (jsonb),
54
- * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
121
+ * $4 = metadata patch (jsonb, nullable), $5 = write_all roles (text[], null = global /
122
+ * no filter), $6 = write_self roles (text[], nullable).
123
+ *
124
+ * Write-scope is folded into the same FOR UPDATE statement (no TOCTOU): the row
125
+ * is resolvable if the caller has global access ($5 NULL), or the row's role is in
126
+ * their write_all set, or the row's role is in their write_self set AND it is
127
+ * already assigned to them ($2). assigned_to is indexed, so the self-branch scales.
55
128
  */
56
129
  exports.RESOLVE_BY_METADATA_ATOMIC = `\
57
130
  WITH target AS MATERIALIZED (
@@ -59,7 +132,11 @@ WITH target AS MATERIALIZED (
59
132
  FROM public.hmsh_escalations
60
133
  WHERE metadata @> $1::jsonb
61
134
  AND status = 'pending'
62
- AND ($5::text[] IS NULL OR role = ANY($5))
135
+ AND (
136
+ $5::text[] IS NULL
137
+ OR role = ANY($5)
138
+ OR (role = ANY($6::text[]) AND assigned_to = $2)
139
+ )
63
140
  ORDER BY priority ASC, created_at ASC
64
141
  LIMIT 1
65
142
  FOR UPDATE
@@ -8,6 +8,8 @@
8
8
  export declare function ltResolveEscalation(input: {
9
9
  escalationId: string;
10
10
  resolverPayload: Record<string, any>;
11
+ /** Outcome patch merged into the row inside the same atomic resolve (see resolveEscalation). */
12
+ metadata?: Record<string, any>;
11
13
  }): Promise<void>;
12
14
  /**
13
15
  * Claim an escalation to a specific user. Used for auto-assignment
@@ -47,7 +47,7 @@ const logger_1 = require("../../../lib/logger");
47
47
  * retries this activity.
48
48
  */
49
49
  async function ltResolveEscalation(input) {
50
- const result = await escalationService.resolveEscalation(input.escalationId, input.resolverPayload);
50
+ const result = await escalationService.resolveEscalation(input.escalationId, input.resolverPayload, input.metadata);
51
51
  if (!result) {
52
52
  logger_1.loggerRegistry.warn(`[ltResolveEscalation] Escalation ${input.escalationId} already resolved or not found`);
53
53
  }
@@ -53,9 +53,13 @@ async function resolveReRun(activities, envelope, existingTask, wf, taskQueue) {
53
53
  const escalationId = envelope?.lt?.escalationId;
54
54
  const isRealEscalation = isReRun && escalationId && !escalationId.startsWith('auto-triage-');
55
55
  if (isRealEscalation) {
56
+ // Thread the outcome patch carried on the re-run envelope so it merges into the
57
+ // prior escalation's metadata inside this SAME atomic resolve — never a separate
58
+ // write. (resolve orchestrator Path E sets envelope.lt.escalationMetadata.)
56
59
  await activities.ltResolveEscalation({
57
60
  escalationId: escalationId,
58
61
  resolverPayload: envelope.resolver,
62
+ metadata: envelope.lt?.escalationMetadata,
59
63
  });
60
64
  // escalation.resolved event published by service layer (services/escalation/crud.ts)
61
65
  }
@@ -54,14 +54,20 @@ const getAvailableWorkSchema = zod_1.z.object({
54
54
  role: zod_1.z.string().describe('Role to filter by'),
55
55
  limit: zod_1.z.number().optional().default(10).describe('Max results to return'),
56
56
  });
57
+ /** Outcome facets merged onto the row on resolve — see the field describe(). */
58
+ const outcomeMetadata = zod_1.z.record(zod_1.z.any()).optional().describe('Outcome facets to merge into the escalation\'s metadata on resolve — the durable, ' +
59
+ 'queryable record of what happened (disposition, reviewer, timing). Distinct from ' +
60
+ 'payload, which resumes the waiting workflow and is not indexed.');
57
61
  const claimAndResolveSchema = zod_1.z.object({
58
62
  escalation_id: zod_1.z.string().describe('The escalation ID to claim and resolve'),
59
63
  resolver_id: zod_1.z.string().describe('Identifier for who/what is resolving'),
60
64
  payload: zod_1.z.record(zod_1.z.any()).describe('Resolution payload data'),
65
+ metadata: outcomeMetadata,
61
66
  });
62
67
  const resolveEscalationSchema = zod_1.z.object({
63
68
  escalation_id: zod_1.z.string().describe('The escalation ID to resolve'),
64
69
  payload: zod_1.z.record(zod_1.z.any()).describe('Resolution payload data'),
70
+ metadata: outcomeMetadata,
65
71
  });
66
72
  const escalateAndWaitSchema = zod_1.z.object({
67
73
  role: zod_1.z.string().describe('Target role for the escalation (e.g., "reviewer")'),
@@ -176,7 +182,7 @@ function registerHumanQueueTools(server) {
176
182
  // ── claim_and_resolve ───────────────────────────────────────────────
177
183
  server.registerTool('claim_and_resolve', {
178
184
  title: 'Claim and Resolve',
179
- description: 'Claim an escalation and immediately resolve it with a payload. Atomic operation.',
185
+ description: 'Claim an escalation and immediately resolve it with a payload. Atomic operation. Optionally pass `metadata` to record the outcome (disposition, timing) onto the row for the audit trail.',
180
186
  inputSchema: claimAndResolveSchema,
181
187
  }, async (args) => {
182
188
  const claimed = await escalationService.claimEscalation(args.escalation_id, args.resolver_id, 5);
@@ -189,7 +195,7 @@ function registerHumanQueueTools(server) {
189
195
  isError: true,
190
196
  };
191
197
  }
192
- const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
198
+ const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload, args.metadata);
193
199
  if (!resolved) {
194
200
  return {
195
201
  content: [{
@@ -213,10 +219,10 @@ function registerHumanQueueTools(server) {
213
219
  // ── resolve_escalation ──────────────────────────────────────────────
214
220
  server.registerTool('resolve_escalation', {
215
221
  title: 'Resolve Escalation',
216
- description: 'Resolve an already-claimed escalation with a payload. Use when the claim happened externally (e.g. via API).',
222
+ description: 'Resolve an already-claimed escalation with a payload. Use when the claim happened externally (e.g. via API). Optionally pass `metadata` to record the outcome (disposition, timing) onto the row for the audit trail.',
217
223
  inputSchema: resolveEscalationSchema,
218
224
  }, async (args) => {
219
- const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
225
+ const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload, args.metadata);
220
226
  if (!resolved) {
221
227
  return {
222
228
  content: [{
@@ -87,11 +87,15 @@ async function conditionLT(signalId, escalation) {
87
87
  taskQueue: LT_ACTIVITY_QUEUE,
88
88
  retry: { maximumAttempts: 3 },
89
89
  });
90
- // Strip $escalation_id before passing as resolver payload
91
- const { $escalation_id: _, ...resolverPayload } = raw;
90
+ // Strip the injected control keys ($escalation_id, $escalation_metadata) before the
91
+ // payload is returned to the caller. The outcome patch ($escalation_metadata, set by
92
+ // the resolve orchestrator's signal paths) rides INTO the single atomic resolve below
93
+ // so it merges in the same guarded UPDATE — never a separate write.
94
+ const { $escalation_id: _id, $escalation_metadata: metadata, ...resolverPayload } = raw;
92
95
  await ltResolveEscalation({
93
96
  escalationId,
94
97
  resolverPayload: resolverPayload,
98
+ metadata: metadata,
95
99
  });
96
100
  return resolverPayload;
97
101
  }
@@ -34,9 +34,8 @@ async function getAllEscalationChains() {
34
34
  */
35
35
  async function addEscalationChain(sourceRole, targetRole) {
36
36
  const pool = (0, db_1.getPool)();
37
- await pool.query(sql_1.ENSURE_ROLE_EXISTS, [sourceRole]);
38
- await pool.query(sql_1.ENSURE_ROLE_EXISTS, [targetRole]);
39
- await pool.query(sql_1.INSERT_ESCALATION_CHAIN, [sourceRole, targetRole]);
37
+ // One atomic statement: ensure both role FK targets + insert the chain link.
38
+ await pool.query(sql_1.ADD_ESCALATION_CHAIN, [sourceRole, targetRole]);
40
39
  }
41
40
  /**
42
41
  * Remove a single escalation chain entry.
@@ -1,6 +1,14 @@
1
1
  export declare const GET_ESCALATION_TARGETS = "\n SELECT target_role\n FROM lt_config_role_escalations\n WHERE source_role = $1\n ORDER BY target_role";
2
2
  export declare const GET_ALL_ESCALATION_CHAINS = "\n SELECT source_role, target_role\n FROM lt_config_role_escalations\n ORDER BY source_role, target_role";
3
3
  export declare const INSERT_ESCALATION_CHAIN = "\n INSERT INTO lt_config_role_escalations (source_role, target_role)\n VALUES ($1, $2)\n ON CONFLICT DO NOTHING";
4
+ /**
5
+ * Add an escalation chain in ONE atomic statement: ensure both role FK targets
6
+ * exist, then insert the source→target link. Postgres checks the chain's FK to
7
+ * lt_roles at statement end (after the sibling ensure CTEs run), so brand-new
8
+ * roles are valid targets. Replaces the former ensure+ensure+insert three-call
9
+ * saga, which had no transaction guarding the writes together.
10
+ */
11
+ export declare const ADD_ESCALATION_CHAIN = "\n WITH ensured_source AS (\n INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING\n ), ensured_target AS (\n INSERT INTO lt_roles (role) VALUES ($2) ON CONFLICT DO NOTHING\n )\n INSERT INTO lt_config_role_escalations (source_role, target_role)\n VALUES ($1, $2)\n ON CONFLICT DO NOTHING";
4
12
  export declare const DELETE_ESCALATION_CHAIN = "\n DELETE FROM lt_config_role_escalations\n WHERE source_role = $1 AND target_role = $2";
5
13
  export declare const DELETE_ESCALATION_CHAINS_BY_SOURCE = "\n DELETE FROM lt_config_role_escalations\n WHERE source_role = $1";
6
14
  export declare const CHECK_ESCALATION_CHAIN_EXISTS = "\n SELECT 1\n FROM lt_config_role_escalations\n WHERE source_role = $1 AND target_role = $2";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // ─── Escalation chain queries ───────────────────────────────────────────────
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.DELETE_ROLE = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
4
+ exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.DELETE_ROLE = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
5
5
  exports.GET_ESCALATION_TARGETS = `
6
6
  SELECT target_role
7
7
  FROM lt_config_role_escalations
@@ -15,6 +15,22 @@ exports.INSERT_ESCALATION_CHAIN = `
15
15
  INSERT INTO lt_config_role_escalations (source_role, target_role)
16
16
  VALUES ($1, $2)
17
17
  ON CONFLICT DO NOTHING`;
18
+ /**
19
+ * Add an escalation chain in ONE atomic statement: ensure both role FK targets
20
+ * exist, then insert the source→target link. Postgres checks the chain's FK to
21
+ * lt_roles at statement end (after the sibling ensure CTEs run), so brand-new
22
+ * roles are valid targets. Replaces the former ensure+ensure+insert three-call
23
+ * saga, which had no transaction guarding the writes together.
24
+ */
25
+ exports.ADD_ESCALATION_CHAIN = `
26
+ WITH ensured_source AS (
27
+ INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING
28
+ ), ensured_target AS (
29
+ INSERT INTO lt_roles (role) VALUES ($2) ON CONFLICT DO NOTHING
30
+ )
31
+ INSERT INTO lt_config_role_escalations (source_role, target_role)
32
+ VALUES ($1, $2)
33
+ ON CONFLICT DO NOTHING`;
18
34
  exports.DELETE_ESCALATION_CHAIN = `
19
35
  DELETE FROM lt_config_role_escalations
20
36
  WHERE source_role = $1 AND target_role = $2`;
@@ -31,17 +31,25 @@ async function createTask(input) {
31
31
  input.executing_as || null,
32
32
  input.status || null,
33
33
  ]);
34
- const task = rows[0];
35
- (0, publish_1.publishTaskEvent)({
36
- type: 'task.created',
37
- source: 'service',
38
- workflowId: task.workflow_id || '',
39
- workflowName: task.workflow_type || '',
40
- taskQueue: task.task_queue || '',
41
- taskId: task.id,
42
- originId: task.origin_id || undefined,
43
- status: task.status || 'pending',
44
- });
34
+ // ON CONFLICT (workflow_id) makes this idempotent: a retried proxyActivity or
35
+ // re-driven saga re-targets the same row. `_inserted` (xmax = 0) is true only
36
+ // when this call actually inserted, so the created event fires exactly once.
37
+ const row = rows[0];
38
+ const inserted = row._inserted === true;
39
+ delete row._inserted;
40
+ const task = row;
41
+ if (inserted) {
42
+ (0, publish_1.publishTaskEvent)({
43
+ type: 'task.created',
44
+ source: 'service',
45
+ workflowId: task.workflow_id || '',
46
+ workflowName: task.workflow_type || '',
47
+ taskQueue: task.task_queue || '',
48
+ taskId: task.id,
49
+ originId: task.origin_id || undefined,
50
+ status: task.status || 'pending',
51
+ });
52
+ }
45
53
  return task;
46
54
  }
47
55
  async function updateTask(id, input) {
@@ -70,7 +78,7 @@ async function updateTask(id, input) {
70
78
  values.push(JSON.stringify(input.milestones));
71
79
  }
72
80
  values.push(id);
73
- const { rows } = await pool.query(`UPDATE lt_tasks SET ${sets.join(', ')} WHERE id = $${idx} RETURNING *`, values);
81
+ const { rows } = await pool.query((0, sql_1.updateTaskById)(sets.join(', '), idx), values);
74
82
  const task = rows[0];
75
83
  // Publish status-driven events from the single write path
76
84
  if (input.status && task) {
@@ -148,8 +156,8 @@ async function listTasks(filters) {
148
156
  const limit = filters.limit || 50;
149
157
  const offset = filters.offset || 0;
150
158
  const [countResult, dataResult] = await Promise.all([
151
- pool.query(`SELECT COUNT(*) FROM lt_tasks ${where}`, values),
152
- pool.query(`SELECT * FROM lt_tasks ${where} ORDER BY created_at DESC LIMIT $${idx++} OFFSET $${idx++}`, [...values, limit, offset]),
159
+ pool.query((0, sql_1.listTasksCount)(where), values),
160
+ pool.query((0, sql_1.listTasksData)(where, idx++, idx++), [...values, limit, offset]),
153
161
  ]);
154
162
  return {
155
163
  tasks: dataResult.rows,
@@ -44,27 +44,9 @@ async function listProcesses(filters) {
44
44
  having = `HAVING COUNT(*) > COUNT(*) FILTER (WHERE status = 'completed')
45
45
  AND COUNT(*) FILTER (WHERE status = 'needs_intervention') = 0`;
46
46
  }
47
- // Count query wrap in subquery because of HAVING
48
- const countSql = having
49
- ? `SELECT COUNT(*) FROM (
50
- SELECT origin_id FROM lt_tasks ${where}
51
- GROUP BY origin_id ${having}
52
- ) sub`
53
- : `SELECT COUNT(DISTINCT origin_id) FROM lt_tasks ${where}`;
54
- const dataSql = `SELECT
55
- origin_id,
56
- COUNT(*)::int AS task_count,
57
- COUNT(*) FILTER (WHERE status = 'completed')::int AS completed,
58
- COUNT(*) FILTER (WHERE status = 'needs_intervention')::int AS escalated,
59
- array_agg(DISTINCT workflow_type) AS workflow_types,
60
- MIN(created_at) AS started_at,
61
- MAX(COALESCE(completed_at, created_at)) AS last_activity
62
- FROM lt_tasks
63
- ${where}
64
- GROUP BY origin_id
65
- ${having}
66
- ORDER BY MAX(created_at) DESC
67
- LIMIT $${idx++} OFFSET $${idx++}`;
47
+ // Count wraps the grouped set in a subquery when a status HAVING filter is present.
48
+ const countSql = (0, sql_1.listProcessesCount)(where, having);
49
+ const dataSql = (0, sql_1.listProcessesData)(where, having, idx++, idx++);
68
50
  const dataParams = [...filterParams, limit, offset];
69
51
  const [countResult, dataResult] = await Promise.all([
70
52
  pool.query(countSql, filterParams),
@@ -4,9 +4,11 @@ import type { ResolvedHandle } from './types';
4
4
  * HotMesh needs to get a workflow handle.
5
5
  *
6
6
  * 1. Look up lt_tasks by workflow_id — returns workflow_type and task_queue.
7
- * 2. If no task record (e.g., orchestrators/containers), fall back to
8
- * durable.jobs (entity) + lt_config_workflows (task_queue).
7
+ * 2. If no task record (e.g., orchestrators/containers, or a child running in
8
+ * another app), fall back to `<appId>.jobs` (entity) + lt_config_workflows
9
+ * (task_queue). `appId` selects the HotMesh namespace to scan — children of
10
+ * a workflow live under their own app's schema, not always `durable`.
9
11
  * 3. If task_queue is null (pre-migration record), fall back to lt_config_workflows.
10
12
  * 4. Throws if the workflow cannot be resolved.
11
13
  */
12
- export declare function resolveWorkflowHandle(workflowId: string): Promise<ResolvedHandle>;
14
+ export declare function resolveWorkflowHandle(workflowId: string, appId?: string): Promise<ResolvedHandle>;
@@ -9,12 +9,14 @@ const sql_1 = require("./sql");
9
9
  * HotMesh needs to get a workflow handle.
10
10
  *
11
11
  * 1. Look up lt_tasks by workflow_id — returns workflow_type and task_queue.
12
- * 2. If no task record (e.g., orchestrators/containers), fall back to
13
- * durable.jobs (entity) + lt_config_workflows (task_queue).
12
+ * 2. If no task record (e.g., orchestrators/containers, or a child running in
13
+ * another app), fall back to `<appId>.jobs` (entity) + lt_config_workflows
14
+ * (task_queue). `appId` selects the HotMesh namespace to scan — children of
15
+ * a workflow live under their own app's schema, not always `durable`.
14
16
  * 3. If task_queue is null (pre-migration record), fall back to lt_config_workflows.
15
17
  * 4. Throws if the workflow cannot be resolved.
16
18
  */
17
- async function resolveWorkflowHandle(workflowId) {
19
+ async function resolveWorkflowHandle(workflowId, appId = 'durable') {
18
20
  const pool = (0, db_1.getPool)();
19
21
  // 1. Try lt_tasks first (leaf workflows)
20
22
  const { rows } = await pool.query(sql_1.RESOLVE_TASK_BY_WORKFLOW_ID, [workflowId]);
@@ -29,9 +31,10 @@ async function resolveWorkflowHandle(workflowId) {
29
31
  return { taskQueue: configRows[0].task_queue, workflowName: workflow_type };
30
32
  }
31
33
  }
32
- // 2. Fall back to durable.jobs — handles orchestrators/containers that
33
- // have no lt_tasks record but do have a job with an entity tag.
34
- const { rows: jobRows } = await pool.query(sql_1.RESOLVE_JOB_ENTITY, [`hmsh:durable:j:${workflowId}`]);
34
+ // 2. Fall back to <appId>.jobs — handles orchestrators/containers that
35
+ // have no lt_tasks record but do have a job with an entity tag, and
36
+ // children running in a non-default namespace.
37
+ const { rows: jobRows } = await pool.query((0, sql_1.RESOLVE_JOB_ENTITY)(appId), [`hmsh:${appId}:j:${workflowId}`]);
35
38
  if (jobRows.length > 0 && jobRows[0].entity) {
36
39
  const entity = jobRows[0].entity;
37
40
  // 2a. Try lt_config_workflows for task_queue
@@ -1,12 +1,40 @@
1
- export declare const CREATE_TASK = "\n INSERT INTO lt_tasks\n (workflow_id, workflow_type, lt_type, task_queue, signal_id,\n parent_workflow_id, origin_id, parent_id, envelope, metadata, priority,\n trace_id, span_id, initiated_by, principal_type, executing_as, status)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, COALESCE($17, 'pending'))\n RETURNING *";
1
+ export declare const CREATE_TASK = "\n INSERT INTO lt_tasks\n (workflow_id, workflow_type, lt_type, task_queue, signal_id,\n parent_workflow_id, origin_id, parent_id, envelope, metadata, priority,\n trace_id, span_id, initiated_by, principal_type, executing_as, status)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, COALESCE($17, 'pending'))\n ON CONFLICT (workflow_id) DO UPDATE SET workflow_id = lt_tasks.workflow_id\n RETURNING *, (xmax = 0) AS _inserted";
2
2
  export declare const APPEND_MILESTONES = "\n UPDATE lt_tasks\n SET milestones = milestones || $1::jsonb\n WHERE id = $2\n RETURNING *";
3
3
  export declare const GET_TASK = "SELECT * FROM lt_tasks WHERE id = $1";
4
4
  export declare const GET_TASK_BY_SIGNAL_ID = "SELECT * FROM lt_tasks WHERE signal_id = $1";
5
5
  export declare const GET_TASK_BY_WORKFLOW_ID = "SELECT * FROM lt_tasks WHERE workflow_id = $1 ORDER BY created_at DESC LIMIT 1";
6
+ /**
7
+ * Build the partial-update statement for updateTask. The caller assembles the
8
+ * `SET` clause from whichever fields are present (each as a `$n` placeholder) and
9
+ * passes the placeholder index of the trailing `id` bind. One guarded UPDATE by
10
+ * primary key — no read-then-write.
11
+ */
12
+ export declare function updateTaskById(setClause: string, idIdx: number): string;
13
+ /** Count query for listTasks. `where` is the caller-built `WHERE …` clause (or ''). */
14
+ export declare function listTasksCount(where: string): string;
15
+ /** Page query for listTasks. limit/offset placeholder indices follow the filter binds. */
16
+ export declare function listTasksData(where: string, limitIdx: number, offsetIdx: number): string;
6
17
  export declare const RESOLVE_TASK_BY_WORKFLOW_ID = "SELECT workflow_type, task_queue FROM lt_tasks WHERE workflow_id = $1 ORDER BY created_at DESC LIMIT 1";
7
18
  export declare const RESOLVE_CONFIG_TASK_QUEUE = "SELECT task_queue FROM lt_config_workflows WHERE workflow_type = $1";
8
- export declare const RESOLVE_JOB_ENTITY = "SELECT entity FROM durable.jobs WHERE key = $1 LIMIT 1";
19
+ /**
20
+ * Look up a job's entity tag in a specific HotMesh namespace. The namespace is a
21
+ * Postgres schema name, so it is interpolated (not a bind param) — same pattern
22
+ * as the diagnostics queries. Callers pass the trusted app_id from config.
23
+ */
24
+ export declare const RESOLVE_JOB_ENTITY: (appId: string) => string;
9
25
  export declare const GET_PROCESS_TASKS = "SELECT * FROM lt_tasks WHERE origin_id = $1 ORDER BY created_at ASC";
26
+ /**
27
+ * Count query for listProcesses. `where` restricts which origin_ids are in scope;
28
+ * `having` (empty string when no status filter) aggregates per-origin counts, so the
29
+ * count must wrap the grouped set in a subquery. Both fragments carry only `$n` binds.
30
+ */
31
+ export declare function listProcessesCount(where: string, having: string): string;
32
+ /**
33
+ * Page query for listProcesses — one row per origin_id with rolled-up task counts,
34
+ * workflow types, and activity window. limit/offset placeholder indices follow the
35
+ * filter binds.
36
+ */
37
+ export declare function listProcessesData(where: string, having: string, limitIdx: number, offsetIdx: number): string;
10
38
  /**
11
39
  * Build the process-stats totals CTE query for a given interval.
12
40
  * The interval value MUST come from the VALID_PERIODS whitelist.
@@ -4,16 +4,29 @@
4
4
  // ---------------------------------------------------------------------------
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.GET_PROCESS_TASKS = exports.RESOLVE_JOB_ENTITY = exports.RESOLVE_CONFIG_TASK_QUEUE = exports.RESOLVE_TASK_BY_WORKFLOW_ID = exports.GET_TASK_BY_WORKFLOW_ID = exports.GET_TASK_BY_SIGNAL_ID = exports.GET_TASK = exports.APPEND_MILESTONES = exports.CREATE_TASK = void 0;
7
+ exports.updateTaskById = updateTaskById;
8
+ exports.listTasksCount = listTasksCount;
9
+ exports.listTasksData = listTasksData;
10
+ exports.listProcessesCount = listProcessesCount;
11
+ exports.listProcessesData = listProcessesData;
7
12
  exports.processStatsTotals = processStatsTotals;
8
13
  exports.processStatsByType = processStatsByType;
9
14
  // ---- crud.ts queries ------------------------------------------------------
15
+ // A task is 1:1 with its workflow_id. ON CONFLICT (workflow_id) makes createTask
16
+ // idempotent under proxyActivity retry (maximumAttempts: 3) and re-driven sagas:
17
+ // a retry re-targets the SAME row instead of inserting a duplicate. The no-op
18
+ // DO UPDATE is required so RETURNING yields the existing row on conflict; the
19
+ // `(xmax = 0)` flag tells the caller whether this call actually inserted (so the
20
+ // `task.created` event fires exactly once). Requires the unique index from
21
+ // migration 012.
10
22
  exports.CREATE_TASK = `
11
23
  INSERT INTO lt_tasks
12
24
  (workflow_id, workflow_type, lt_type, task_queue, signal_id,
13
25
  parent_workflow_id, origin_id, parent_id, envelope, metadata, priority,
14
26
  trace_id, span_id, initiated_by, principal_type, executing_as, status)
15
27
  VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, COALESCE($17, 'pending'))
16
- RETURNING *`;
28
+ ON CONFLICT (workflow_id) DO UPDATE SET workflow_id = lt_tasks.workflow_id
29
+ RETURNING *, (xmax = 0) AS _inserted`;
17
30
  exports.APPEND_MILESTONES = `
18
31
  UPDATE lt_tasks
19
32
  SET milestones = milestones || $1::jsonb
@@ -22,12 +35,69 @@ exports.APPEND_MILESTONES = `
22
35
  exports.GET_TASK = `SELECT * FROM lt_tasks WHERE id = $1`;
23
36
  exports.GET_TASK_BY_SIGNAL_ID = `SELECT * FROM lt_tasks WHERE signal_id = $1`;
24
37
  exports.GET_TASK_BY_WORKFLOW_ID = `SELECT * FROM lt_tasks WHERE workflow_id = $1 ORDER BY created_at DESC LIMIT 1`;
38
+ /**
39
+ * Build the partial-update statement for updateTask. The caller assembles the
40
+ * `SET` clause from whichever fields are present (each as a `$n` placeholder) and
41
+ * passes the placeholder index of the trailing `id` bind. One guarded UPDATE by
42
+ * primary key — no read-then-write.
43
+ */
44
+ function updateTaskById(setClause, idIdx) {
45
+ return `UPDATE lt_tasks SET ${setClause} WHERE id = $${idIdx} RETURNING *`;
46
+ }
47
+ /** Count query for listTasks. `where` is the caller-built `WHERE …` clause (or ''). */
48
+ function listTasksCount(where) {
49
+ return `SELECT COUNT(*) FROM lt_tasks ${where}`;
50
+ }
51
+ /** Page query for listTasks. limit/offset placeholder indices follow the filter binds. */
52
+ function listTasksData(where, limitIdx, offsetIdx) {
53
+ return `SELECT * FROM lt_tasks ${where} ORDER BY created_at DESC LIMIT $${limitIdx} OFFSET $${offsetIdx}`;
54
+ }
25
55
  // ---- resolve.ts queries ---------------------------------------------------
26
56
  exports.RESOLVE_TASK_BY_WORKFLOW_ID = `SELECT workflow_type, task_queue FROM lt_tasks WHERE workflow_id = $1 ORDER BY created_at DESC LIMIT 1`;
27
57
  exports.RESOLVE_CONFIG_TASK_QUEUE = `SELECT task_queue FROM lt_config_workflows WHERE workflow_type = $1`;
28
- exports.RESOLVE_JOB_ENTITY = `SELECT entity FROM durable.jobs WHERE key = $1 LIMIT 1`;
58
+ /**
59
+ * Look up a job's entity tag in a specific HotMesh namespace. The namespace is a
60
+ * Postgres schema name, so it is interpolated (not a bind param) — same pattern
61
+ * as the diagnostics queries. Callers pass the trusted app_id from config.
62
+ */
63
+ const RESOLVE_JOB_ENTITY = (appId) => `SELECT entity FROM "${appId}".jobs WHERE key = $1 LIMIT 1`;
64
+ exports.RESOLVE_JOB_ENTITY = RESOLVE_JOB_ENTITY;
29
65
  // ---- process.ts queries ---------------------------------------------------
30
66
  exports.GET_PROCESS_TASKS = `SELECT * FROM lt_tasks WHERE origin_id = $1 ORDER BY created_at ASC`;
67
+ /**
68
+ * Count query for listProcesses. `where` restricts which origin_ids are in scope;
69
+ * `having` (empty string when no status filter) aggregates per-origin counts, so the
70
+ * count must wrap the grouped set in a subquery. Both fragments carry only `$n` binds.
71
+ */
72
+ function listProcessesCount(where, having) {
73
+ return having
74
+ ? `SELECT COUNT(*) FROM (
75
+ SELECT origin_id FROM lt_tasks ${where}
76
+ GROUP BY origin_id ${having}
77
+ ) sub`
78
+ : `SELECT COUNT(DISTINCT origin_id) FROM lt_tasks ${where}`;
79
+ }
80
+ /**
81
+ * Page query for listProcesses — one row per origin_id with rolled-up task counts,
82
+ * workflow types, and activity window. limit/offset placeholder indices follow the
83
+ * filter binds.
84
+ */
85
+ function listProcessesData(where, having, limitIdx, offsetIdx) {
86
+ return `SELECT
87
+ origin_id,
88
+ COUNT(*)::int AS task_count,
89
+ COUNT(*) FILTER (WHERE status = 'completed')::int AS completed,
90
+ COUNT(*) FILTER (WHERE status = 'needs_intervention')::int AS escalated,
91
+ array_agg(DISTINCT workflow_type) AS workflow_types,
92
+ MIN(created_at) AS started_at,
93
+ MAX(COALESCE(completed_at, created_at)) AS last_activity
94
+ FROM lt_tasks
95
+ ${where}
96
+ GROUP BY origin_id
97
+ ${having}
98
+ ORDER BY MAX(created_at) DESC
99
+ LIMIT $${limitIdx} OFFSET $${offsetIdx}`;
100
+ }
31
101
  /**
32
102
  * Build the process-stats totals CTE query for a given interval.
33
103
  * The interval value MUST come from the VALID_PERIODS whitelist.
@@ -11,6 +11,7 @@ export declare function listUsers(filters: {
11
11
  role?: string;
12
12
  roleType?: LTRoleType;
13
13
  status?: LTUserStatus;
14
+ search?: string;
14
15
  limit?: number;
15
16
  offset?: number;
16
17
  }): Promise<{