@hotmeshio/long-tail 0.10.8 → 0.10.10

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 (296) hide show
  1. package/build/api/escalations/bulk.js +7 -1
  2. package/build/api/escalations/helpers.d.ts +10 -1
  3. package/build/api/escalations/helpers.js +52 -12
  4. package/build/api/index.d.ts +1 -0
  5. package/build/api/index.js +2 -1
  6. package/build/api/personas.d.ts +121 -0
  7. package/build/api/personas.js +341 -0
  8. package/build/bin/ltc.js +23 -0
  9. package/build/lib/cli/commands/personas.d.ts +16 -0
  10. package/build/lib/cli/commands/personas.js +42 -0
  11. package/build/lib/db/schemas/024_personas.sql +53 -0
  12. package/build/lib/events/matching.d.ts +10 -0
  13. package/build/lib/events/matching.js +14 -0
  14. package/build/lib/events/publish.d.ts +8 -2
  15. package/build/lib/events/publish.js +9 -2
  16. package/build/lib/events/socketio.d.ts +8 -2
  17. package/build/lib/events/socketio.js +36 -3
  18. package/build/lib/events/system-events.js +9 -1
  19. package/build/routes/index.js +2 -0
  20. package/build/routes/personas.d.ts +2 -0
  21. package/build/routes/personas.js +118 -0
  22. package/build/routes/users.js +35 -0
  23. package/build/sdk/index.d.ts +15 -0
  24. package/build/sdk/index.js +16 -0
  25. package/build/services/escalation/crud.js +40 -2
  26. package/build/services/orchestrator/condition.d.ts +1 -1
  27. package/build/services/orchestrator/condition.js +1 -1
  28. package/build/services/persona/index.d.ts +92 -0
  29. package/build/services/persona/index.js +217 -0
  30. package/build/services/persona/sql.d.ts +24 -0
  31. package/build/services/persona/sql.js +158 -0
  32. package/build/services/persona/types.d.ts +23 -0
  33. package/build/services/persona/types.js +33 -0
  34. package/build/services/topics/system-topics.d.ts +0 -4
  35. package/build/services/topics/system-topics.js +57 -14
  36. package/build/services/user/sql.d.ts +8 -5
  37. package/build/services/user/sql.js +15 -5
  38. package/build/system/mcp-servers/admin/index.d.ts +1 -0
  39. package/build/system/mcp-servers/admin/index.js +5 -2
  40. package/build/system/mcp-servers/admin/personas.d.ts +8 -0
  41. package/build/system/mcp-servers/admin/personas.js +186 -0
  42. package/build/system/mcp-servers/admin/schemas.d.ts +91 -0
  43. package/build/system/mcp-servers/admin/schemas.js +42 -2
  44. package/build/system/seed/tool-manifests-admin.d.ts +975 -0
  45. package/build/system/seed/tool-manifests-admin.js +11 -0
  46. package/build/tsconfig.tsbuildinfo +1 -1
  47. package/build/types/events.d.ts +11 -3
  48. package/build/types/index.d.ts +1 -0
  49. package/build/types/persona.d.ts +56 -0
  50. package/build/types/persona.js +2 -0
  51. package/build/types/user.d.ts +2 -0
  52. package/dashboard/dist/assets/{AdminDashboard-D0HdEkT9.js → AdminDashboard-cGYuppUP.js} +2 -2
  53. package/dashboard/dist/assets/{AdminDashboard-D0HdEkT9.js.map → AdminDashboard-cGYuppUP.js.map} +1 -1
  54. package/dashboard/dist/assets/{AgentConfigPage-CtURUMOV.js → AgentConfigPage-DwaUyoCy.js} +2 -2
  55. package/dashboard/dist/assets/{AgentConfigPage-CtURUMOV.js.map → AgentConfigPage-DwaUyoCy.js.map} +1 -1
  56. package/dashboard/dist/assets/AgentDetailPage-DxpFaltM.js +4 -0
  57. package/dashboard/dist/assets/AgentDetailPage-DxpFaltM.js.map +1 -0
  58. package/dashboard/dist/assets/{AgentsPage-DBequneI.js → AgentsPage-ByOoA8oT.js} +2 -2
  59. package/dashboard/dist/assets/{AgentsPage-DBequneI.js.map → AgentsPage-ByOoA8oT.js.map} +1 -1
  60. package/dashboard/dist/assets/AutoGrowTextarea-y-oNY51_.js +2 -0
  61. package/dashboard/dist/assets/AutoGrowTextarea-y-oNY51_.js.map +1 -0
  62. package/dashboard/dist/assets/{AvailableEscalationsPage-Bk7fFV2e.js → AvailableEscalationsPage-C1vtTvqP.js} +2 -2
  63. package/dashboard/dist/assets/AvailableEscalationsPage-C1vtTvqP.js.map +1 -0
  64. package/dashboard/dist/assets/{BotPicker-BMXokkH7.js → BotPicker-Dohv8dhR.js} +2 -2
  65. package/dashboard/dist/assets/{BotPicker-BMXokkH7.js.map → BotPicker-Dohv8dhR.js.map} +1 -1
  66. package/dashboard/dist/assets/{CapabilitiesPage-w-D6xraE.js → CapabilitiesPage-DeijFG3J.js} +2 -2
  67. package/dashboard/dist/assets/{CapabilitiesPage-w-D6xraE.js.map → CapabilitiesPage-DeijFG3J.js.map} +1 -1
  68. package/dashboard/dist/assets/{CollapsibleSection-IPL1H1bQ.js → CollapsibleSection-BPNwS4eO.js} +2 -2
  69. package/dashboard/dist/assets/{CollapsibleSection-IPL1H1bQ.js.map → CollapsibleSection-BPNwS4eO.js.map} +1 -1
  70. package/dashboard/dist/assets/CountdownTimer-BF71ldGF.js +2 -0
  71. package/dashboard/dist/assets/CountdownTimer-BF71ldGF.js.map +1 -0
  72. package/dashboard/dist/assets/{CredentialsPage-DR48hDES.js → CredentialsPage-oeNmMzTM.js} +2 -2
  73. package/dashboard/dist/assets/{CredentialsPage-DR48hDES.js.map → CredentialsPage-oeNmMzTM.js.map} +1 -1
  74. package/dashboard/dist/assets/{CronLabel-KQEj0cDS.js → CronLabel-CebR1m2k.js} +2 -2
  75. package/dashboard/dist/assets/{CronLabel-KQEj0cDS.js.map → CronLabel-CebR1m2k.js.map} +1 -1
  76. package/dashboard/dist/assets/CustomDurationPicker-Bh9QdBVw.js +2 -0
  77. package/dashboard/dist/assets/CustomDurationPicker-Bh9QdBVw.js.map +1 -0
  78. package/dashboard/dist/assets/{DropZone-BrnAkQxF.js → DropZone-Bavzt2QR.js} +2 -2
  79. package/dashboard/dist/assets/{DropZone-BrnAkQxF.js.map → DropZone-Bavzt2QR.js.map} +1 -1
  80. package/dashboard/dist/assets/ElapsedCell-Caa6CU_y.js +2 -0
  81. package/dashboard/dist/assets/{ElapsedCell-Cflz7Pb5.js.map → ElapsedCell-Caa6CU_y.js.map} +1 -1
  82. package/dashboard/dist/assets/{EscalationListSchemaPage-BTBZ8OBY.js → EscalationListSchemaPage-CAGfq0eK.js} +3 -3
  83. package/dashboard/dist/assets/{EscalationListSchemaPage-BTBZ8OBY.js.map → EscalationListSchemaPage-CAGfq0eK.js.map} +1 -1
  84. package/dashboard/dist/assets/{EscalationSchemaPage-Cd9fR2EA.js → EscalationSchemaPage-qDD4ur6P.js} +2 -2
  85. package/dashboard/dist/assets/{EscalationSchemaPage-Cd9fR2EA.js.map → EscalationSchemaPage-qDD4ur6P.js.map} +1 -1
  86. package/dashboard/dist/assets/{EscalationsOverview-BzNFcA0i.js → EscalationsOverview-CC1wRTzy.js} +2 -2
  87. package/dashboard/dist/assets/{EscalationsOverview-BzNFcA0i.js.map → EscalationsOverview-CC1wRTzy.js.map} +1 -1
  88. package/dashboard/dist/assets/{EventTable-S2BJqOt2.js → EventTable-4JeTcXr_.js} +2 -2
  89. package/dashboard/dist/assets/{EventTable-S2BJqOt2.js.map → EventTable-4JeTcXr_.js.map} +1 -1
  90. package/dashboard/dist/assets/{FilterBar-CeXwNVn6.js → FilterBar-BOV8DWIO.js} +2 -2
  91. package/dashboard/dist/assets/{FilterBar-CeXwNVn6.js.map → FilterBar-BOV8DWIO.js.map} +1 -1
  92. package/dashboard/dist/assets/{GraphInvokePage-CBjXjOLX.js → GraphInvokePage-C0i1speW.js} +2 -2
  93. package/dashboard/dist/assets/{GraphInvokePage-CBjXjOLX.js.map → GraphInvokePage-C0i1speW.js.map} +1 -1
  94. package/dashboard/dist/assets/HomePage-HPCd8SjF.js +2 -0
  95. package/dashboard/dist/assets/HomePage-HPCd8SjF.js.map +1 -0
  96. package/dashboard/dist/assets/{ListToolbar-Dx6DuFdR.js → ListToolbar-BFHVOba6.js} +2 -2
  97. package/dashboard/dist/assets/{ListToolbar-Dx6DuFdR.js.map → ListToolbar-BFHVOba6.js.map} +1 -1
  98. package/dashboard/dist/assets/{McpOverview-Cj8_UyWJ.js → McpOverview-Chn2zIXr.js} +2 -2
  99. package/dashboard/dist/assets/{McpOverview-Cj8_UyWJ.js.map → McpOverview-Chn2zIXr.js.map} +1 -1
  100. package/dashboard/dist/assets/McpQueryDetailPage-Cv1FKrvw.js +5 -0
  101. package/dashboard/dist/assets/McpQueryDetailPage-Cv1FKrvw.js.map +1 -0
  102. package/dashboard/dist/assets/McpQueryPage-Dzn8JE4E.js +2 -0
  103. package/dashboard/dist/assets/McpQueryPage-Dzn8JE4E.js.map +1 -0
  104. package/dashboard/dist/assets/{McpRunDetailPage-BqhRwkGk.js → McpRunDetailPage-CuNtR4Ed.js} +2 -2
  105. package/dashboard/dist/assets/{McpRunDetailPage-BqhRwkGk.js.map → McpRunDetailPage-CuNtR4Ed.js.map} +1 -1
  106. package/dashboard/dist/assets/{McpRunsPage-CNXYU4iX.js → McpRunsPage-C8iifeKN.js} +2 -2
  107. package/dashboard/dist/assets/{McpRunsPage-CNXYU4iX.js.map → McpRunsPage-C8iifeKN.js.map} +1 -1
  108. package/dashboard/dist/assets/{NamespacePill-DQGzN0Ph.js → NamespacePill-ep9Zmokr.js} +2 -2
  109. package/dashboard/dist/assets/{NamespacePill-DQGzN0Ph.js.map → NamespacePill-ep9Zmokr.js.map} +1 -1
  110. package/dashboard/dist/assets/{OperationsPage-C7UB_d-X.js → OperationsPage-flrZ-EJ9.js} +2 -2
  111. package/dashboard/dist/assets/{OperationsPage-C7UB_d-X.js.map → OperationsPage-flrZ-EJ9.js.map} +1 -1
  112. package/dashboard/dist/assets/OperatorDashboard-Dhs2eo8p.js +2 -0
  113. package/dashboard/dist/assets/OperatorDashboard-Dhs2eo8p.js.map +1 -0
  114. package/dashboard/dist/assets/{PageHeader-DlcE3U5L.js → PageHeader-Bw8RNkqR.js} +2 -2
  115. package/dashboard/dist/assets/{PageHeader-DlcE3U5L.js.map → PageHeader-Bw8RNkqR.js.map} +1 -1
  116. package/dashboard/dist/assets/{PageHeaderWithStats-BMhnR3-9.js → PageHeaderWithStats-NR_4idn6.js} +2 -2
  117. package/dashboard/dist/assets/{PageHeaderWithStats-BMhnR3-9.js.map → PageHeaderWithStats-NR_4idn6.js.map} +1 -1
  118. package/dashboard/dist/assets/PersonaDetailPage-DKILoUqL.js +2 -0
  119. package/dashboard/dist/assets/PersonaDetailPage-DKILoUqL.js.map +1 -0
  120. package/dashboard/dist/assets/PersonasPage-qvzHTrFw.js +2 -0
  121. package/dashboard/dist/assets/PersonasPage-qvzHTrFw.js.map +1 -0
  122. package/dashboard/dist/assets/ProcessDetailPage-C3LfeKvi.js +2 -0
  123. package/dashboard/dist/assets/ProcessDetailPage-C3LfeKvi.js.map +1 -0
  124. package/dashboard/dist/assets/{ProcessesListPage-DatKHVkd.js → ProcessesListPage-OoZ_u4ty.js} +2 -2
  125. package/dashboard/dist/assets/{ProcessesListPage-DatKHVkd.js.map → ProcessesListPage-OoZ_u4ty.js.map} +1 -1
  126. package/dashboard/dist/assets/RoleDetailPage-D70jTLZm.js +8 -0
  127. package/dashboard/dist/assets/RoleDetailPage-D70jTLZm.js.map +1 -0
  128. package/dashboard/dist/assets/{RolePill-dzo14hB_.js → RolePill-TySZq7dB.js} +2 -2
  129. package/dashboard/dist/assets/{RolePill-dzo14hB_.js.map → RolePill-TySZq7dB.js.map} +1 -1
  130. package/dashboard/dist/assets/RolesPage-CNueMVuJ.js +2 -0
  131. package/dashboard/dist/assets/RolesPage-CNueMVuJ.js.map +1 -0
  132. package/dashboard/dist/assets/{RunAsSelector-VbBn0o7s.js → RunAsSelector-CwWEpiSF.js} +2 -2
  133. package/dashboard/dist/assets/{RunAsSelector-VbBn0o7s.js.map → RunAsSelector-CwWEpiSF.js.map} +1 -1
  134. package/dashboard/dist/assets/ScopeBadge-C7Uixtmk.js +2 -0
  135. package/dashboard/dist/assets/ScopeBadge-C7Uixtmk.js.map +1 -0
  136. package/dashboard/dist/assets/StatCard-Ca-ngCaD.js +2 -0
  137. package/dashboard/dist/assets/StatCard-Ca-ngCaD.js.map +1 -0
  138. package/dashboard/dist/assets/{StatusBadge-BbqghFMi.js → StatusBadge-BwUvykDo.js} +2 -2
  139. package/dashboard/dist/assets/{StatusBadge-BbqghFMi.js.map → StatusBadge-BwUvykDo.js.map} +1 -1
  140. package/dashboard/dist/assets/{StickyPagination-BI8tDf2V.js → StickyPagination-DvIF3kQK.js} +2 -2
  141. package/dashboard/dist/assets/{StickyPagination-BI8tDf2V.js.map → StickyPagination-DvIF3kQK.js.map} +1 -1
  142. package/dashboard/dist/assets/{StreamMessageDetail-BObbEz7P.js → StreamMessageDetail-DkFK_XGD.js} +2 -2
  143. package/dashboard/dist/assets/StreamMessageDetail-DkFK_XGD.js.map +1 -0
  144. package/dashboard/dist/assets/{SwimlaneTimeline-BHjAtOGC.js → SwimlaneTimeline-CMw-Et6h.js} +2 -2
  145. package/dashboard/dist/assets/{SwimlaneTimeline-BHjAtOGC.js.map → SwimlaneTimeline-CMw-Et6h.js.map} +1 -1
  146. package/dashboard/dist/assets/{TagInput-cyhTZTwe.js → TagInput-D8gSp48D.js} +2 -2
  147. package/dashboard/dist/assets/{TagInput-cyhTZTwe.js.map → TagInput-D8gSp48D.js.map} +1 -1
  148. package/dashboard/dist/assets/{TaskDetailPage-B-E1dqUw.js → TaskDetailPage-BhXuChOf.js} +2 -2
  149. package/dashboard/dist/assets/{TaskDetailPage-B-E1dqUw.js.map → TaskDetailPage-BhXuChOf.js.map} +1 -1
  150. package/dashboard/dist/assets/{TaskQueuePill-_zIpG4bG.js → TaskQueuePill-CHqolBmU.js} +2 -2
  151. package/dashboard/dist/assets/{TaskQueuePill-_zIpG4bG.js.map → TaskQueuePill-CHqolBmU.js.map} +1 -1
  152. package/dashboard/dist/assets/{TasksListPage-urJ4XiUi.js → TasksListPage-6JHQQ5QZ.js} +2 -2
  153. package/dashboard/dist/assets/{TasksListPage-urJ4XiUi.js.map → TasksListPage-6JHQQ5QZ.js.map} +1 -1
  154. package/dashboard/dist/assets/{TimeAgo-D6Dg0SQs.js → TimeAgo-CInx-vzY.js} +2 -2
  155. package/dashboard/dist/assets/{TimeAgo-D6Dg0SQs.js.map → TimeAgo-CInx-vzY.js.map} +1 -1
  156. package/dashboard/dist/assets/{TimestampCell-DG__Gr-e.js → TimestampCell-Fq17Zrsu.js} +2 -2
  157. package/dashboard/dist/assets/{TimestampCell-DG__Gr-e.js.map → TimestampCell-Fq17Zrsu.js.map} +1 -1
  158. package/dashboard/dist/assets/{ToolPill-CKHYG6eV.js → ToolPill-BbgMDhaE.js} +2 -2
  159. package/dashboard/dist/assets/{ToolPill-CKHYG6eV.js.map → ToolPill-BbgMDhaE.js.map} +1 -1
  160. package/dashboard/dist/assets/{ToolTestPanel-D-hGLf95.js → ToolTestPanel-DhjEe59s.js} +2 -2
  161. package/dashboard/dist/assets/{ToolTestPanel-D-hGLf95.js.map → ToolTestPanel-DhjEe59s.js.map} +1 -1
  162. package/dashboard/dist/assets/{TopicDetailPage-B10i4xV2.js → TopicDetailPage-DbIdmQpQ.js} +3 -3
  163. package/dashboard/dist/assets/{TopicDetailPage-B10i4xV2.js.map → TopicDetailPage-DbIdmQpQ.js.map} +1 -1
  164. package/dashboard/dist/assets/TopicsPage-CAP-GUbr.js +2 -0
  165. package/dashboard/dist/assets/{TopicsPage-C5THflVQ.js.map → TopicsPage-CAP-GUbr.js.map} +1 -1
  166. package/dashboard/dist/assets/{UserName-CZTpouta.js → UserName-DggcLkSc.js} +2 -2
  167. package/dashboard/dist/assets/{UserName-CZTpouta.js.map → UserName-DggcLkSc.js.map} +1 -1
  168. package/dashboard/dist/assets/{WorkflowExecutionPage-mbnj6saI.js → WorkflowExecutionPage-Bmra5fVt.js} +2 -2
  169. package/dashboard/dist/assets/{WorkflowExecutionPage-mbnj6saI.js.map → WorkflowExecutionPage-Bmra5fVt.js.map} +1 -1
  170. package/dashboard/dist/assets/{WorkflowPill-DlSVXnnj.js → WorkflowPill-CcUUVugA.js} +2 -2
  171. package/dashboard/dist/assets/{WorkflowPill-DlSVXnnj.js.map → WorkflowPill-CcUUVugA.js.map} +1 -1
  172. package/dashboard/dist/assets/{WorkflowsDashboard-DC_9GrpY.js → WorkflowsDashboard-BQsZAGYU.js} +2 -2
  173. package/dashboard/dist/assets/{WorkflowsDashboard-DC_9GrpY.js.map → WorkflowsDashboard-BQsZAGYU.js.map} +1 -1
  174. package/dashboard/dist/assets/{WorkflowsOverview-ClSH1UwG.js → WorkflowsOverview-CeliraHZ.js} +2 -2
  175. package/dashboard/dist/assets/{WorkflowsOverview-ClSH1UwG.js.map → WorkflowsOverview-CeliraHZ.js.map} +1 -1
  176. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BkgoB7oD.js → YamlWorkflowDetailPage-DGxlonrV.js} +2 -2
  177. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BkgoB7oD.js.map → YamlWorkflowDetailPage-DGxlonrV.js.map} +1 -1
  178. package/dashboard/dist/assets/{YamlWorkflowsPage-Db_REA2f.js → YamlWorkflowsPage-DnT8UiyQ.js} +2 -2
  179. package/dashboard/dist/assets/{YamlWorkflowsPage-Db_REA2f.js.map → YamlWorkflowsPage-DnT8UiyQ.js.map} +1 -1
  180. package/dashboard/dist/assets/{agents-Dvb8j9AB.js → agents-mRV7m4sh.js} +2 -2
  181. package/dashboard/dist/assets/{agents-Dvb8j9AB.js.map → agents-mRV7m4sh.js.map} +1 -1
  182. package/dashboard/dist/assets/{bots-D9jYHjBM.js → bots-SONCZlCM.js} +2 -2
  183. package/dashboard/dist/assets/{bots-D9jYHjBM.js.map → bots-SONCZlCM.js.map} +1 -1
  184. package/dashboard/dist/assets/{capabilities-BAto9JcQ.js → capabilities-DZjCMN32.js} +2 -2
  185. package/dashboard/dist/assets/{capabilities-BAto9JcQ.js.map → capabilities-DZjCMN32.js.map} +1 -1
  186. package/dashboard/dist/assets/{controlplane-2Aic2Tfm.js → controlplane-RQNXjna2.js} +2 -2
  187. package/dashboard/dist/assets/{controlplane-2Aic2Tfm.js.map → controlplane-RQNXjna2.js.map} +1 -1
  188. package/dashboard/dist/assets/{escalation-columns-DPKPJtw3.js → escalation-columns-XLEcZRCg.js} +2 -2
  189. package/dashboard/dist/assets/{escalation-columns-DPKPJtw3.js.map → escalation-columns-XLEcZRCg.js.map} +1 -1
  190. package/dashboard/dist/assets/index-2BwHxjCw.css +1 -0
  191. package/dashboard/dist/assets/{index-BZbDwh_Y.js → index-C6GsrvX1.js} +2 -2
  192. package/dashboard/dist/assets/{index-BZbDwh_Y.js.map → index-C6GsrvX1.js.map} +1 -1
  193. package/dashboard/dist/assets/{index-BzQIzZfd.js → index-CK-6m8e_.js} +2 -2
  194. package/dashboard/dist/assets/{index-BzQIzZfd.js.map → index-CK-6m8e_.js.map} +1 -1
  195. package/dashboard/dist/assets/index-CkeSxuZ0.js +2 -0
  196. package/dashboard/dist/assets/{index-B5JgykZD.js.map → index-CkeSxuZ0.js.map} +1 -1
  197. package/dashboard/dist/assets/{index-BW7-Q9Qf.js → index-CxVGlkK6.js} +2 -2
  198. package/dashboard/dist/assets/{index-BW7-Q9Qf.js.map → index-CxVGlkK6.js.map} +1 -1
  199. package/dashboard/dist/assets/index-D2CfSx_x.js +5 -0
  200. package/dashboard/dist/assets/index-D2CfSx_x.js.map +1 -0
  201. package/dashboard/dist/assets/{index-4zRmxPwA.js → index-DFJF8aWz.js} +3 -3
  202. package/dashboard/dist/assets/{index-4zRmxPwA.js.map → index-DFJF8aWz.js.map} +1 -1
  203. package/dashboard/dist/assets/index-DYKRtstT.js +2 -0
  204. package/dashboard/dist/assets/index-DYKRtstT.js.map +1 -0
  205. package/dashboard/dist/assets/index-DY_hlZCQ.js +2 -0
  206. package/dashboard/dist/assets/index-DY_hlZCQ.js.map +1 -0
  207. package/dashboard/dist/assets/{index-KkikDsJ2.js → index-DbZpL10z.js} +2 -2
  208. package/dashboard/dist/assets/{index-KkikDsJ2.js.map → index-DbZpL10z.js.map} +1 -1
  209. package/dashboard/dist/assets/index-Dh3CVChT.js +63 -0
  210. package/dashboard/dist/assets/index-Dh3CVChT.js.map +1 -0
  211. package/dashboard/dist/assets/{index-peRHL38z.js → index-DqsLfO-0.js} +2 -2
  212. package/dashboard/dist/assets/{index-peRHL38z.js.map → index-DqsLfO-0.js.map} +1 -1
  213. package/dashboard/dist/assets/{index-C-T1Wq0Z.js → index-iHV3d7o3.js} +2 -2
  214. package/dashboard/dist/assets/{index-C-T1Wq0Z.js.map → index-iHV3d7o3.js.map} +1 -1
  215. package/dashboard/dist/assets/{index-CeM012DJ.js → index-ymm58cTW.js} +2 -2
  216. package/dashboard/dist/assets/{index-CeM012DJ.js.map → index-ymm58cTW.js.map} +1 -1
  217. package/dashboard/dist/assets/{knowledge-DO8idX0e.js → knowledge-Bawo8u7l.js} +2 -2
  218. package/dashboard/dist/assets/{knowledge-DO8idX0e.js.map → knowledge-Bawo8u7l.js.map} +1 -1
  219. package/dashboard/dist/assets/{mcp-BGpQlkFp.js → mcp-CKIpbpRZ.js} +2 -2
  220. package/dashboard/dist/assets/{mcp-BGpQlkFp.js.map → mcp-CKIpbpRZ.js.map} +1 -1
  221. package/dashboard/dist/assets/{mcp-query-DT0SCB9l.js → mcp-query-vld4hYxQ.js} +2 -2
  222. package/dashboard/dist/assets/{mcp-query-DT0SCB9l.js.map → mcp-query-vld4hYxQ.js.map} +1 -1
  223. package/dashboard/dist/assets/personas-BsARc3df.js +2 -0
  224. package/dashboard/dist/assets/personas-BsARc3df.js.map +1 -0
  225. package/dashboard/dist/assets/{pipelines-CYk7cN6-.js → pipelines-BTSL-5ko.js} +2 -2
  226. package/dashboard/dist/assets/{pipelines-CYk7cN6-.js.map → pipelines-BTSL-5ko.js.map} +1 -1
  227. package/dashboard/dist/assets/{tasks-B4Y5xbF0.js → tasks-DggQdNbj.js} +2 -2
  228. package/dashboard/dist/assets/{tasks-B4Y5xbF0.js.map → tasks-DggQdNbj.js.map} +1 -1
  229. package/dashboard/dist/assets/{topics-CVnqDw3B.js → topics-DzAKa34X.js} +2 -2
  230. package/dashboard/dist/assets/{topics-CVnqDw3B.js.map → topics-DzAKa34X.js.map} +1 -1
  231. package/dashboard/dist/assets/useEventHooks-5uI9oI5W.js +2 -0
  232. package/dashboard/dist/assets/useEventHooks-5uI9oI5W.js.map +1 -0
  233. package/dashboard/dist/assets/{useNamespace-B1t3hsGf.js → useNamespace-CEKzFIqe.js} +2 -2
  234. package/dashboard/dist/assets/{useNamespace-B1t3hsGf.js.map → useNamespace-CEKzFIqe.js.map} +1 -1
  235. package/dashboard/dist/assets/{useYamlActivityEvents-B8Ru07xQ.js → useYamlActivityEvents-hHgX1Z50.js} +2 -2
  236. package/dashboard/dist/assets/{useYamlActivityEvents-B8Ru07xQ.js.map → useYamlActivityEvents-hHgX1Z50.js.map} +1 -1
  237. package/dashboard/dist/assets/{users-C8H4jjTq.js → users-AO8lUyNr.js} +2 -2
  238. package/dashboard/dist/assets/{users-C8H4jjTq.js.map → users-AO8lUyNr.js.map} +1 -1
  239. package/dashboard/dist/assets/{vendor-icons-BE_WrH2z.js → vendor-icons-DN9yGSuM.js} +134 -129
  240. package/dashboard/dist/assets/vendor-icons-DN9yGSuM.js.map +1 -0
  241. package/dashboard/dist/assets/{workflows-BAdI5k--.js → workflows-PtnlRK09.js} +2 -2
  242. package/dashboard/dist/assets/{workflows-BAdI5k--.js.map → workflows-PtnlRK09.js.map} +1 -1
  243. package/dashboard/dist/assets/{yaml-workflows-Bf2aQS-M.js → yaml-workflows-DPu3Y8vG.js} +2 -2
  244. package/dashboard/dist/assets/{yaml-workflows-Bf2aQS-M.js.map → yaml-workflows-DPu3Y8vG.js.map} +1 -1
  245. package/dashboard/dist/index.html +3 -3
  246. package/docs/api/http/escalations.md +1 -1
  247. package/docs/api/http/personas.md +160 -0
  248. package/docs/api/sdk/escalations.md +2 -2
  249. package/docs/cli.md +12 -0
  250. package/docs/dashboard.md +16 -1
  251. package/docs/design-principles.md +9 -5
  252. package/docs/events.md +4 -2
  253. package/docs/hitl/escalation.md +1 -1
  254. package/docs/hitl/x-lt-list-schema.md +12 -5
  255. package/docs/iam.md +47 -0
  256. package/docs/sdk.md +1 -0
  257. package/package.json +1 -1
  258. package/dashboard/dist/assets/AgentDetailPage-C5AnjpD9.js +0 -4
  259. package/dashboard/dist/assets/AgentDetailPage-C5AnjpD9.js.map +0 -1
  260. package/dashboard/dist/assets/AvailableEscalationsPage-Bk7fFV2e.js.map +0 -1
  261. package/dashboard/dist/assets/CountdownTimer-D-CpxYDO.js +0 -2
  262. package/dashboard/dist/assets/CountdownTimer-D-CpxYDO.js.map +0 -1
  263. package/dashboard/dist/assets/CustomDurationPicker-_KceggR9.js +0 -2
  264. package/dashboard/dist/assets/CustomDurationPicker-_KceggR9.js.map +0 -1
  265. package/dashboard/dist/assets/ElapsedCell-Cflz7Pb5.js +0 -2
  266. package/dashboard/dist/assets/HomePage-NMLaXTvf.js +0 -2
  267. package/dashboard/dist/assets/HomePage-NMLaXTvf.js.map +0 -1
  268. package/dashboard/dist/assets/McpQueryDetailPage-Bqh8GChr.js +0 -5
  269. package/dashboard/dist/assets/McpQueryDetailPage-Bqh8GChr.js.map +0 -1
  270. package/dashboard/dist/assets/McpQueryPage-CqFkBwBR.js +0 -2
  271. package/dashboard/dist/assets/McpQueryPage-CqFkBwBR.js.map +0 -1
  272. package/dashboard/dist/assets/OperatorDashboard-DwbPAPaf.js +0 -2
  273. package/dashboard/dist/assets/OperatorDashboard-DwbPAPaf.js.map +0 -1
  274. package/dashboard/dist/assets/ProcessDetailPage-ChGWcwSp.js +0 -2
  275. package/dashboard/dist/assets/ProcessDetailPage-ChGWcwSp.js.map +0 -1
  276. package/dashboard/dist/assets/RoleDetailPage-GJ_coHsM.js +0 -8
  277. package/dashboard/dist/assets/RoleDetailPage-GJ_coHsM.js.map +0 -1
  278. package/dashboard/dist/assets/RolesPage-CPKw336d.js +0 -2
  279. package/dashboard/dist/assets/RolesPage-CPKw336d.js.map +0 -1
  280. package/dashboard/dist/assets/StatCard-DBANWIss.js +0 -2
  281. package/dashboard/dist/assets/StatCard-DBANWIss.js.map +0 -1
  282. package/dashboard/dist/assets/StreamMessageDetail-BObbEz7P.js.map +0 -1
  283. package/dashboard/dist/assets/TopicsPage-C5THflVQ.js +0 -2
  284. package/dashboard/dist/assets/index-B5JgykZD.js +0 -2
  285. package/dashboard/dist/assets/index-CKxFjMtw.js +0 -63
  286. package/dashboard/dist/assets/index-CKxFjMtw.js.map +0 -1
  287. package/dashboard/dist/assets/index-Pmvw74oY.css +0 -1
  288. package/dashboard/dist/assets/index-_Q1Wf2A8.js +0 -2
  289. package/dashboard/dist/assets/index-_Q1Wf2A8.js.map +0 -1
  290. package/dashboard/dist/assets/index-jkVeGCkD.js +0 -5
  291. package/dashboard/dist/assets/index-jkVeGCkD.js.map +0 -1
  292. package/dashboard/dist/assets/index-oHU-ramT.js +0 -2
  293. package/dashboard/dist/assets/index-oHU-ramT.js.map +0 -1
  294. package/dashboard/dist/assets/useEventHooks-D8bVEx-w.js +0 -2
  295. package/dashboard/dist/assets/useEventHooks-D8bVEx-w.js.map +0 -1
  296. package/dashboard/dist/assets/vendor-icons-BE_WrH2z.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listPersonas = listPersonas;
4
+ exports.getPersona = getPersona;
5
+ exports.assignPersona = assignPersona;
6
+ exports.unassignPersona = unassignPersona;
7
+ exports.getUserPersonas = getUserPersonas;
8
+ const client_1 = require("../client");
9
+ const format_1 = require("../format");
10
+ const COLUMNS = [
11
+ { key: 'key', label: 'Key', width: 20 },
12
+ { key: 'title', label: 'Title', width: 24 },
13
+ {
14
+ key: 'roles', label: 'Roles', width: 8,
15
+ format: (v) => String(Array.isArray(v) ? v.length : 0),
16
+ },
17
+ { key: 'user_count', label: 'Users', width: 6, format: (v) => String(v ?? 0) },
18
+ { key: 'description', label: 'Description', width: 40 },
19
+ ];
20
+ async function listPersonas(opts) {
21
+ const data = await (0, client_1.apiFetch)('/personas');
22
+ (0, format_1.output)(data, data.personas || [], COLUMNS, opts, 'key');
23
+ }
24
+ async function getPersona(key, opts) {
25
+ const data = await (0, client_1.apiFetch)(`/personas/${encodeURIComponent(key)}`);
26
+ console.log(JSON.stringify(data, null, 2));
27
+ }
28
+ async function assignPersona(key, userId, opts) {
29
+ const data = await (0, client_1.apiFetch)(`/users/${encodeURIComponent(userId)}/personas`, {
30
+ method: 'POST',
31
+ body: JSON.stringify({ persona: key }),
32
+ });
33
+ console.log(JSON.stringify(data, null, 2));
34
+ }
35
+ async function unassignPersona(key, userId, opts) {
36
+ const data = await (0, client_1.apiFetch)(`/users/${encodeURIComponent(userId)}/personas/${encodeURIComponent(key)}`, { method: 'DELETE' });
37
+ console.log(JSON.stringify(data, null, 2));
38
+ }
39
+ async function getUserPersonas(userId, opts) {
40
+ const data = await (0, client_1.apiFetch)(`/users/${encodeURIComponent(userId)}/personas`);
41
+ console.log(JSON.stringify(data, null, 2));
42
+ }
@@ -0,0 +1,53 @@
1
+ -- Migration 024: Personas — named role bundles with per-role relationship scope
2
+ --
3
+ -- A persona is a suggestion, the same way a default pin is: shorthand for "add
4
+ -- this user to these roles with these scoped privileges." Assigning a persona
5
+ -- fans out to ordinary lt_user_roles memberships (one per linked role, mapped
6
+ -- from the persona's relationship onto the read/write scope lattice), so
7
+ -- lt_user_roles remains the single source of authorization truth — no second
8
+ -- ACL path, no hot-path changes.
9
+ --
10
+ -- lt_personas — the bundle: stable key, display title, description.
11
+ -- lt_persona_roles — the bundle's role links; relationship maps onto the
12
+ -- membership scope lattice: write-all → (all, all),
13
+ -- write-self → (all, self), read-all → (all, none).
14
+ -- lt_user_personas — who holds which persona (the auditable "why").
15
+ -- lt_user_roles.granted_by_persona — provenance: NULL means the membership was
16
+ -- granted directly; non-NULL names the persona currently
17
+ -- sustaining the row. Unassigning a persona removes only
18
+ -- rows it sustains (re-homing rows another held persona
19
+ -- still grants); direct grants are never touched, and a
20
+ -- direct grant on a persona-sustained role takes the row
21
+ -- over (provenance flips to NULL).
22
+
23
+ CREATE TABLE IF NOT EXISTS lt_personas (
24
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
25
+ key TEXT NOT NULL UNIQUE,
26
+ title TEXT,
27
+ description TEXT,
28
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
29
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
30
+ );
31
+
32
+ CREATE TABLE IF NOT EXISTS lt_persona_roles (
33
+ persona_id UUID NOT NULL REFERENCES lt_personas(id) ON DELETE CASCADE,
34
+ role TEXT NOT NULL REFERENCES lt_roles(role) ON DELETE CASCADE,
35
+ relationship TEXT NOT NULL CHECK (relationship IN ('write-all', 'write-self', 'read-all')),
36
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
37
+ PRIMARY KEY (persona_id, role)
38
+ );
39
+
40
+ CREATE TABLE IF NOT EXISTS lt_user_personas (
41
+ user_id UUID NOT NULL REFERENCES lt_users(id) ON DELETE CASCADE,
42
+ persona_id UUID NOT NULL REFERENCES lt_personas(id) ON DELETE CASCADE,
43
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
44
+ PRIMARY KEY (user_id, persona_id)
45
+ );
46
+
47
+ ALTER TABLE lt_user_roles
48
+ ADD COLUMN IF NOT EXISTS granted_by_persona UUID REFERENCES lt_personas(id) ON DELETE SET NULL;
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_lt_persona_roles_role ON lt_persona_roles (role);
51
+ CREATE INDEX IF NOT EXISTS idx_lt_user_personas_persona ON lt_user_personas (persona_id);
52
+ CREATE INDEX IF NOT EXISTS idx_lt_user_roles_granted_by_persona
53
+ ON lt_user_roles (granted_by_persona) WHERE granted_by_persona IS NOT NULL;
@@ -10,4 +10,14 @@
10
10
  * - `app.epic.apis.createorder.error` matches `app.epic.>`
11
11
  * - `app.epic.apis.createorder.error` does NOT match `app.vendor.>`
12
12
  */
13
+ /**
14
+ * Make a value safe to embed as ONE token of a dot-delimited subject.
15
+ *
16
+ * Dots would splinter the token into extra subject levels; `*`, `>`, spaces,
17
+ * and other non-token characters would corrupt pattern matching (and are
18
+ * illegal in NATS subjects). Each run of unsafe characters collapses to a
19
+ * single `-`. An empty or missing value yields `none` so the subject always
20
+ * keeps its arity.
21
+ */
22
+ export declare function sanitizeSubjectToken(value: string | null | undefined): string;
13
23
  export declare function subjectMatchesPattern(subject: string, pattern: string): boolean;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitizeSubjectToken = sanitizeSubjectToken;
3
4
  exports.subjectMatchesPattern = subjectMatchesPattern;
4
5
  /**
5
6
  * Match a dot-delimited subject against a pattern with NATS-style wildcards.
@@ -13,6 +14,19 @@ exports.subjectMatchesPattern = subjectMatchesPattern;
13
14
  * - `app.epic.apis.createorder.error` matches `app.epic.>`
14
15
  * - `app.epic.apis.createorder.error` does NOT match `app.vendor.>`
15
16
  */
17
+ /**
18
+ * Make a value safe to embed as ONE token of a dot-delimited subject.
19
+ *
20
+ * Dots would splinter the token into extra subject levels; `*`, `>`, spaces,
21
+ * and other non-token characters would corrupt pattern matching (and are
22
+ * illegal in NATS subjects). Each run of unsafe characters collapses to a
23
+ * single `-`. An empty or missing value yields `none` so the subject always
24
+ * keeps its arity.
25
+ */
26
+ function sanitizeSubjectToken(value) {
27
+ const cleaned = (value ?? '').replace(/[^A-Za-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
28
+ return cleaned || 'none';
29
+ }
16
30
  function subjectMatchesPattern(subject, pattern) {
17
31
  if (pattern === '*')
18
32
  return true;
@@ -32,16 +32,22 @@ export declare function publishTaskEvent(params: {
32
32
  }): Promise<void>;
33
33
  /**
34
34
  * Publish an escalation lifecycle event.
35
- * Subject: system.escalation.{escalationId}.{action}
35
+ * Subject: system.escalation.{role}.{escalationId}.{action}
36
+ *
37
+ * The role token makes the queue the organizing level of the hierarchy:
38
+ * subscribers scope to one role (`system.escalation.{role}.>`), one verb
39
+ * across roles (`system.escalation.*.*.created`), or one item regardless of
40
+ * role hops (`system.escalation.*.{id}.>`).
36
41
  */
37
42
  export declare function publishEscalationEvent(params: {
38
- type: 'escalation.created' | 'escalation.resolved' | 'escalation.claimed' | 'escalation.released' | 'escalation.cancelled';
43
+ type: 'escalation.created' | 'escalation.resolved' | 'escalation.claimed' | 'escalation.released' | 'escalation.cancelled' | 'escalation.reassigned';
39
44
  source: string;
40
45
  workflowId: string;
41
46
  workflowName: string;
42
47
  taskQueue: string;
43
48
  taskId?: string;
44
49
  escalationId: string;
50
+ role: string;
45
51
  originId?: string;
46
52
  status: string;
47
53
  data?: Record<string, any>;
@@ -9,6 +9,7 @@ exports.publishFileEvent = publishFileEvent;
9
9
  exports.publishAgentEvent = publishAgentEvent;
10
10
  exports.publishWorkflowEvent = publishWorkflowEvent;
11
11
  const index_1 = require("./index");
12
+ const matching_1 = require("./matching");
12
13
  const logger_1 = require("../logger");
13
14
  /**
14
15
  * Fire-and-forget publish helper. Swallows errors (best-effort).
@@ -62,13 +63,19 @@ function publishTaskEvent(params) {
62
63
  }
63
64
  /**
64
65
  * Publish an escalation lifecycle event.
65
- * Subject: system.escalation.{escalationId}.{action}
66
+ * Subject: system.escalation.{role}.{escalationId}.{action}
67
+ *
68
+ * The role token makes the queue the organizing level of the hierarchy:
69
+ * subscribers scope to one role (`system.escalation.{role}.>`), one verb
70
+ * across roles (`system.escalation.*.*.created`), or one item regardless of
71
+ * role hops (`system.escalation.*.{id}.>`).
66
72
  */
67
73
  function publishEscalationEvent(params) {
68
74
  const action = params.type.split('.')[1];
69
75
  return fireAndForget({
70
- type: `system.escalation.${params.escalationId}.${action}`,
76
+ type: `system.escalation.${(0, matching_1.sanitizeSubjectToken)(params.role)}.${params.escalationId}.${action}`,
71
77
  source: params.source,
78
+ role: params.role,
72
79
  workflowId: params.workflowId,
73
80
  workflowName: params.workflowName,
74
81
  taskQueue: params.taskQueue,
@@ -8,8 +8,14 @@ export type SocketIOAuthenticator = (token: string) => boolean | Promise<boolean
8
8
  /**
9
9
  * Socket.IO event adapter for browser clients.
10
10
  *
11
- * Publishes LTEvent payloads to all connected Socket.IO clients
12
- * on channels following the pattern: `lt.events.{event.type}`
11
+ * Publishes LTEvent payloads to connected Socket.IO clients on channels
12
+ * following the pattern: `lt.events.{event.type}`.
13
+ *
14
+ * Delivery is scoped per socket: a client registers NATS-style subject
15
+ * patterns with `lt.subscribe` / `lt.unsubscribe` messages and receives only
16
+ * matching events — the server filters, the wire carries only what the page
17
+ * asked for. A socket that never registers a pattern receives every event
18
+ * (the broadcast contract external consumers may rely on).
13
19
  *
14
20
  * The HTTP server must be attached via `attachServer()` before
15
21
  * `connect()` is called. The startup flow handles this automatically
@@ -3,11 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SocketIOEventAdapter = void 0;
4
4
  const socket_io_1 = require("socket.io");
5
5
  const logger_1 = require("../logger");
6
+ const matching_1 = require("./matching");
6
7
  /**
7
8
  * Socket.IO event adapter for browser clients.
8
9
  *
9
- * Publishes LTEvent payloads to all connected Socket.IO clients
10
- * on channels following the pattern: `lt.events.{event.type}`
10
+ * Publishes LTEvent payloads to connected Socket.IO clients on channels
11
+ * following the pattern: `lt.events.{event.type}`.
12
+ *
13
+ * Delivery is scoped per socket: a client registers NATS-style subject
14
+ * patterns with `lt.subscribe` / `lt.unsubscribe` messages and receives only
15
+ * matching events — the server filters, the wire carries only what the page
16
+ * asked for. A socket that never registers a pattern receives every event
17
+ * (the broadcast contract external consumers may rely on).
11
18
  *
12
19
  * The HTTP server must be attached via `attachServer()` before
13
20
  * `connect()` is called. The startup flow handles this automatically
@@ -75,6 +82,19 @@ class SocketIOEventAdapter {
75
82
  }
76
83
  this.io.on('connection', (socket) => {
77
84
  logger_1.loggerRegistry.info(`[lt-events:socketio] client connected (${socket.id})`);
85
+ // Per-socket subject-pattern scope. Registering the first pattern
86
+ // switches the socket from broadcast to scoped delivery.
87
+ const patterns = new Set();
88
+ socket.data.ltPatterns = patterns;
89
+ socket.on('lt.subscribe', (pattern) => {
90
+ if (typeof pattern === 'string' && pattern.length > 0 && pattern.length <= 256) {
91
+ patterns.add(pattern);
92
+ }
93
+ });
94
+ socket.on('lt.unsubscribe', (pattern) => {
95
+ if (typeof pattern === 'string')
96
+ patterns.delete(pattern);
97
+ });
78
98
  socket.on('disconnect', () => {
79
99
  logger_1.loggerRegistry.debug(`[lt-events:socketio] client disconnected (${socket.id})`);
80
100
  });
@@ -85,7 +105,20 @@ class SocketIOEventAdapter {
85
105
  if (!this.io)
86
106
  return;
87
107
  const channel = `lt.events.${event.type}`;
88
- this.io.emit(channel, event);
108
+ for (const socket of this.io.of('/').sockets.values()) {
109
+ const patterns = socket.data.ltPatterns;
110
+ if (!patterns || patterns.size === 0) {
111
+ // Legacy scope: a socket with no registered patterns gets everything.
112
+ socket.emit(channel, event);
113
+ continue;
114
+ }
115
+ for (const pattern of patterns) {
116
+ if ((0, matching_1.subjectMatchesPattern)(channel, pattern)) {
117
+ socket.emit(channel, event);
118
+ break;
119
+ }
120
+ }
121
+ }
89
122
  }
90
123
  async disconnect() {
91
124
  if (this.io) {
@@ -4,6 +4,7 @@ exports.systemEventsConfig = void 0;
4
4
  exports.mapSystemEvent = mapSystemEvent;
5
5
  exports.onSystemEvent = onSystemEvent;
6
6
  const index_1 = require("./index");
7
+ const matching_1 = require("./matching");
7
8
  /** Verb → long-tail event status, matching the manual publishEscalationEvent convention. */
8
9
  const ESCALATION_STATUS_BY_VERB = {
9
10
  created: 'pending',
@@ -27,9 +28,16 @@ function mapSystemEvent(event) {
27
28
  if (domain === 'escalation') {
28
29
  const row = (event.data ?? {});
29
30
  const verb = segments[3] ?? '';
31
+ // The SDK forms `system.escalation.{id}.{verb}`; long-tail's canonical
32
+ // subject carries the role as the organizing token. The committed row
33
+ // rides in `data`, so the role is lifted from it and the subject is
34
+ // rewritten to `system.escalation.{role}.{id}.{verb}` — the same shape
35
+ // publishEscalationEvent produces for the service-mediated path.
36
+ const role = row.role || undefined;
30
37
  return {
31
- type: event.type,
38
+ type: `system.escalation.${(0, matching_1.sanitizeSubjectToken)(role)}.${segments[2]}.${verb}`,
32
39
  source: 'sdk',
40
+ role,
33
41
  workflowId: row.workflow_id || event.workflow_id || undefined,
34
42
  workflowName: row.workflow_type || undefined,
35
43
  taskQueue: row.task_queue || undefined,
@@ -16,6 +16,7 @@ const exports_1 = __importDefault(require("./exports"));
16
16
  const users_1 = __importDefault(require("./users"));
17
17
  const me_1 = __importDefault(require("./me"));
18
18
  const roles_1 = __importDefault(require("./roles"));
19
+ const personas_1 = __importDefault(require("./personas"));
19
20
  const dba_1 = __importDefault(require("./dba"));
20
21
  const maintenance_1 = __importDefault(require("./maintenance"));
21
22
  const mcp_1 = __importDefault(require("./mcp"));
@@ -54,6 +55,7 @@ router.use('/config/maintenance', maintenance_1.default);
54
55
  router.use('/users', users_1.default);
55
56
  router.use('/me', me_1.default);
56
57
  router.use('/roles', roles_1.default);
58
+ router.use('/personas', personas_1.default);
57
59
  router.use('/dba', dba_1.default);
58
60
  router.use('/mcp', mcp_1.default);
59
61
  router.use('/insight', insight_1.default);
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
@@ -0,0 +1,118 @@
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
+ const express_1 = require("express");
37
+ const auth_1 = require("../modules/auth");
38
+ const api = __importStar(require("../api/personas"));
39
+ const router = (0, express_1.Router)();
40
+ // Personas are role bundles — a management surface. Reads and writes share the
41
+ // role-management gate (admin type, superadmin, engineer), the same audience
42
+ // that manages roles and users.
43
+ router.use(auth_1.requireRoleManager);
44
+ /**
45
+ * GET /api/personas
46
+ * List all personas with role links and holder counts.
47
+ */
48
+ router.get('/', async (_req, res) => {
49
+ const result = await api.listPersonas();
50
+ res.status(result.status).json(result.data ?? { error: result.error });
51
+ });
52
+ /**
53
+ * POST /api/personas
54
+ * Create a persona.
55
+ * Body: { key, title?, description? }
56
+ */
57
+ router.post('/', async (req, res) => {
58
+ const result = await api.createPersona(req.body || {});
59
+ res.status(result.status).json(result.data ?? { error: result.error });
60
+ });
61
+ /**
62
+ * POST /api/personas/seed
63
+ * Declarative, idempotent seed — upsert personas, sync role links, reconcile holders.
64
+ * Body: { personas: [{ key, title?, description?, roles: [{ role, relationship }] }] }
65
+ */
66
+ router.post('/seed', async (req, res) => {
67
+ const result = await api.seedPersonas(req.body || {});
68
+ res.status(result.status).json(result.data ?? { error: result.error });
69
+ });
70
+ /**
71
+ * GET /api/personas/:key
72
+ * Get one persona with role links and assignees.
73
+ */
74
+ router.get('/:key', async (req, res) => {
75
+ const result = await api.getPersona({ key: req.params.key });
76
+ res.status(result.status).json(result.data ?? { error: result.error });
77
+ });
78
+ /**
79
+ * PATCH /api/personas/:key
80
+ * Update title/description (PATCH semantics; null clears).
81
+ */
82
+ router.patch('/:key', async (req, res) => {
83
+ const result = await api.updatePersona({ key: req.params.key, ...(req.body || {}) });
84
+ res.status(result.status).json(result.data ?? { error: result.error });
85
+ });
86
+ /**
87
+ * DELETE /api/personas/:key
88
+ * Delete a persona. Sustained memberships are removed or re-homed; direct grants untouched.
89
+ */
90
+ router.delete('/:key', async (req, res) => {
91
+ const result = await api.deletePersona({ key: req.params.key });
92
+ res.status(result.status).json(result.data ?? { error: result.error });
93
+ });
94
+ /**
95
+ * PUT /api/personas/:key/roles/:role
96
+ * Link a role (or change its relationship).
97
+ * Body: { relationship: 'write-all' | 'write-self' | 'read-all' } ('write-none' = read-all)
98
+ */
99
+ router.put('/:key/roles/:role', async (req, res) => {
100
+ const result = await api.linkPersonaRole({
101
+ key: req.params.key,
102
+ role: req.params.role,
103
+ relationship: (req.body || {}).relationship,
104
+ });
105
+ res.status(result.status).json(result.data ?? { error: result.error });
106
+ });
107
+ /**
108
+ * DELETE /api/personas/:key/roles/:role
109
+ * Unlink a role from a persona.
110
+ */
111
+ router.delete('/:key/roles/:role', async (req, res) => {
112
+ const result = await api.unlinkPersonaRole({
113
+ key: req.params.key,
114
+ role: req.params.role,
115
+ });
116
+ res.status(result.status).json(result.data ?? { error: result.error });
117
+ });
118
+ exports.default = router;
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const express_1 = require("express");
37
37
  const auth_1 = require("../modules/auth");
38
38
  const api = __importStar(require("../api/users"));
39
+ const personasApi = __importStar(require("../api/personas"));
39
40
  const router = (0, express_1.Router)();
40
41
  // ── User CRUD ─────────────────────────────────────────────────────────────────
41
42
  /**
@@ -144,4 +145,38 @@ router.delete('/:id/roles/:role', auth_1.requireAdmin, async (req, res) => {
144
145
  const result = await api.removeUserRole({ id: req.params.id, role: req.params.role });
145
146
  res.status(result.status).json(result.data ?? { error: result.error });
146
147
  });
148
+ // ── Persona assignment ───────────────────────────────────────────────────────
149
+ // A persona assignment is shorthand for scoped role memberships, so the gate is
150
+ // the persona-management gate (admin type, superadmin, engineer).
151
+ /**
152
+ * GET /api/users/:id/personas
153
+ * The personas a user holds plus the composed role/scope map.
154
+ */
155
+ router.get('/:id/personas', async (req, res) => {
156
+ const result = await personasApi.getUserPersonas({ id: req.params.id });
157
+ res.status(result.status).json(result.data ?? { error: result.error });
158
+ });
159
+ /**
160
+ * POST /api/users/:id/personas
161
+ * Assign a persona to a user (idempotent; re-assigning overlays fresh).
162
+ * Body: { persona: '<key>' }
163
+ */
164
+ router.post('/:id/personas', auth_1.requireRoleManager, async (req, res) => {
165
+ const result = await personasApi.assignPersona({
166
+ id: req.params.id,
167
+ key: (req.body || {}).persona,
168
+ });
169
+ res.status(result.status).json(result.data ?? { error: result.error });
170
+ });
171
+ /**
172
+ * DELETE /api/users/:id/personas/:key
173
+ * Unassign a persona — removes only memberships the persona sustains.
174
+ */
175
+ router.delete('/:id/personas/:key', auth_1.requireRoleManager, async (req, res) => {
176
+ const result = await personasApi.unassignPersona({
177
+ id: req.params.id,
178
+ key: req.params.key,
179
+ });
180
+ res.status(result.status).json(result.data ?? { error: result.error });
181
+ });
147
182
  exports.default = router;
@@ -4,6 +4,7 @@ import * as workflowsApi from '../api/workflows';
4
4
  import * as yamlWorkflowsApi from '../api/yaml-workflows';
5
5
  import * as usersApi from '../api/users';
6
6
  import * as rolesApi from '../api/roles';
7
+ import * as personasApi from '../api/personas';
7
8
  import * as authApi from '../api/auth';
8
9
  import * as mcpApi from '../api/mcp';
9
10
  import * as pipelinesApi from '../api/pipelines';
@@ -299,6 +300,20 @@ export declare function createClient(options?: LTClientOptions): {
299
300
  getEscalationTargets: typeof rolesApi.getEscalationTargets;
300
301
  replaceEscalationTargets: typeof rolesApi.replaceEscalationTargets;
301
302
  };
303
+ personas: {
304
+ list: typeof personasApi.listPersonas;
305
+ get: typeof personasApi.getPersona;
306
+ create: typeof personasApi.createPersona;
307
+ update: typeof personasApi.updatePersona;
308
+ delete: typeof personasApi.deletePersona;
309
+ linkRole: typeof personasApi.linkPersonaRole;
310
+ unlinkRole: typeof personasApi.unlinkPersonaRole;
311
+ assign: typeof personasApi.assignPersona;
312
+ unassign: typeof personasApi.unassignPersona;
313
+ forUser: typeof personasApi.getUserPersonas;
314
+ /** Declarative, idempotent seed — the static-config twin of the API surface. */
315
+ seed: (personas: Parameters<typeof personasApi.seedPersonas>[0]["personas"]) => Promise<LTApiResult<any>>;
316
+ };
302
317
  auth: {
303
318
  login: typeof authApi.login;
304
319
  };
@@ -42,6 +42,7 @@ const yamlWorkflowsApi = __importStar(require("../api/yaml-workflows"));
42
42
  const usersApi = __importStar(require("../api/users"));
43
43
  const meApi = __importStar(require("../api/me"));
44
44
  const rolesApi = __importStar(require("../api/roles"));
45
+ const personasApi = __importStar(require("../api/personas"));
45
46
  const authApi = __importStar(require("../api/auth"));
46
47
  const mcpApi = __importStar(require("../api/mcp"));
47
48
  const pipelinesApi = __importStar(require("../api/pipelines"));
@@ -217,6 +218,21 @@ function createClient(options = {}) {
217
218
  getEscalationTargets: rolesApi.getEscalationTargets,
218
219
  replaceEscalationTargets: rolesApi.replaceEscalationTargets,
219
220
  },
221
+ // ── Personas — role bundles with per-role relationship scope ───────────
222
+ personas: {
223
+ list: personasApi.listPersonas,
224
+ get: personasApi.getPersona,
225
+ create: personasApi.createPersona,
226
+ update: personasApi.updatePersona,
227
+ delete: personasApi.deletePersona,
228
+ linkRole: personasApi.linkPersonaRole,
229
+ unlinkRole: personasApi.unlinkPersonaRole,
230
+ assign: personasApi.assignPersona,
231
+ unassign: personasApi.unassignPersona,
232
+ forUser: personasApi.getUserPersonas,
233
+ /** Declarative, idempotent seed — the static-config twin of the API surface. */
234
+ seed: (personas) => personasApi.seedPersonas({ personas }),
235
+ },
220
236
  // ── Auth ───────────────────────────────────────────────────────────────
221
237
  auth: {
222
238
  login: authApi.login,