@hotmeshio/long-tail 0.13.1 → 0.14.1

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 (248) hide show
  1. package/build/api/announcements.d.ts +22 -0
  2. package/build/api/announcements.js +96 -0
  3. package/build/api/escalations/claim.d.ts +4 -1
  4. package/build/api/escalations/claim.js +6 -2
  5. package/build/api/escalations/list.d.ts +8 -0
  6. package/build/api/escalations/list.js +14 -4
  7. package/build/api/index.d.ts +1 -0
  8. package/build/api/index.js +2 -1
  9. package/build/api/workflows/config.d.ts +1 -0
  10. package/build/api/workflows/config.js +1 -0
  11. package/build/api/workflows/discovery.js +1 -0
  12. package/build/index.js +4 -0
  13. package/build/lib/db/schemas/031_announcements.sql +30 -0
  14. package/build/lib/db/schemas/032_workflow_read_safe.sql +9 -0
  15. package/build/lib/events/publish.d.ts +15 -0
  16. package/build/lib/events/publish.js +22 -0
  17. package/build/routes/announcements.d.ts +2 -0
  18. package/build/routes/announcements.js +64 -0
  19. package/build/routes/escalations/list.js +2 -0
  20. package/build/routes/escalations/single.js +3 -1
  21. package/build/routes/index.js +2 -0
  22. package/build/sdk/index.d.ts +1 -0
  23. package/build/services/announcement/index.d.ts +30 -0
  24. package/build/services/announcement/index.js +29 -0
  25. package/build/services/announcement/sql.d.ts +8 -0
  26. package/build/services/announcement/sql.js +24 -0
  27. package/build/services/config/cache.js +1 -0
  28. package/build/services/config/read.js +2 -0
  29. package/build/services/config/sql.d.ts +2 -2
  30. package/build/services/config/sql.js +6 -5
  31. package/build/services/config/write.js +5 -0
  32. package/build/services/escalation/crud.d.ts +10 -2
  33. package/build/services/escalation/crud.js +20 -12
  34. package/build/services/topics/system-topics.js +20 -0
  35. package/build/shared/form-validation/index.d.ts +1 -0
  36. package/build/shared/form-validation/index.js +1 -0
  37. package/build/shared/form-validation/validate-resolver-payload.d.ts +3 -0
  38. package/build/shared/form-validation/validate-resolver-payload.js +19 -0
  39. package/build/shared/form-validation/x-lt-labels.d.ts +17 -6
  40. package/build/shared/form-validation/x-lt-labels.js +12 -4
  41. package/build/shared/form-validation/x-lt-require-any.d.ts +22 -0
  42. package/build/shared/form-validation/x-lt-require-any.js +41 -0
  43. package/build/start/workers.js +3 -5
  44. package/build/system/mcp-servers/admin/announcements.d.ts +7 -0
  45. package/build/system/mcp-servers/admin/announcements.js +69 -0
  46. package/build/system/mcp-servers/admin/index.js +5 -3
  47. package/build/system/mcp-servers/admin/workflows.js +45 -0
  48. package/build/system/seed/tool-manifests-admin.d.ts +357 -0
  49. package/build/system/seed/tool-manifests-admin.js +3 -0
  50. package/build/tsconfig.tsbuildinfo +1 -1
  51. package/build/types/config.d.ts +8 -0
  52. package/build/types/startup.d.ts +5 -0
  53. package/dashboard/dist/assets/{AdminDashboard-D2unnS2b.js → AdminDashboard-C4h1R-lz.js} +2 -2
  54. package/dashboard/dist/assets/{AdminDashboard-D2unnS2b.js.map → AdminDashboard-C4h1R-lz.js.map} +1 -1
  55. package/dashboard/dist/assets/{AgentConfigPage-CBkf403g.js → AgentConfigPage-EWC8VQ7R.js} +2 -2
  56. package/dashboard/dist/assets/{AgentConfigPage-CBkf403g.js.map → AgentConfigPage-EWC8VQ7R.js.map} +1 -1
  57. package/dashboard/dist/assets/{AgentDetailPage-CAIU3yzo.js → AgentDetailPage-DaLfa80d.js} +2 -2
  58. package/dashboard/dist/assets/{AgentDetailPage-CAIU3yzo.js.map → AgentDetailPage-DaLfa80d.js.map} +1 -1
  59. package/dashboard/dist/assets/{AgentsPage-qP9fWMyT.js → AgentsPage-islj_zrh.js} +2 -2
  60. package/dashboard/dist/assets/{AgentsPage-qP9fWMyT.js.map → AgentsPage-islj_zrh.js.map} +1 -1
  61. package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js +2 -0
  62. package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js.map +1 -0
  63. package/dashboard/dist/assets/{BotPicker-BN-MKITV.js → BotPicker-CnX8xfka.js} +2 -2
  64. package/dashboard/dist/assets/{BotPicker-BN-MKITV.js.map → BotPicker-CnX8xfka.js.map} +1 -1
  65. package/dashboard/dist/assets/{CapabilitiesPage-CJfmWokN.js → CapabilitiesPage-DK7wGMFt.js} +2 -2
  66. package/dashboard/dist/assets/{CapabilitiesPage-CJfmWokN.js.map → CapabilitiesPage-DK7wGMFt.js.map} +1 -1
  67. package/dashboard/dist/assets/{CollapsibleSection-BvMHlHyt.js → CollapsibleSection-WqEpMTyx.js} +2 -2
  68. package/dashboard/dist/assets/{CollapsibleSection-BvMHlHyt.js.map → CollapsibleSection-WqEpMTyx.js.map} +1 -1
  69. package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js +2 -0
  70. package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js.map +1 -0
  71. package/dashboard/dist/assets/{CredentialsPage-2TvvRwGJ.js → CredentialsPage-CfT60FiU.js} +2 -2
  72. package/dashboard/dist/assets/{CredentialsPage-2TvvRwGJ.js.map → CredentialsPage-CfT60FiU.js.map} +1 -1
  73. package/dashboard/dist/assets/{CronLabel-HxmsDSnV.js → CronLabel-ds7dLz6S.js} +2 -2
  74. package/dashboard/dist/assets/{CronLabel-HxmsDSnV.js.map → CronLabel-ds7dLz6S.js.map} +1 -1
  75. package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js +2 -0
  76. package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js.map +1 -0
  77. package/dashboard/dist/assets/{ElapsedCell-BkRu9Xpd.js → ElapsedCell-DRQhFky_.js} +2 -2
  78. package/dashboard/dist/assets/{ElapsedCell-BkRu9Xpd.js.map → ElapsedCell-DRQhFky_.js.map} +1 -1
  79. package/dashboard/dist/assets/{EntityTimelinePanel--E6hLMCM.js → EntityTimelinePanel-nCgWdmpK.js} +2 -2
  80. package/dashboard/dist/assets/{EntityTimelinePanel--E6hLMCM.js.map → EntityTimelinePanel-nCgWdmpK.js.map} +1 -1
  81. package/dashboard/dist/assets/{EscalationListSchemaPage-CdFtqEEX.js → EscalationListSchemaPage-DBCnPMG9.js} +2 -2
  82. package/dashboard/dist/assets/{EscalationListSchemaPage-CdFtqEEX.js.map → EscalationListSchemaPage-DBCnPMG9.js.map} +1 -1
  83. package/dashboard/dist/assets/{EscalationSchemaPage-BsjS2axz.js → EscalationSchemaPage-DfzRTqhV.js} +2 -2
  84. package/dashboard/dist/assets/{EscalationSchemaPage-BsjS2axz.js.map → EscalationSchemaPage-DfzRTqhV.js.map} +1 -1
  85. package/dashboard/dist/assets/{EscalationsOverview-FL-xteVc.js → EscalationsOverview-CWd2Ivso.js} +2 -2
  86. package/dashboard/dist/assets/{EscalationsOverview-FL-xteVc.js.map → EscalationsOverview-CWd2Ivso.js.map} +1 -1
  87. package/dashboard/dist/assets/{EventTable-BOcgZ78i.js → EventTable-Dm9Fbab1.js} +2 -2
  88. package/dashboard/dist/assets/{EventTable-BOcgZ78i.js.map → EventTable-Dm9Fbab1.js.map} +1 -1
  89. package/dashboard/dist/assets/{FilterBar-DfCiCmm-.js → FilterBar-DR4cJvTB.js} +2 -2
  90. package/dashboard/dist/assets/{FilterBar-DfCiCmm-.js.map → FilterBar-DR4cJvTB.js.map} +1 -1
  91. package/dashboard/dist/assets/{GraphInvokePage-DfVeiN-8.js → GraphInvokePage-DQt64Ru0.js} +2 -2
  92. package/dashboard/dist/assets/{GraphInvokePage-DfVeiN-8.js.map → GraphInvokePage-DQt64Ru0.js.map} +1 -1
  93. package/dashboard/dist/assets/{HomePage-C2IhF9WB.js → HomePage-D7qNiqtw.js} +2 -2
  94. package/dashboard/dist/assets/{HomePage-C2IhF9WB.js.map → HomePage-D7qNiqtw.js.map} +1 -1
  95. package/dashboard/dist/assets/{ListToolbar-DA0PTOl5.js → ListToolbar-BdZkpRMo.js} +2 -2
  96. package/dashboard/dist/assets/{ListToolbar-DA0PTOl5.js.map → ListToolbar-BdZkpRMo.js.map} +1 -1
  97. package/dashboard/dist/assets/{McpOverview-DstPch5M.js → McpOverview-DHAEYY1b.js} +2 -2
  98. package/dashboard/dist/assets/{McpOverview-DstPch5M.js.map → McpOverview-DHAEYY1b.js.map} +1 -1
  99. package/dashboard/dist/assets/{McpQueryDetailPage-Csv0PKE0.js → McpQueryDetailPage-BfGhRO_c.js} +2 -2
  100. package/dashboard/dist/assets/{McpQueryDetailPage-Csv0PKE0.js.map → McpQueryDetailPage-BfGhRO_c.js.map} +1 -1
  101. package/dashboard/dist/assets/{McpQueryPage-DxmqCkly.js → McpQueryPage-3EXLX1Eq.js} +2 -2
  102. package/dashboard/dist/assets/{McpQueryPage-DxmqCkly.js.map → McpQueryPage-3EXLX1Eq.js.map} +1 -1
  103. package/dashboard/dist/assets/{McpRunDetailPage-CcJOlp_B.js → McpRunDetailPage-DHI0F65P.js} +2 -2
  104. package/dashboard/dist/assets/{McpRunDetailPage-CcJOlp_B.js.map → McpRunDetailPage-DHI0F65P.js.map} +1 -1
  105. package/dashboard/dist/assets/{McpRunsPage-BZCR043j.js → McpRunsPage-C6-KpYCY.js} +2 -2
  106. package/dashboard/dist/assets/{McpRunsPage-BZCR043j.js.map → McpRunsPage-C6-KpYCY.js.map} +1 -1
  107. package/dashboard/dist/assets/{OperationsPage-DMsPXITh.js → OperationsPage-BNW7uris.js} +2 -2
  108. package/dashboard/dist/assets/{OperationsPage-DMsPXITh.js.map → OperationsPage-BNW7uris.js.map} +1 -1
  109. package/dashboard/dist/assets/{OperatorDashboard-DSloftQ5.js → OperatorDashboard-DLp9gCTA.js} +2 -2
  110. package/dashboard/dist/assets/{OperatorDashboard-DSloftQ5.js.map → OperatorDashboard-DLp9gCTA.js.map} +1 -1
  111. package/dashboard/dist/assets/{PersonaDetailPage-jDVRCLbU.js → PersonaDetailPage-DFv4Zwmq.js} +2 -2
  112. package/dashboard/dist/assets/{PersonaDetailPage-jDVRCLbU.js.map → PersonaDetailPage-DFv4Zwmq.js.map} +1 -1
  113. package/dashboard/dist/assets/{PersonasPage-DnDDwXoy.js → PersonasPage-C52o87Zv.js} +2 -2
  114. package/dashboard/dist/assets/{PersonasPage-DnDDwXoy.js.map → PersonasPage-C52o87Zv.js.map} +1 -1
  115. package/dashboard/dist/assets/{ProcessDetailPage-CfAUU6q2.js → ProcessDetailPage-CKCxXogl.js} +2 -2
  116. package/dashboard/dist/assets/{ProcessDetailPage-CfAUU6q2.js.map → ProcessDetailPage-CKCxXogl.js.map} +1 -1
  117. package/dashboard/dist/assets/{ProcessesListPage-CnAXzaVv.js → ProcessesListPage-D1bxIy7-.js} +2 -2
  118. package/dashboard/dist/assets/{ProcessesListPage-CnAXzaVv.js.map → ProcessesListPage-D1bxIy7-.js.map} +1 -1
  119. package/dashboard/dist/assets/{RoleDetailPage-Dg1p6Qz_.js → RoleDetailPage-_MrbOGW_.js} +2 -2
  120. package/dashboard/dist/assets/{RoleDetailPage-Dg1p6Qz_.js.map → RoleDetailPage-_MrbOGW_.js.map} +1 -1
  121. package/dashboard/dist/assets/{RolesPage-DeRVQux8.js → RolesPage-ZVCkB4iF.js} +2 -2
  122. package/dashboard/dist/assets/{RolesPage-DeRVQux8.js.map → RolesPage-ZVCkB4iF.js.map} +1 -1
  123. package/dashboard/dist/assets/{RunAsSelector-BFNqQGuG.js → RunAsSelector-BAqa1Tya.js} +2 -2
  124. package/dashboard/dist/assets/{RunAsSelector-BFNqQGuG.js.map → RunAsSelector-BAqa1Tya.js.map} +1 -1
  125. package/dashboard/dist/assets/{ScanCodesPage-D0GOdk5m.js → ScanCodesPage-b7WkFiy-.js} +2 -2
  126. package/dashboard/dist/assets/{ScanCodesPage-D0GOdk5m.js.map → ScanCodesPage-b7WkFiy-.js.map} +1 -1
  127. package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js +2 -0
  128. package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js.map +1 -0
  129. package/dashboard/dist/assets/ScanStationPage-CPC9CdCR.js +2 -0
  130. package/dashboard/dist/assets/ScanStationPage-CPC9CdCR.js.map +1 -0
  131. package/dashboard/dist/assets/{StickyPagination-B99hVu95.js → StickyPagination-CgSzarlP.js} +2 -2
  132. package/dashboard/dist/assets/{StickyPagination-B99hVu95.js.map → StickyPagination-CgSzarlP.js.map} +1 -1
  133. package/dashboard/dist/assets/{StreamMessageDetail-DcDGISrv.js → StreamMessageDetail-B4E3S5RB.js} +2 -2
  134. package/dashboard/dist/assets/{StreamMessageDetail-DcDGISrv.js.map → StreamMessageDetail-B4E3S5RB.js.map} +1 -1
  135. package/dashboard/dist/assets/{SwimlaneTimeline-BP3mSQAg.js → SwimlaneTimeline-BkcjucMZ.js} +2 -2
  136. package/dashboard/dist/assets/{SwimlaneTimeline-BP3mSQAg.js.map → SwimlaneTimeline-BkcjucMZ.js.map} +1 -1
  137. package/dashboard/dist/assets/{TaskDetailPage-_XWLJzt-.js → TaskDetailPage-D7e8x2gX.js} +2 -2
  138. package/dashboard/dist/assets/{TaskDetailPage-_XWLJzt-.js.map → TaskDetailPage-D7e8x2gX.js.map} +1 -1
  139. package/dashboard/dist/assets/{TasksListPage-iGriKiO2.js → TasksListPage-B4mxP9Ey.js} +2 -2
  140. package/dashboard/dist/assets/{TasksListPage-iGriKiO2.js.map → TasksListPage-B4mxP9Ey.js.map} +1 -1
  141. package/dashboard/dist/assets/{TimeAgo-BO33VeFl.js → TimeAgo-D6sbYsUO.js} +2 -2
  142. package/dashboard/dist/assets/{TimeAgo-BO33VeFl.js.map → TimeAgo-D6sbYsUO.js.map} +1 -1
  143. package/dashboard/dist/assets/{TimestampCell-KAjX7w35.js → TimestampCell-DFDf3NAT.js} +2 -2
  144. package/dashboard/dist/assets/{TimestampCell-KAjX7w35.js.map → TimestampCell-DFDf3NAT.js.map} +1 -1
  145. package/dashboard/dist/assets/{ToolTestPanel-BchG2yC6.js → ToolTestPanel-DbWw0-Le.js} +2 -2
  146. package/dashboard/dist/assets/{ToolTestPanel-BchG2yC6.js.map → ToolTestPanel-DbWw0-Le.js.map} +1 -1
  147. package/dashboard/dist/assets/{TopicDetailPage-BaK8H0o1.js → TopicDetailPage-C6CPcvuO.js} +2 -2
  148. package/dashboard/dist/assets/{TopicDetailPage-BaK8H0o1.js.map → TopicDetailPage-C6CPcvuO.js.map} +1 -1
  149. package/dashboard/dist/assets/{TopicsPage-DEyvm669.js → TopicsPage-C8_XpeT2.js} +2 -2
  150. package/dashboard/dist/assets/{TopicsPage-DEyvm669.js.map → TopicsPage-C8_XpeT2.js.map} +1 -1
  151. package/dashboard/dist/assets/{UserName-BV6SKI9P.js → UserName-CIoJvf_e.js} +2 -2
  152. package/dashboard/dist/assets/{UserName-BV6SKI9P.js.map → UserName-CIoJvf_e.js.map} +1 -1
  153. package/dashboard/dist/assets/{WorkflowExecutionPage-1sKoEFNC.js → WorkflowExecutionPage-Bq3kSkRr.js} +2 -2
  154. package/dashboard/dist/assets/{WorkflowExecutionPage-1sKoEFNC.js.map → WorkflowExecutionPage-Bq3kSkRr.js.map} +1 -1
  155. package/dashboard/dist/assets/{WorkflowsDashboard-YTHDZZOD.js → WorkflowsDashboard-y2L_zwnf.js} +2 -2
  156. package/dashboard/dist/assets/{WorkflowsDashboard-YTHDZZOD.js.map → WorkflowsDashboard-y2L_zwnf.js.map} +1 -1
  157. package/dashboard/dist/assets/{WorkflowsOverview-ucXPLTtm.js → WorkflowsOverview-ChE1Mm3P.js} +2 -2
  158. package/dashboard/dist/assets/{WorkflowsOverview-ucXPLTtm.js.map → WorkflowsOverview-ChE1Mm3P.js.map} +1 -1
  159. package/dashboard/dist/assets/{YamlWorkflowDetailPage-C_RTZKqZ.js → YamlWorkflowDetailPage-D0aY_inb.js} +2 -2
  160. package/dashboard/dist/assets/{YamlWorkflowDetailPage-C_RTZKqZ.js.map → YamlWorkflowDetailPage-D0aY_inb.js.map} +1 -1
  161. package/dashboard/dist/assets/{YamlWorkflowsPage-Usid3w2W.js → YamlWorkflowsPage-DJ0JitPs.js} +2 -2
  162. package/dashboard/dist/assets/{YamlWorkflowsPage-Usid3w2W.js.map → YamlWorkflowsPage-DJ0JitPs.js.map} +1 -1
  163. package/dashboard/dist/assets/{agents-BTDsRK8e.js → agents-Bu5Ly_ER.js} +2 -2
  164. package/dashboard/dist/assets/{agents-BTDsRK8e.js.map → agents-Bu5Ly_ER.js.map} +1 -1
  165. package/dashboard/dist/assets/{bots-DxLrfdfr.js → bots-Cb14wZ1Y.js} +2 -2
  166. package/dashboard/dist/assets/{bots-DxLrfdfr.js.map → bots-Cb14wZ1Y.js.map} +1 -1
  167. package/dashboard/dist/assets/{capabilities-DbTmeW-S.js → capabilities-DeHLk9JJ.js} +2 -2
  168. package/dashboard/dist/assets/{capabilities-DbTmeW-S.js.map → capabilities-DeHLk9JJ.js.map} +1 -1
  169. package/dashboard/dist/assets/{controlplane-CEBntAL4.js → controlplane-YBZ3SbA6.js} +2 -2
  170. package/dashboard/dist/assets/{controlplane-CEBntAL4.js.map → controlplane-YBZ3SbA6.js.map} +1 -1
  171. package/dashboard/dist/assets/{escalation-columns-Carqdwoh.js → escalation-columns-CA9DQlhA.js} +2 -2
  172. package/dashboard/dist/assets/{escalation-columns-Carqdwoh.js.map → escalation-columns-CA9DQlhA.js.map} +1 -1
  173. package/dashboard/dist/assets/{index-BhapT-Vl.js → index-B0qNe7Ux.js} +2 -2
  174. package/dashboard/dist/assets/{index-BhapT-Vl.js.map → index-B0qNe7Ux.js.map} +1 -1
  175. package/dashboard/dist/assets/{index-kes8V4Xw.js → index-B4Nea96C.js} +2 -2
  176. package/dashboard/dist/assets/{index-kes8V4Xw.js.map → index-B4Nea96C.js.map} +1 -1
  177. package/dashboard/dist/assets/{index-cFHoANSG.css → index-B5jxf81r.css} +1 -1
  178. package/dashboard/dist/assets/{index-Bqm4zu46.js → index-B7fE-rND.js} +2 -2
  179. package/dashboard/dist/assets/{index-Bqm4zu46.js.map → index-B7fE-rND.js.map} +1 -1
  180. package/dashboard/dist/assets/{index-nwLh3CK2.js → index-BAKroiNw.js} +2 -2
  181. package/dashboard/dist/assets/{index-nwLh3CK2.js.map → index-BAKroiNw.js.map} +1 -1
  182. package/dashboard/dist/assets/{index-CgIBjZta.js → index-BRmgxeZM.js} +2 -2
  183. package/dashboard/dist/assets/{index-CgIBjZta.js.map → index-BRmgxeZM.js.map} +1 -1
  184. package/dashboard/dist/assets/{index-De8iV1y2.js → index-BaDimDGQ.js} +2 -2
  185. package/dashboard/dist/assets/{index-De8iV1y2.js.map → index-BaDimDGQ.js.map} +1 -1
  186. package/dashboard/dist/assets/{index-CDkg6iOE.js → index-BhurEB5s.js} +2 -2
  187. package/dashboard/dist/assets/{index-CDkg6iOE.js.map → index-BhurEB5s.js.map} +1 -1
  188. package/dashboard/dist/assets/{index-B2hz0pUh.js → index-CQriisJy.js} +2 -2
  189. package/dashboard/dist/assets/{index-B2hz0pUh.js.map → index-CQriisJy.js.map} +1 -1
  190. package/dashboard/dist/assets/{index-B9m7fA3M.js → index-D5MSJsiW.js} +2 -2
  191. package/dashboard/dist/assets/{index-B9m7fA3M.js.map → index-D5MSJsiW.js.map} +1 -1
  192. package/dashboard/dist/assets/{index-DBXm49S6.js → index-Ntul2ZC1.js} +30 -29
  193. package/dashboard/dist/assets/index-Ntul2ZC1.js.map +1 -0
  194. package/dashboard/dist/assets/{index-C0hSttF5.js → index-YUv7aNb4.js} +2 -2
  195. package/dashboard/dist/assets/{index-C0hSttF5.js.map → index-YUv7aNb4.js.map} +1 -1
  196. package/dashboard/dist/assets/{index-CVBBkW8V.js → index-chMUPSOd.js} +2 -2
  197. package/dashboard/dist/assets/{index-CVBBkW8V.js.map → index-chMUPSOd.js.map} +1 -1
  198. package/dashboard/dist/assets/index-uWUJXqGS.js +3 -0
  199. package/dashboard/dist/assets/index-uWUJXqGS.js.map +1 -0
  200. package/dashboard/dist/assets/{knowledge-oFYAanUp.js → knowledge-B1HqYuB2.js} +2 -2
  201. package/dashboard/dist/assets/{knowledge-oFYAanUp.js.map → knowledge-B1HqYuB2.js.map} +1 -1
  202. package/dashboard/dist/assets/{mcp-C9Kw4Ow8.js → mcp-dhihqJpH.js} +2 -2
  203. package/dashboard/dist/assets/{mcp-C9Kw4Ow8.js.map → mcp-dhihqJpH.js.map} +1 -1
  204. package/dashboard/dist/assets/{mcp-query-BwzpZ91Z.js → mcp-query-B_gkB7JK.js} +2 -2
  205. package/dashboard/dist/assets/{mcp-query-BwzpZ91Z.js.map → mcp-query-B_gkB7JK.js.map} +1 -1
  206. package/dashboard/dist/assets/metadata-display-DHjqWkLG.js +2 -0
  207. package/dashboard/dist/assets/metadata-display-DHjqWkLG.js.map +1 -0
  208. package/dashboard/dist/assets/{personas-D5ehmtRb.js → personas-Bw_OlfI6.js} +2 -2
  209. package/dashboard/dist/assets/{personas-D5ehmtRb.js.map → personas-Bw_OlfI6.js.map} +1 -1
  210. package/dashboard/dist/assets/{pipelines-xgPKGEdD.js → pipelines-BYwn0LXY.js} +2 -2
  211. package/dashboard/dist/assets/{pipelines-xgPKGEdD.js.map → pipelines-BYwn0LXY.js.map} +1 -1
  212. package/dashboard/dist/assets/{tasks-CLyrl-MU.js → tasks-t6bPmJ7P.js} +2 -2
  213. package/dashboard/dist/assets/{tasks-CLyrl-MU.js.map → tasks-t6bPmJ7P.js.map} +1 -1
  214. package/dashboard/dist/assets/{topics-B_gO7CQ0.js → topics-Bgo9xw80.js} +2 -2
  215. package/dashboard/dist/assets/{topics-B_gO7CQ0.js.map → topics-Bgo9xw80.js.map} +1 -1
  216. package/dashboard/dist/assets/{useEventHooks-BdWYm63U.js → useEventHooks-BJbMbg_h.js} +2 -2
  217. package/dashboard/dist/assets/{useEventHooks-BdWYm63U.js.map → useEventHooks-BJbMbg_h.js.map} +1 -1
  218. package/dashboard/dist/assets/{useNamespace-C238M4Qn.js → useNamespace-CaXJuSFG.js} +2 -2
  219. package/dashboard/dist/assets/{useNamespace-C238M4Qn.js.map → useNamespace-CaXJuSFG.js.map} +1 -1
  220. package/dashboard/dist/assets/{useYamlActivityEvents-B2ryEK4S.js → useYamlActivityEvents-B47LQrDk.js} +2 -2
  221. package/dashboard/dist/assets/{useYamlActivityEvents-B2ryEK4S.js.map → useYamlActivityEvents-B47LQrDk.js.map} +1 -1
  222. package/dashboard/dist/assets/{users-BFaTe6Mt.js → users-D0jvzUqW.js} +2 -2
  223. package/dashboard/dist/assets/{users-BFaTe6Mt.js.map → users-D0jvzUqW.js.map} +1 -1
  224. package/dashboard/dist/assets/{workflows-DXz7tZxp.js → workflows-DRoZRrMH.js} +2 -2
  225. package/dashboard/dist/assets/{workflows-DXz7tZxp.js.map → workflows-DRoZRrMH.js.map} +1 -1
  226. package/dashboard/dist/assets/{yaml-workflows-u3xuRAnS.js → yaml-workflows-BdhYyIef.js} +2 -2
  227. package/dashboard/dist/assets/{yaml-workflows-u3xuRAnS.js.map → yaml-workflows-BdhYyIef.js.map} +1 -1
  228. package/dashboard/dist/index.html +2 -2
  229. package/docs/api/http/escalations.md +5 -1
  230. package/docs/dashboard.md +15 -0
  231. package/docs/hitl/iframe.md +56 -6
  232. package/docs/hitl/x-lt-footer.md +16 -4
  233. package/docs/hitl/x-lt-validation.md +23 -0
  234. package/docs/mcp.md +2 -0
  235. package/package.json +1 -1
  236. package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js +0 -2
  237. package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js.map +0 -1
  238. package/dashboard/dist/assets/CountdownTimer-By4rbMDN.js +0 -2
  239. package/dashboard/dist/assets/CountdownTimer-By4rbMDN.js.map +0 -1
  240. package/dashboard/dist/assets/CustomDurationPicker-8Ao-1pKA.js +0 -2
  241. package/dashboard/dist/assets/CustomDurationPicker-8Ao-1pKA.js.map +0 -1
  242. package/dashboard/dist/assets/ScanSchemeDetailPage-vFqoe_P4.js +0 -2
  243. package/dashboard/dist/assets/ScanSchemeDetailPage-vFqoe_P4.js.map +0 -1
  244. package/dashboard/dist/assets/ScanStationPage-DH1ynTX9.js +0 -2
  245. package/dashboard/dist/assets/ScanStationPage-DH1ynTX9.js.map +0 -1
  246. package/dashboard/dist/assets/index-DBXm49S6.js.map +0 -1
  247. package/dashboard/dist/assets/index-DsgjFRvA.js +0 -3
  248. package/dashboard/dist/assets/index-DsgjFRvA.js.map +0 -1
@@ -5,13 +5,13 @@ export declare const LIST_ALL_WORKFLOWS = "SELECT * FROM lt_config_workflows ORD
5
5
  export declare const LIST_ALL_ROLES = "SELECT * FROM lt_config_roles ORDER BY workflow_type, role";
6
6
  export declare const LIST_ALL_INVOCATION_ROLES = "SELECT * FROM lt_config_invocation_roles ORDER BY workflow_type, role";
7
7
  export declare const ENSURE_ROLE_EXISTS = "INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING";
8
- export declare const UPSERT_WORKFLOW = "INSERT INTO lt_config_workflows\n (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (workflow_type) DO UPDATE SET\n invocable = EXCLUDED.invocable,\n task_queue = EXCLUDED.task_queue,\n default_role = EXCLUDED.default_role,\n description = EXCLUDED.description,\n consumes = EXCLUDED.consumes,\n envelope_schema = EXCLUDED.envelope_schema,\n resolver_schema = EXCLUDED.resolver_schema,\n cron_schedule = EXCLUDED.cron_schedule,\n tool_tags = EXCLUDED.tool_tags,\n execute_as = EXCLUDED.execute_as,\n certified = EXCLUDED.certified";
8
+ export declare const UPSERT_WORKFLOW = "INSERT INTO lt_config_workflows\n (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified, read_safe)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)\nON CONFLICT (workflow_type) DO UPDATE SET\n invocable = EXCLUDED.invocable,\n task_queue = EXCLUDED.task_queue,\n default_role = EXCLUDED.default_role,\n description = EXCLUDED.description,\n consumes = EXCLUDED.consumes,\n envelope_schema = EXCLUDED.envelope_schema,\n resolver_schema = EXCLUDED.resolver_schema,\n cron_schedule = EXCLUDED.cron_schedule,\n tool_tags = EXCLUDED.tool_tags,\n execute_as = EXCLUDED.execute_as,\n certified = EXCLUDED.certified,\n read_safe = EXCLUDED.read_safe";
9
9
  export declare const DELETE_CONFIG_ROLES = "DELETE FROM lt_config_roles WHERE workflow_type = $1";
10
10
  export declare const INSERT_CONFIG_ROLE = "INSERT INTO lt_config_roles (workflow_type, role) VALUES ($1, $2)";
11
11
  export declare const DELETE_INVOCATION_ROLES = "DELETE FROM lt_config_invocation_roles WHERE workflow_type = $1";
12
12
  export declare const INSERT_INVOCATION_ROLE = "INSERT INTO lt_config_invocation_roles (workflow_type, role) VALUES ($1, $2)";
13
13
  export declare const DELETE_WORKFLOW = "DELETE FROM lt_config_workflows WHERE workflow_type = $1";
14
- export declare const SEED_WORKFLOW_CONFIG = "INSERT INTO lt_config_workflows\n (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (workflow_type) DO NOTHING";
14
+ export declare const SEED_WORKFLOW_CONFIG = "INSERT INTO lt_config_workflows\n (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified, read_safe)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)\nON CONFLICT (workflow_type) DO NOTHING";
15
15
  export declare const SEED_CONFIG_ROLE = "INSERT INTO lt_config_roles (workflow_type, role) VALUES ($1, $2)\nON CONFLICT (workflow_type, role) DO NOTHING";
16
16
  export declare const SEED_INVOCATION_ROLE = "INSERT INTO lt_config_invocation_roles (workflow_type, role) VALUES ($1, $2)\nON CONFLICT (workflow_type, role) DO NOTHING";
17
17
  export declare const GET_PROVIDER_DATA = "SELECT workflow_type, data, completed_at\n FROM lt_tasks\n WHERE origin_id = $1\n AND workflow_type = ANY($2)\n AND status = 'completed'\n ORDER BY completed_at DESC";
@@ -23,8 +23,8 @@ exports.ENSURE_ROLE_EXISTS = `\
23
23
  INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING`;
24
24
  exports.UPSERT_WORKFLOW = `\
25
25
  INSERT INTO lt_config_workflows
26
- (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified)
27
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
26
+ (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified, read_safe)
27
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
28
28
  ON CONFLICT (workflow_type) DO UPDATE SET
29
29
  invocable = EXCLUDED.invocable,
30
30
  task_queue = EXCLUDED.task_queue,
@@ -36,7 +36,8 @@ ON CONFLICT (workflow_type) DO UPDATE SET
36
36
  cron_schedule = EXCLUDED.cron_schedule,
37
37
  tool_tags = EXCLUDED.tool_tags,
38
38
  execute_as = EXCLUDED.execute_as,
39
- certified = EXCLUDED.certified`;
39
+ certified = EXCLUDED.certified,
40
+ read_safe = EXCLUDED.read_safe`;
40
41
  exports.DELETE_CONFIG_ROLES = `\
41
42
  DELETE FROM lt_config_roles WHERE workflow_type = $1`;
42
43
  exports.INSERT_CONFIG_ROLE = `\
@@ -52,8 +53,8 @@ DELETE FROM lt_config_workflows WHERE workflow_type = $1`;
52
53
  // ------------------------------------------------------------------ //
53
54
  exports.SEED_WORKFLOW_CONFIG = `\
54
55
  INSERT INTO lt_config_workflows
55
- (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified)
56
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
56
+ (workflow_type, invocable, task_queue, default_role, description, consumes, envelope_schema, resolver_schema, cron_schedule, tool_tags, execute_as, certified, read_safe)
57
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
57
58
  ON CONFLICT (workflow_type) DO NOTHING`;
58
59
  exports.SEED_CONFIG_ROLE = `\
59
60
  INSERT INTO lt_config_roles (workflow_type, role) VALUES ($1, $2)
@@ -52,6 +52,7 @@ async function replaceWorkflowConfig(config, certified) {
52
52
  config.tool_tags || [],
53
53
  config.execute_as ?? null,
54
54
  certified,
55
+ config.read_safe ?? false,
55
56
  ]);
56
57
  // Replace roles
57
58
  await client.query(sql_1.DELETE_CONFIG_ROLES, [config.workflow_type]);
@@ -112,6 +113,7 @@ async function seedWorkflowConfig(config) {
112
113
  config.tool_tags || [],
113
114
  config.execute_as ?? null,
114
115
  resolveCertified(config),
116
+ config.read_safe ?? false,
115
117
  ]);
116
118
  const inserted = (rowCount ?? 0) > 0;
117
119
  if (inserted) {
@@ -134,6 +136,8 @@ async function seedWorkflowConfig(config) {
134
136
  drifts.push('invocable');
135
137
  if (resolveCertified(config) !== existing.certified)
136
138
  drifts.push('certified');
139
+ if ((config.read_safe ?? false) !== (existing.read_safe ?? false))
140
+ drifts.push('read_safe');
137
141
  if (config.default_role !== existing.default_role)
138
142
  drifts.push('default_role');
139
143
  if (JSON.stringify(config.envelope_schema) !== JSON.stringify(existing.envelope_schema))
@@ -169,6 +173,7 @@ async function applyWorkflowConfig(config) {
169
173
  existing.default_role === config.default_role &&
170
174
  (existing.description ?? null) === (config.description ?? null) &&
171
175
  existing.certified === certified &&
176
+ (existing.read_safe ?? false) === (config.read_safe ?? false) &&
172
177
  (existing.cron_schedule ?? null) === (config.cron_schedule ?? null) &&
173
178
  (existing.execute_as ?? null) === (config.execute_as ?? null) &&
174
179
  sortedEqual(existing.consumes ?? [], config.consumes ?? []) &&
@@ -134,8 +134,16 @@ export declare function getEscalationScopeRows(ids: string[]): Promise<{
134
134
  /**
135
135
  * Release a single escalation claim back to the available pool.
136
136
  * Only the assigned user (or superadmin via route) may release.
137
- */
138
- export declare function releaseEscalation(id: string, userId: string): Promise<LTEscalationRecord | null>;
137
+ *
138
+ * `quiet` performs the identical release without publishing the `released`
139
+ * event — for bookkeeping releases (a dispatcher's held-skip loop frees rows
140
+ * every ranking window) that are not lifecycle transitions. Faceted machine
141
+ * claims are already silent; this is the release-side counterpart. Default
142
+ * stays loud.
143
+ */
144
+ export declare function releaseEscalation(id: string, userId: string, opts?: {
145
+ quiet?: boolean;
146
+ }): Promise<LTEscalationRecord | null>;
139
147
  /**
140
148
  * Sweep expired claims back to the available pool, returning the count cleared.
141
149
  * Availability is already query-time in the implicit model, but long-tail's
@@ -328,24 +328,32 @@ async function getEscalationScopeRows(ids) {
328
328
  /**
329
329
  * Release a single escalation claim back to the available pool.
330
330
  * Only the assigned user (or superadmin via route) may release.
331
+ *
332
+ * `quiet` performs the identical release without publishing the `released`
333
+ * event — for bookkeeping releases (a dispatcher's held-skip loop frees rows
334
+ * every ranking window) that are not lifecycle transitions. Faceted machine
335
+ * claims are already silent; this is the release-side counterpart. Default
336
+ * stays loud.
331
337
  */
332
- async function releaseEscalation(id, userId) {
338
+ async function releaseEscalation(id, userId, opts) {
333
339
  const client = await (0, client_1.escalations)();
334
340
  const result = await client.release({ id, assignee: userId });
335
341
  if (!result.ok)
336
342
  return null;
337
343
  const released = (0, map_1.toEscalationRecord)(result.entry);
338
- publishEscalationChange({
339
- type: 'escalation.released',
340
- source: 'service',
341
- workflowId: released.workflow_id || '',
342
- workflowName: released.workflow_type || '',
343
- taskQueue: released.task_queue || '',
344
- escalationId: released.id,
345
- role: released.role,
346
- status: 'released',
347
- data: (0, escalation_wire_1.escalationEventData)(released, { released_by: userId }),
348
- });
344
+ if (!opts?.quiet) {
345
+ publishEscalationChange({
346
+ type: 'escalation.released',
347
+ source: 'service',
348
+ workflowId: released.workflow_id || '',
349
+ workflowName: released.workflow_type || '',
350
+ taskQueue: released.task_queue || '',
351
+ escalationId: released.id,
352
+ role: released.role,
353
+ status: 'released',
354
+ data: (0, escalation_wire_1.escalationEventData)(released, { released_by: userId }),
355
+ });
356
+ }
349
357
  return released;
350
358
  }
351
359
  /**
@@ -261,6 +261,26 @@ const SYSTEM_TOPICS = [
261
261
  example_payload: { workflowId: 'wf-abc', workflowName: 'processOrder', milestones: [{ name: 'items_processed', value: 42 }] },
262
262
  tags: ['progress', 'core'],
263
263
  },
264
+ // Surfaces
265
+ {
266
+ topic: 'system.surfaces.dashboard',
267
+ description: 'A dashboard announcement was published or removed. Delivery reaches ' +
268
+ 'every authenticated subscriber — role targeting is display scoping, ' +
269
+ 'so bodies must never carry secrets.',
270
+ category: 'surfaces',
271
+ payload_schema: objectSchema({
272
+ action: { type: 'string', description: 'created | deleted' },
273
+ announcement: {
274
+ type: 'object',
275
+ description: 'The announcement row (id, title, body, layout, roles, expires_at)',
276
+ },
277
+ }),
278
+ example_payload: {
279
+ action: 'created',
280
+ announcement: { id: 'ann-001', title: 'Maintenance tonight', layout: 'banner', roles: [] },
281
+ },
282
+ tags: ['surface', 'dashboard'],
283
+ },
264
284
  ];
265
285
  // ── Seeding ─────────────────────────────────────────────────────────────────────
266
286
  /**
@@ -13,5 +13,6 @@ export * from './x-lt-labels';
13
13
  export * from './x-lt-query';
14
14
  export * from './x-lt-submit-guard';
15
15
  export * from './x-lt-show-if';
16
+ export * from './x-lt-require-any';
16
17
  export * from './field-validator';
17
18
  export * from './validate-resolver-payload';
@@ -29,5 +29,6 @@ __exportStar(require("./x-lt-labels"), exports);
29
29
  __exportStar(require("./x-lt-query"), exports);
30
30
  __exportStar(require("./x-lt-submit-guard"), exports);
31
31
  __exportStar(require("./x-lt-show-if"), exports);
32
+ __exportStar(require("./x-lt-require-any"), exports);
32
33
  __exportStar(require("./field-validator"), exports);
33
34
  __exportStar(require("./validate-resolver-payload"), exports);
@@ -15,6 +15,9 @@
15
15
  * - x-lt-require-all against the checklist items resolved from context
16
16
  * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)
17
17
  *
18
+ * Root-level x-lt-require-any groups run after the per-field pass: each group
19
+ * needs a value in at least one visible member (all-hidden groups are waived).
20
+ *
18
21
  * The showIf/`resolver.*` domain is always the FLAT form representation, so a
19
22
  * condition like `resolver.approved` reads the same on both sides.
20
23
  */
@@ -19,12 +19,16 @@ exports.validateResolverPayload = validateResolverPayload;
19
19
  * - x-lt-require-all against the checklist items resolved from context
20
20
  * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)
21
21
  *
22
+ * Root-level x-lt-require-any groups run after the per-field pass: each group
23
+ * needs a value in at least one visible member (all-hidden groups are waived).
24
+ *
22
25
  * The showIf/`resolver.*` domain is always the FLAT form representation, so a
23
26
  * condition like `resolver.approved` reads the same on both sides.
24
27
  */
25
28
  const field_validator_1 = require("./field-validator");
26
29
  const x_lt_show_if_1 = require("./x-lt-show-if");
27
30
  const x_lt_bind_1 = require("./x-lt-bind");
31
+ const x_lt_require_any_1 = require("./x-lt-require-any");
28
32
  /**
29
33
  * Validate FLAT form values against the form schema. This is the dashboard's
30
34
  * entry point (the values the user edits, keyed by field name).
@@ -46,6 +50,21 @@ function validateResolverForm(schema, formValues, ctx) {
46
50
  if (err)
47
51
  errors.push({ field, message: err });
48
52
  }
53
+ // Require-any groups: at least one VISIBLE member per group carries a value.
54
+ // A member hidden by showIf (or naming no property) can neither satisfy nor
55
+ // be demanded; an all-hidden group is waived.
56
+ for (const group of (0, x_lt_require_any_1.readRequireAnyGroups)(schema)) {
57
+ const visible = group.filter((k) => properties[k] && (0, x_lt_show_if_1.evaluateShowIf)(properties[k]['x-lt-showIf'], liveCtx));
58
+ if (visible.length === 0)
59
+ continue;
60
+ if (visible.some((k) => (0, x_lt_require_any_1.hasRequireAnyValue)(formValues[k])))
61
+ continue;
62
+ const titles = visible.map((k) => properties[k].title ?? k);
63
+ errors.push({
64
+ field: visible[0],
65
+ message: `Enter a value for at least one of: ${titles.join(', ')}`,
66
+ });
67
+ }
49
68
  return errors;
50
69
  }
51
70
  /**
@@ -10,19 +10,30 @@
10
10
  * { "x-lt-labels": { "claim": "Claim and Submit", "submit": "Approve" } }
11
11
  * ```
12
12
  *
13
- * Only the five known targets are read; unknown keys and non-string values are
14
- * ignored. Any target the schema omits keeps its default label, so a schema
15
- * overrides just the controls it cares about.
13
+ * `cancel` additionally accepts `false` to remove the control entirely
14
+ * for roles where cancelling is not part of the process ("Send to Service"
15
+ * flows escalate instead). The other targets are rename-only: hiding
16
+ * claim/submit/release would strand the footer.
17
+ *
18
+ * Only the five known targets are read; unknown keys and non-string values
19
+ * (except `cancel: false`) are ignored. Any target the schema omits keeps its
20
+ * default label, so a schema overrides just the controls it cares about.
16
21
  */
17
22
  export declare const X_LT_LABELS = "x-lt-labels";
18
23
  /** The footer controls a schema may rename. */
19
24
  export declare const FOOTER_LABEL_TARGETS: readonly ["claim", "cancel", "submit", "escalate", "release"];
20
25
  export type FooterLabelTarget = (typeof FOOTER_LABEL_TARGETS)[number];
21
- /** A partial map of target → override label. Absent targets keep their default. */
22
- export type FooterLabels = Partial<Record<FooterLabelTarget, string>>;
26
+ /**
27
+ * A partial map of target → override label. Absent targets keep their
28
+ * default. `cancel: false` removes the cancel control from the footer.
29
+ */
30
+ export type FooterLabels = Partial<Record<Exclude<FooterLabelTarget, 'cancel'>, string>> & {
31
+ cancel?: string | false;
32
+ };
23
33
  /**
24
34
  * The schema's footer label overrides, or an empty map when none are declared.
25
35
  * Reads only the known targets; a non-object `x-lt-labels`, unknown keys, and
26
- * blank or non-string values are dropped.
36
+ * blank or non-string values are dropped — except `cancel: false`, which is
37
+ * preserved as the hide instruction.
27
38
  */
28
39
  export declare function readFooterLabels(schema: Record<string, unknown> | null | undefined): FooterLabels;
@@ -11,9 +11,14 @@
11
11
  * { "x-lt-labels": { "claim": "Claim and Submit", "submit": "Approve" } }
12
12
  * ```
13
13
  *
14
- * Only the five known targets are read; unknown keys and non-string values are
15
- * ignored. Any target the schema omits keeps its default label, so a schema
16
- * overrides just the controls it cares about.
14
+ * `cancel` additionally accepts `false` to remove the control entirely
15
+ * for roles where cancelling is not part of the process ("Send to Service"
16
+ * flows escalate instead). The other targets are rename-only: hiding
17
+ * claim/submit/release would strand the footer.
18
+ *
19
+ * Only the five known targets are read; unknown keys and non-string values
20
+ * (except `cancel: false`) are ignored. Any target the schema omits keeps its
21
+ * default label, so a schema overrides just the controls it cares about.
17
22
  */
18
23
  Object.defineProperty(exports, "__esModule", { value: true });
19
24
  exports.FOOTER_LABEL_TARGETS = exports.X_LT_LABELS = void 0;
@@ -24,7 +29,8 @@ exports.FOOTER_LABEL_TARGETS = ['claim', 'cancel', 'submit', 'escalate', 'releas
24
29
  /**
25
30
  * The schema's footer label overrides, or an empty map when none are declared.
26
31
  * Reads only the known targets; a non-object `x-lt-labels`, unknown keys, and
27
- * blank or non-string values are dropped.
32
+ * blank or non-string values are dropped — except `cancel: false`, which is
33
+ * preserved as the hide instruction.
28
34
  */
29
35
  function readFooterLabels(schema) {
30
36
  const raw = schema?.[exports.X_LT_LABELS];
@@ -32,6 +38,8 @@ function readFooterLabels(schema) {
32
38
  return {};
33
39
  const source = raw;
34
40
  const labels = {};
41
+ if (source.cancel === false)
42
+ labels.cancel = false;
35
43
  for (const target of exports.FOOTER_LABEL_TARGETS) {
36
44
  const value = source[target];
37
45
  if (typeof value === 'string' && value.trim().length > 0) {
@@ -0,0 +1,22 @@
1
+ /**
2
+ * x-lt-require-any — "at least one of this set" as a root-schema token. A
3
+ * form_schema declares groups of field names; a submission passes when every
4
+ * group has a value in at least one member. The canonical case: a Left
5
+ * quantity and a Right quantity where either satisfies, but blank-both fails.
6
+ *
7
+ * x-lt-require-any string[][] — e.g. [["left_quantity", "right_quantity"]]
8
+ *
9
+ * Visibility rules compose: a member hidden by its `x-lt-showIf` (or naming
10
+ * no schema property) can neither satisfy the group nor be demanded of the
11
+ * submitter, and a group whose members are ALL hidden is waived. `false` and
12
+ * `0` are answers; `''`, null, and undefined are not.
13
+ */
14
+ export declare const X_LT_REQUIRE_ANY = "x-lt-require-any";
15
+ /**
16
+ * The schema's require-any groups. Malformed declarations (non-array token,
17
+ * non-array groups, non-string members) read as no groups — a bad token never
18
+ * bricks submission.
19
+ */
20
+ export declare function readRequireAnyGroups(schema: Record<string, unknown> | null | undefined): string[][];
21
+ /** Present = an actual answer: `false` and `0` count; `''`/null/undefined do not. */
22
+ export declare function hasRequireAnyValue(value: unknown): boolean;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * x-lt-require-any — "at least one of this set" as a root-schema token. A
4
+ * form_schema declares groups of field names; a submission passes when every
5
+ * group has a value in at least one member. The canonical case: a Left
6
+ * quantity and a Right quantity where either satisfies, but blank-both fails.
7
+ *
8
+ * x-lt-require-any string[][] — e.g. [["left_quantity", "right_quantity"]]
9
+ *
10
+ * Visibility rules compose: a member hidden by its `x-lt-showIf` (or naming
11
+ * no schema property) can neither satisfy the group nor be demanded of the
12
+ * submitter, and a group whose members are ALL hidden is waived. `false` and
13
+ * `0` are answers; `''`, null, and undefined are not.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.X_LT_REQUIRE_ANY = void 0;
17
+ exports.readRequireAnyGroups = readRequireAnyGroups;
18
+ exports.hasRequireAnyValue = hasRequireAnyValue;
19
+ exports.X_LT_REQUIRE_ANY = 'x-lt-require-any';
20
+ /**
21
+ * The schema's require-any groups. Malformed declarations (non-array token,
22
+ * non-array groups, non-string members) read as no groups — a bad token never
23
+ * bricks submission.
24
+ */
25
+ function readRequireAnyGroups(schema) {
26
+ const raw = schema?.[exports.X_LT_REQUIRE_ANY];
27
+ if (!Array.isArray(raw))
28
+ return [];
29
+ return raw
30
+ .filter((group) => Array.isArray(group))
31
+ .map((group) => group.filter((m) => typeof m === 'string' && m.length > 0))
32
+ .filter((group) => group.length > 0);
33
+ }
34
+ /** Present = an actual answer: `false` and `0` count; `''`/null/undefined do not. */
35
+ function hasRequireAnyValue(value) {
36
+ if (value === undefined || value === null)
37
+ return false;
38
+ if (typeof value === 'string')
39
+ return value.trim().length > 0;
40
+ return true;
41
+ }
@@ -236,6 +236,7 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
236
236
  resolver_schema: c.resolverSchema ?? null,
237
237
  cron_schedule: c.cronSchedule ?? null,
238
238
  execute_as: c.executeAs ?? null,
239
+ read_safe: c.readSafe ?? false,
239
240
  };
240
241
  try {
241
242
  if ((0, apply_report_1.ownedByCode)(c.reset, configSource)) {
@@ -472,9 +473,8 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
472
473
  (0, apply_report_1.logSurfaceReport)('agents', agentReport);
473
474
  }
474
475
  }
475
- // Register declared scan schemes (with their rules) ownership per
476
- // configSource / per-entry reset. A scheme and its rules are one ownership
477
- // unit; the scheme applies first so rule validation sees its kind.
476
+ // Declared scan schemes + rules (one ownership unit, one reset). The scheme
477
+ // applies first rule validation reads its kind.
478
478
  if (startConfig.scanSchemes?.length) {
479
479
  const { seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, listScanSchemes, listScanRules, } = await Promise.resolve().then(() => __importStar(require('../services/scan-code')));
480
480
  const scanReport = (0, apply_report_1.newSurfaceReport)();
@@ -492,7 +492,6 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
492
492
  (0, apply_report_1.recordOutcome)(scanReport, `scheme ${scheme.version}`, outcome);
493
493
  if (outcome === 'applied')
494
494
  logger_1.loggerRegistry.info(`[long-tail] scan scheme applied: ${scheme.version}`);
495
- // Undeclared rules on a code-owned scheme are reported, never deleted.
496
495
  const declaredCategories = new Set((rules ?? []).map((r) => r.category));
497
496
  const existingRules = await listScanRules(scheme.version);
498
497
  scanReport.orphans.push(...existingRules
@@ -514,7 +513,6 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
514
513
  }
515
514
  }
516
515
  if (codeOwnedBoot && !startConfig.examples) {
517
- // Schemes in the DB not declared here (demo seeds own theirs under examples).
518
516
  const declaredVersions = new Set(startConfig.scanSchemes.map((s) => s.version));
519
517
  scanReport.orphans.push(...(await listScanSchemes())
520
518
  .map((s) => s.version)
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Dashboard announcement tool — mirrors routes/announcements.ts. Publishing
3
+ * is a privileged surface (the HTTP route guards with requireRoleManager);
4
+ * targeting is display scoping only, so bodies must never carry secrets.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ export declare function registerAnnouncementTools(server: McpServer): void;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerAnnouncementTools = registerAnnouncementTools;
37
+ const zod_1 = require("zod");
38
+ const api = __importStar(require("../../../api/announcements"));
39
+ const publishAnnouncementSchema = zod_1.z.object({
40
+ body: zod_1.z.string().describe('Markdown body — the only required field.'),
41
+ title: zod_1.z.string().optional().describe('Headline shown on the collapsed banner.'),
42
+ layout: zod_1.z.string().optional().describe("Presentation form. Default: 'banner'."),
43
+ roles: zod_1.z.array(zod_1.z.string()).optional().describe('Target roles; omitted = everyone.'),
44
+ expires_at: zod_1.z.string().optional().describe('ISO timestamp; omitted = 24 hours from now.'),
45
+ });
46
+ function registerAnnouncementTools(server) {
47
+ // mirrors POST /api/announcements
48
+ server.registerTool('publish_announcement', {
49
+ title: 'Publish Announcement',
50
+ description: 'Publish a dashboard announcement — a banner every targeted user sees ' +
51
+ 'live and on their next load until it expires or is dismissed. Only ' +
52
+ 'the body is required; title, layout, role targeting, and expiry ' +
53
+ '(default 24h) are optional. Bodies broadcast to all authenticated ' +
54
+ 'subscribers — never include secrets.',
55
+ inputSchema: publishAnnouncementSchema,
56
+ }, async (args) => {
57
+ const result = await api.createAnnouncement({
58
+ body: args.body,
59
+ title: args.title,
60
+ layout: args.layout,
61
+ roles: args.roles,
62
+ expiresAt: args.expires_at,
63
+ }, { userId: 'lt-system', role: 'superadmin' });
64
+ if (result.error) {
65
+ return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
66
+ }
67
+ return { content: [{ type: 'text', text: JSON.stringify(result.data) }] };
68
+ });
69
+ }
@@ -60,7 +60,8 @@ const overview_1 = require("./overview");
60
60
  const diagnostics_1 = require("./diagnostics");
61
61
  const scan_codes_1 = require("./scan-codes");
62
62
  const domain_context_1 = require("./domain-context");
63
- const TOOL_COUNT = 103;
63
+ const announcements_1 = require("./announcements");
64
+ const TOOL_COUNT = 105;
64
65
  let server = null;
65
66
  async function createAdminServer(options) {
66
67
  if (server && !options?.fresh)
@@ -73,7 +74,7 @@ async function createAdminServer(options) {
73
74
  (0, tasks_1.registerTaskTools)(instance); // 2 tools
74
75
  (0, escalations_1.registerEscalationTools)(instance); // 20 tools (RO + RW single + metadata + bulk)
75
76
  (0, workflow_config_1.registerWorkflowConfigTools)(instance); // 3 tools
76
- (0, workflows_1.registerWorkflowTools)(instance); // 4 tools (+ terminate_workflow)
77
+ (0, workflows_1.registerWorkflowTools)(instance); // 5 tools (+ terminate_workflow, invoke_workflow_read_safe)
77
78
  (0, mcp_servers_1.registerMcpServerTools)(instance); // 4 tools
78
79
  (0, yaml_workflows_1.registerYamlWorkflowTools)(instance); // 5 tools
79
80
  (0, users_1.registerUserTools)(instance); // 10 tools (users + roles + role schemas)
@@ -91,7 +92,8 @@ async function createAdminServer(options) {
91
92
  (0, diagnostics_1.registerDiagnosticsTools)(instance); // 3 tools
92
93
  (0, scan_codes_1.registerScanCodeTools)(instance); // 5 tools (scan schemes + rules + execute)
93
94
  (0, domain_context_1.registerDomainContextTools)(instance); // 1 tool (get_domain_context)
94
- // Total: 103
95
+ (0, announcements_1.registerAnnouncementTools)(instance); // 1 tool (publish_announcement)
96
+ // Total: 105
95
97
  logger_1.loggerRegistry.info(`[lt-mcp:admin] ${name} ready (${TOOL_COUNT} tools registered)`);
96
98
  return instance;
97
99
  }
@@ -109,6 +109,51 @@ function registerWorkflowTools(server) {
109
109
  }],
110
110
  };
111
111
  });
112
+ // invoke_workflow gated to configs registered read-safe — the invocation
113
+ // surface exposed to read-scoped MCP callers. Any workflow may be attempted;
114
+ // one lacking the flag fails with a clear error.
115
+ server.registerTool('invoke_workflow_read_safe', {
116
+ title: 'Invoke Read-Safe Workflow',
117
+ description: 'Start a workflow registered read-safe (side-effect-free). Same contract ' +
118
+ 'as invoke_workflow, gated to configs carrying read_safe=true — the ' +
119
+ 'variant exposed to read-scoped MCP callers. A workflow without the ' +
120
+ 'flag fails with a clear error.',
121
+ inputSchema: schemas_1.invokeWorkflowSchema,
122
+ }, async (args) => {
123
+ const config = await configService.getWorkflowConfig(args.workflow_type);
124
+ if (!config?.invocable) {
125
+ return {
126
+ content: [{
127
+ type: 'text',
128
+ text: JSON.stringify({ error: `workflow ${args.workflow_type} is not invocable` }),
129
+ }],
130
+ isError: true,
131
+ };
132
+ }
133
+ if (!config.read_safe) {
134
+ return {
135
+ content: [{
136
+ type: 'text',
137
+ text: JSON.stringify({ error: `workflow ${args.workflow_type} is not registered read-safe` }),
138
+ }],
139
+ isError: true,
140
+ };
141
+ }
142
+ const result = await (0, workflow_invocation_1.invokeWorkflow)({
143
+ workflowType: args.workflow_type,
144
+ data: args.data,
145
+ metadata: args.metadata,
146
+ executeAs: args.execute_as,
147
+ options: args.options,
148
+ auth: { userId: 'lt-system', role: 'superadmin' },
149
+ });
150
+ return {
151
+ content: [{
152
+ type: 'text',
153
+ text: JSON.stringify({ workflow_id: result.workflowId, message: 'Workflow started' }),
154
+ }],
155
+ };
156
+ });
112
157
  // mirrors GET /api/workflows/:workflowId/status + /result
113
158
  server.registerTool('get_workflow_status', {
114
159
  title: 'Get Workflow Status',