@hotmeshio/long-tail 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/build/api/announcements.d.ts +22 -0
  2. package/build/api/announcements.js +96 -0
  3. package/build/api/auth-sso.d.ts +6 -3
  4. package/build/api/auth-sso.js +6 -3
  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/lib/db/schemas/031_announcements.sql +30 -0
  13. package/build/lib/db/schemas/032_workflow_read_safe.sql +9 -0
  14. package/build/lib/events/publish.d.ts +15 -0
  15. package/build/lib/events/publish.js +22 -0
  16. package/build/modules/auth.js +9 -3
  17. package/build/routes/announcements.d.ts +2 -0
  18. package/build/routes/announcements.js +64 -0
  19. package/build/routes/auth-sso.js +6 -1
  20. package/build/routes/escalations/list.js +2 -0
  21. package/build/routes/index.js +2 -0
  22. package/build/services/announcement/index.d.ts +30 -0
  23. package/build/services/announcement/index.js +29 -0
  24. package/build/services/announcement/sql.d.ts +8 -0
  25. package/build/services/announcement/sql.js +24 -0
  26. package/build/services/config/cache.js +1 -0
  27. package/build/services/config/read.js +2 -0
  28. package/build/services/config/sql.d.ts +2 -2
  29. package/build/services/config/sql.js +6 -5
  30. package/build/services/config/write.js +5 -0
  31. package/build/services/scan-code/index.d.ts +1 -1
  32. package/build/services/scan-code/index.js +3 -1
  33. package/build/services/scan-code/sql.d.ts +7 -0
  34. package/build/services/scan-code/sql.js +55 -1
  35. package/build/services/scan-code/write.d.ts +8 -0
  36. package/build/services/scan-code/write.js +23 -1
  37. package/build/services/topics/system-topics.js +20 -0
  38. package/build/shared/form-validation/index.d.ts +1 -0
  39. package/build/shared/form-validation/index.js +1 -0
  40. package/build/shared/form-validation/validate-resolver-payload.d.ts +3 -0
  41. package/build/shared/form-validation/validate-resolver-payload.js +19 -0
  42. package/build/shared/form-validation/x-lt-labels.d.ts +17 -6
  43. package/build/shared/form-validation/x-lt-labels.js +12 -4
  44. package/build/shared/form-validation/x-lt-require-any.d.ts +22 -0
  45. package/build/shared/form-validation/x-lt-require-any.js +41 -0
  46. package/build/start/workers.js +50 -0
  47. package/build/system/mcp-servers/admin/announcements.d.ts +7 -0
  48. package/build/system/mcp-servers/admin/announcements.js +69 -0
  49. package/build/system/mcp-servers/admin/index.js +5 -3
  50. package/build/system/mcp-servers/admin/workflows.js +45 -0
  51. package/build/system/seed/tool-manifests-admin.d.ts +357 -0
  52. package/build/system/seed/tool-manifests-admin.js +3 -0
  53. package/build/tsconfig.tsbuildinfo +1 -1
  54. package/build/types/auth.d.ts +21 -7
  55. package/build/types/config.d.ts +8 -0
  56. package/build/types/index.d.ts +1 -1
  57. package/build/types/startup.d.ts +57 -0
  58. package/dashboard/dist/assets/{AdminDashboard-D2unnS2b.js → AdminDashboard-DeZsR4pA.js} +2 -2
  59. package/dashboard/dist/assets/{AdminDashboard-D2unnS2b.js.map → AdminDashboard-DeZsR4pA.js.map} +1 -1
  60. package/dashboard/dist/assets/{AgentConfigPage-CBkf403g.js → AgentConfigPage-Bi5ZAsjf.js} +2 -2
  61. package/dashboard/dist/assets/{AgentConfigPage-CBkf403g.js.map → AgentConfigPage-Bi5ZAsjf.js.map} +1 -1
  62. package/dashboard/dist/assets/{AgentDetailPage-CAIU3yzo.js → AgentDetailPage-CIbKor5E.js} +2 -2
  63. package/dashboard/dist/assets/{AgentDetailPage-CAIU3yzo.js.map → AgentDetailPage-CIbKor5E.js.map} +1 -1
  64. package/dashboard/dist/assets/{AgentsPage-qP9fWMyT.js → AgentsPage-CRFZ6KDu.js} +2 -2
  65. package/dashboard/dist/assets/{AgentsPage-qP9fWMyT.js.map → AgentsPage-CRFZ6KDu.js.map} +1 -1
  66. package/dashboard/dist/assets/AvailableEscalationsPage-DDsmXjpi.js +2 -0
  67. package/dashboard/dist/assets/AvailableEscalationsPage-DDsmXjpi.js.map +1 -0
  68. package/dashboard/dist/assets/{BotPicker-BN-MKITV.js → BotPicker-dUpw1wW6.js} +2 -2
  69. package/dashboard/dist/assets/{BotPicker-BN-MKITV.js.map → BotPicker-dUpw1wW6.js.map} +1 -1
  70. package/dashboard/dist/assets/{CapabilitiesPage-CJfmWokN.js → CapabilitiesPage-Ca2jEln-.js} +2 -2
  71. package/dashboard/dist/assets/{CapabilitiesPage-CJfmWokN.js.map → CapabilitiesPage-Ca2jEln-.js.map} +1 -1
  72. package/dashboard/dist/assets/{CollapsibleSection-BvMHlHyt.js → CollapsibleSection-BXlR5QmW.js} +2 -2
  73. package/dashboard/dist/assets/{CollapsibleSection-BvMHlHyt.js.map → CollapsibleSection-BXlR5QmW.js.map} +1 -1
  74. package/dashboard/dist/assets/CountdownTimer-rnoWmFqx.js +2 -0
  75. package/dashboard/dist/assets/CountdownTimer-rnoWmFqx.js.map +1 -0
  76. package/dashboard/dist/assets/{CredentialsPage-2TvvRwGJ.js → CredentialsPage-CGyCCzGh.js} +2 -2
  77. package/dashboard/dist/assets/{CredentialsPage-2TvvRwGJ.js.map → CredentialsPage-CGyCCzGh.js.map} +1 -1
  78. package/dashboard/dist/assets/{CronLabel-HxmsDSnV.js → CronLabel-CAu2hmQf.js} +2 -2
  79. package/dashboard/dist/assets/{CronLabel-HxmsDSnV.js.map → CronLabel-CAu2hmQf.js.map} +1 -1
  80. package/dashboard/dist/assets/CustomDurationPicker-hlnadaFt.js +2 -0
  81. package/dashboard/dist/assets/CustomDurationPicker-hlnadaFt.js.map +1 -0
  82. package/dashboard/dist/assets/{ElapsedCell-BkRu9Xpd.js → ElapsedCell-B1eoCzEw.js} +2 -2
  83. package/dashboard/dist/assets/{ElapsedCell-BkRu9Xpd.js.map → ElapsedCell-B1eoCzEw.js.map} +1 -1
  84. package/dashboard/dist/assets/{EntityTimelinePanel--E6hLMCM.js → EntityTimelinePanel-CIOyjwjM.js} +2 -2
  85. package/dashboard/dist/assets/{EntityTimelinePanel--E6hLMCM.js.map → EntityTimelinePanel-CIOyjwjM.js.map} +1 -1
  86. package/dashboard/dist/assets/{EscalationListSchemaPage-CdFtqEEX.js → EscalationListSchemaPage-DQNQ7o_4.js} +2 -2
  87. package/dashboard/dist/assets/{EscalationListSchemaPage-CdFtqEEX.js.map → EscalationListSchemaPage-DQNQ7o_4.js.map} +1 -1
  88. package/dashboard/dist/assets/{EscalationSchemaPage-BsjS2axz.js → EscalationSchemaPage-DFgDn4R3.js} +2 -2
  89. package/dashboard/dist/assets/{EscalationSchemaPage-BsjS2axz.js.map → EscalationSchemaPage-DFgDn4R3.js.map} +1 -1
  90. package/dashboard/dist/assets/{EscalationsOverview-FL-xteVc.js → EscalationsOverview-DfbKtXVZ.js} +2 -2
  91. package/dashboard/dist/assets/{EscalationsOverview-FL-xteVc.js.map → EscalationsOverview-DfbKtXVZ.js.map} +1 -1
  92. package/dashboard/dist/assets/{EventTable-BOcgZ78i.js → EventTable-CZPkvhao.js} +2 -2
  93. package/dashboard/dist/assets/{EventTable-BOcgZ78i.js.map → EventTable-CZPkvhao.js.map} +1 -1
  94. package/dashboard/dist/assets/{FilterBar-DfCiCmm-.js → FilterBar-CYjKK9Cp.js} +2 -2
  95. package/dashboard/dist/assets/{FilterBar-DfCiCmm-.js.map → FilterBar-CYjKK9Cp.js.map} +1 -1
  96. package/dashboard/dist/assets/{GraphInvokePage-DfVeiN-8.js → GraphInvokePage-DY9u42vt.js} +2 -2
  97. package/dashboard/dist/assets/{GraphInvokePage-DfVeiN-8.js.map → GraphInvokePage-DY9u42vt.js.map} +1 -1
  98. package/dashboard/dist/assets/{HomePage-C2IhF9WB.js → HomePage-p_CYlGnh.js} +2 -2
  99. package/dashboard/dist/assets/{HomePage-C2IhF9WB.js.map → HomePage-p_CYlGnh.js.map} +1 -1
  100. package/dashboard/dist/assets/{ListToolbar-DA0PTOl5.js → ListToolbar-Dz-1RXSH.js} +2 -2
  101. package/dashboard/dist/assets/{ListToolbar-DA0PTOl5.js.map → ListToolbar-Dz-1RXSH.js.map} +1 -1
  102. package/dashboard/dist/assets/{McpOverview-DstPch5M.js → McpOverview-BUI9sVTk.js} +2 -2
  103. package/dashboard/dist/assets/{McpOverview-DstPch5M.js.map → McpOverview-BUI9sVTk.js.map} +1 -1
  104. package/dashboard/dist/assets/{McpQueryDetailPage-Csv0PKE0.js → McpQueryDetailPage-CVN_UAB3.js} +2 -2
  105. package/dashboard/dist/assets/{McpQueryDetailPage-Csv0PKE0.js.map → McpQueryDetailPage-CVN_UAB3.js.map} +1 -1
  106. package/dashboard/dist/assets/{McpQueryPage-DxmqCkly.js → McpQueryPage-DRTKSPDR.js} +2 -2
  107. package/dashboard/dist/assets/{McpQueryPage-DxmqCkly.js.map → McpQueryPage-DRTKSPDR.js.map} +1 -1
  108. package/dashboard/dist/assets/{McpRunDetailPage-CcJOlp_B.js → McpRunDetailPage-CTb1AxR3.js} +2 -2
  109. package/dashboard/dist/assets/{McpRunDetailPage-CcJOlp_B.js.map → McpRunDetailPage-CTb1AxR3.js.map} +1 -1
  110. package/dashboard/dist/assets/{McpRunsPage-BZCR043j.js → McpRunsPage-BWLwjVd0.js} +2 -2
  111. package/dashboard/dist/assets/{McpRunsPage-BZCR043j.js.map → McpRunsPage-BWLwjVd0.js.map} +1 -1
  112. package/dashboard/dist/assets/{OperationsPage-DMsPXITh.js → OperationsPage-BSl_oUAJ.js} +2 -2
  113. package/dashboard/dist/assets/{OperationsPage-DMsPXITh.js.map → OperationsPage-BSl_oUAJ.js.map} +1 -1
  114. package/dashboard/dist/assets/{OperatorDashboard-DSloftQ5.js → OperatorDashboard-DGs9kPOZ.js} +2 -2
  115. package/dashboard/dist/assets/{OperatorDashboard-DSloftQ5.js.map → OperatorDashboard-DGs9kPOZ.js.map} +1 -1
  116. package/dashboard/dist/assets/{PersonaDetailPage-jDVRCLbU.js → PersonaDetailPage-C33MgXUY.js} +2 -2
  117. package/dashboard/dist/assets/{PersonaDetailPage-jDVRCLbU.js.map → PersonaDetailPage-C33MgXUY.js.map} +1 -1
  118. package/dashboard/dist/assets/{PersonasPage-DnDDwXoy.js → PersonasPage-BbLOHq5X.js} +2 -2
  119. package/dashboard/dist/assets/{PersonasPage-DnDDwXoy.js.map → PersonasPage-BbLOHq5X.js.map} +1 -1
  120. package/dashboard/dist/assets/{ProcessDetailPage-CfAUU6q2.js → ProcessDetailPage-zwd0HCJl.js} +2 -2
  121. package/dashboard/dist/assets/{ProcessDetailPage-CfAUU6q2.js.map → ProcessDetailPage-zwd0HCJl.js.map} +1 -1
  122. package/dashboard/dist/assets/{ProcessesListPage-CnAXzaVv.js → ProcessesListPage-DnfmK6jf.js} +2 -2
  123. package/dashboard/dist/assets/{ProcessesListPage-CnAXzaVv.js.map → ProcessesListPage-DnfmK6jf.js.map} +1 -1
  124. package/dashboard/dist/assets/{RoleDetailPage-Dg1p6Qz_.js → RoleDetailPage-axZtFPC_.js} +2 -2
  125. package/dashboard/dist/assets/{RoleDetailPage-Dg1p6Qz_.js.map → RoleDetailPage-axZtFPC_.js.map} +1 -1
  126. package/dashboard/dist/assets/{RolesPage-DeRVQux8.js → RolesPage-DN6yqH7-.js} +2 -2
  127. package/dashboard/dist/assets/{RolesPage-DeRVQux8.js.map → RolesPage-DN6yqH7-.js.map} +1 -1
  128. package/dashboard/dist/assets/{RunAsSelector-BFNqQGuG.js → RunAsSelector-DrGsUhL8.js} +2 -2
  129. package/dashboard/dist/assets/{RunAsSelector-BFNqQGuG.js.map → RunAsSelector-DrGsUhL8.js.map} +1 -1
  130. package/dashboard/dist/assets/{ScanCodesPage-D0GOdk5m.js → ScanCodesPage-BmQjEyWZ.js} +2 -2
  131. package/dashboard/dist/assets/{ScanCodesPage-D0GOdk5m.js.map → ScanCodesPage-BmQjEyWZ.js.map} +1 -1
  132. package/dashboard/dist/assets/ScanSchemeDetailPage-VODehqGs.js +2 -0
  133. package/dashboard/dist/assets/ScanSchemeDetailPage-VODehqGs.js.map +1 -0
  134. package/dashboard/dist/assets/{ScanStationPage-DH1ynTX9.js → ScanStationPage-Y-9Gs7t5.js} +2 -2
  135. package/dashboard/dist/assets/{ScanStationPage-DH1ynTX9.js.map → ScanStationPage-Y-9Gs7t5.js.map} +1 -1
  136. package/dashboard/dist/assets/{StickyPagination-B99hVu95.js → StickyPagination-9VkHiOsT.js} +2 -2
  137. package/dashboard/dist/assets/{StickyPagination-B99hVu95.js.map → StickyPagination-9VkHiOsT.js.map} +1 -1
  138. package/dashboard/dist/assets/{StreamMessageDetail-DcDGISrv.js → StreamMessageDetail-C37J6Qyz.js} +2 -2
  139. package/dashboard/dist/assets/{StreamMessageDetail-DcDGISrv.js.map → StreamMessageDetail-C37J6Qyz.js.map} +1 -1
  140. package/dashboard/dist/assets/{SwimlaneTimeline-BP3mSQAg.js → SwimlaneTimeline-NVGsBIX-.js} +2 -2
  141. package/dashboard/dist/assets/{SwimlaneTimeline-BP3mSQAg.js.map → SwimlaneTimeline-NVGsBIX-.js.map} +1 -1
  142. package/dashboard/dist/assets/{TaskDetailPage-_XWLJzt-.js → TaskDetailPage-5sbMHi5U.js} +2 -2
  143. package/dashboard/dist/assets/{TaskDetailPage-_XWLJzt-.js.map → TaskDetailPage-5sbMHi5U.js.map} +1 -1
  144. package/dashboard/dist/assets/{TasksListPage-iGriKiO2.js → TasksListPage-C9AN7IBb.js} +2 -2
  145. package/dashboard/dist/assets/{TasksListPage-iGriKiO2.js.map → TasksListPage-C9AN7IBb.js.map} +1 -1
  146. package/dashboard/dist/assets/{TimeAgo-BO33VeFl.js → TimeAgo-CsbQGlSd.js} +2 -2
  147. package/dashboard/dist/assets/{TimeAgo-BO33VeFl.js.map → TimeAgo-CsbQGlSd.js.map} +1 -1
  148. package/dashboard/dist/assets/{TimestampCell-KAjX7w35.js → TimestampCell-DlbIkV-G.js} +2 -2
  149. package/dashboard/dist/assets/{TimestampCell-KAjX7w35.js.map → TimestampCell-DlbIkV-G.js.map} +1 -1
  150. package/dashboard/dist/assets/{ToolTestPanel-BchG2yC6.js → ToolTestPanel-BKbLocvr.js} +2 -2
  151. package/dashboard/dist/assets/{ToolTestPanel-BchG2yC6.js.map → ToolTestPanel-BKbLocvr.js.map} +1 -1
  152. package/dashboard/dist/assets/{TopicDetailPage-BaK8H0o1.js → TopicDetailPage-fOnTfDso.js} +2 -2
  153. package/dashboard/dist/assets/{TopicDetailPage-BaK8H0o1.js.map → TopicDetailPage-fOnTfDso.js.map} +1 -1
  154. package/dashboard/dist/assets/{TopicsPage-DEyvm669.js → TopicsPage-BoVkp7DM.js} +2 -2
  155. package/dashboard/dist/assets/{TopicsPage-DEyvm669.js.map → TopicsPage-BoVkp7DM.js.map} +1 -1
  156. package/dashboard/dist/assets/{UserName-BV6SKI9P.js → UserName-0gjVPU_U.js} +2 -2
  157. package/dashboard/dist/assets/{UserName-BV6SKI9P.js.map → UserName-0gjVPU_U.js.map} +1 -1
  158. package/dashboard/dist/assets/{WorkflowExecutionPage-1sKoEFNC.js → WorkflowExecutionPage-B28OxTS_.js} +2 -2
  159. package/dashboard/dist/assets/{WorkflowExecutionPage-1sKoEFNC.js.map → WorkflowExecutionPage-B28OxTS_.js.map} +1 -1
  160. package/dashboard/dist/assets/{WorkflowsDashboard-YTHDZZOD.js → WorkflowsDashboard-Bzvz6tTY.js} +2 -2
  161. package/dashboard/dist/assets/{WorkflowsDashboard-YTHDZZOD.js.map → WorkflowsDashboard-Bzvz6tTY.js.map} +1 -1
  162. package/dashboard/dist/assets/{WorkflowsOverview-ucXPLTtm.js → WorkflowsOverview-BkcRU4Ej.js} +2 -2
  163. package/dashboard/dist/assets/{WorkflowsOverview-ucXPLTtm.js.map → WorkflowsOverview-BkcRU4Ej.js.map} +1 -1
  164. package/dashboard/dist/assets/{YamlWorkflowDetailPage-C_RTZKqZ.js → YamlWorkflowDetailPage-CmM78sYi.js} +2 -2
  165. package/dashboard/dist/assets/{YamlWorkflowDetailPage-C_RTZKqZ.js.map → YamlWorkflowDetailPage-CmM78sYi.js.map} +1 -1
  166. package/dashboard/dist/assets/{YamlWorkflowsPage-Usid3w2W.js → YamlWorkflowsPage-Dp6vG1au.js} +2 -2
  167. package/dashboard/dist/assets/{YamlWorkflowsPage-Usid3w2W.js.map → YamlWorkflowsPage-Dp6vG1au.js.map} +1 -1
  168. package/dashboard/dist/assets/{agents-BTDsRK8e.js → agents-MeqzOPD6.js} +2 -2
  169. package/dashboard/dist/assets/{agents-BTDsRK8e.js.map → agents-MeqzOPD6.js.map} +1 -1
  170. package/dashboard/dist/assets/{bots-DxLrfdfr.js → bots-DTGXnvX_.js} +2 -2
  171. package/dashboard/dist/assets/{bots-DxLrfdfr.js.map → bots-DTGXnvX_.js.map} +1 -1
  172. package/dashboard/dist/assets/{capabilities-DbTmeW-S.js → capabilities-BjlARR7F.js} +2 -2
  173. package/dashboard/dist/assets/{capabilities-DbTmeW-S.js.map → capabilities-BjlARR7F.js.map} +1 -1
  174. package/dashboard/dist/assets/{controlplane-CEBntAL4.js → controlplane-DMYI0OaL.js} +2 -2
  175. package/dashboard/dist/assets/{controlplane-CEBntAL4.js.map → controlplane-DMYI0OaL.js.map} +1 -1
  176. package/dashboard/dist/assets/{escalation-columns-Carqdwoh.js → escalation-columns-BMO_H3cb.js} +2 -2
  177. package/dashboard/dist/assets/{escalation-columns-Carqdwoh.js.map → escalation-columns-BMO_H3cb.js.map} +1 -1
  178. package/dashboard/dist/assets/{index-De8iV1y2.js → index-3QEnMBNG.js} +2 -2
  179. package/dashboard/dist/assets/{index-De8iV1y2.js.map → index-3QEnMBNG.js.map} +1 -1
  180. package/dashboard/dist/assets/{index-Bqm4zu46.js → index-B3FzpDEG.js} +2 -2
  181. package/dashboard/dist/assets/{index-Bqm4zu46.js.map → index-B3FzpDEG.js.map} +1 -1
  182. package/dashboard/dist/assets/{index-cFHoANSG.css → index-B5jxf81r.css} +1 -1
  183. package/dashboard/dist/assets/{index-DBXm49S6.js → index-BU4oujVO.js} +30 -29
  184. package/dashboard/dist/assets/index-BU4oujVO.js.map +1 -0
  185. package/dashboard/dist/assets/{index-kes8V4Xw.js → index-CGCD5hTX.js} +2 -2
  186. package/dashboard/dist/assets/{index-kes8V4Xw.js.map → index-CGCD5hTX.js.map} +1 -1
  187. package/dashboard/dist/assets/{index-BhapT-Vl.js → index-Ch-OS1pk.js} +2 -2
  188. package/dashboard/dist/assets/{index-BhapT-Vl.js.map → index-Ch-OS1pk.js.map} +1 -1
  189. package/dashboard/dist/assets/{index-B9m7fA3M.js → index-CkkOh8y9.js} +2 -2
  190. package/dashboard/dist/assets/{index-B9m7fA3M.js.map → index-CkkOh8y9.js.map} +1 -1
  191. package/dashboard/dist/assets/{index-B2hz0pUh.js → index-D3iDAWK2.js} +2 -2
  192. package/dashboard/dist/assets/{index-B2hz0pUh.js.map → index-D3iDAWK2.js.map} +1 -1
  193. package/dashboard/dist/assets/{index-C0hSttF5.js → index-D6kXz3H8.js} +2 -2
  194. package/dashboard/dist/assets/{index-C0hSttF5.js.map → index-D6kXz3H8.js.map} +1 -1
  195. package/dashboard/dist/assets/{index-CVBBkW8V.js → index-Dsgqxdyh.js} +2 -2
  196. package/dashboard/dist/assets/{index-CVBBkW8V.js.map → index-Dsgqxdyh.js.map} +1 -1
  197. package/dashboard/dist/assets/{index-nwLh3CK2.js → index-DuhqzYwC.js} +2 -2
  198. package/dashboard/dist/assets/{index-nwLh3CK2.js.map → index-DuhqzYwC.js.map} +1 -1
  199. package/dashboard/dist/assets/{index-CDkg6iOE.js → index-DuyzcDuV.js} +2 -2
  200. package/dashboard/dist/assets/{index-CDkg6iOE.js.map → index-DuyzcDuV.js.map} +1 -1
  201. package/dashboard/dist/assets/index-LF1gEc6w.js +3 -0
  202. package/dashboard/dist/assets/index-LF1gEc6w.js.map +1 -0
  203. package/dashboard/dist/assets/{index-CgIBjZta.js → index-k5vcLICm.js} +2 -2
  204. package/dashboard/dist/assets/{index-CgIBjZta.js.map → index-k5vcLICm.js.map} +1 -1
  205. package/dashboard/dist/assets/{knowledge-oFYAanUp.js → knowledge-DAV1Jy7b.js} +2 -2
  206. package/dashboard/dist/assets/{knowledge-oFYAanUp.js.map → knowledge-DAV1Jy7b.js.map} +1 -1
  207. package/dashboard/dist/assets/{mcp-C9Kw4Ow8.js → mcp-CivbxL1P.js} +2 -2
  208. package/dashboard/dist/assets/{mcp-C9Kw4Ow8.js.map → mcp-CivbxL1P.js.map} +1 -1
  209. package/dashboard/dist/assets/{mcp-query-BwzpZ91Z.js → mcp-query-CGvWNrgo.js} +2 -2
  210. package/dashboard/dist/assets/{mcp-query-BwzpZ91Z.js.map → mcp-query-CGvWNrgo.js.map} +1 -1
  211. package/dashboard/dist/assets/{personas-D5ehmtRb.js → personas-lI3aUr6t.js} +2 -2
  212. package/dashboard/dist/assets/{personas-D5ehmtRb.js.map → personas-lI3aUr6t.js.map} +1 -1
  213. package/dashboard/dist/assets/{pipelines-xgPKGEdD.js → pipelines-DjPfnTmx.js} +2 -2
  214. package/dashboard/dist/assets/{pipelines-xgPKGEdD.js.map → pipelines-DjPfnTmx.js.map} +1 -1
  215. package/dashboard/dist/assets/{tasks-CLyrl-MU.js → tasks-Co_S55BO.js} +2 -2
  216. package/dashboard/dist/assets/{tasks-CLyrl-MU.js.map → tasks-Co_S55BO.js.map} +1 -1
  217. package/dashboard/dist/assets/{topics-B_gO7CQ0.js → topics-2IGhZXBi.js} +2 -2
  218. package/dashboard/dist/assets/{topics-B_gO7CQ0.js.map → topics-2IGhZXBi.js.map} +1 -1
  219. package/dashboard/dist/assets/{useEventHooks-BdWYm63U.js → useEventHooks-D0C5yke4.js} +2 -2
  220. package/dashboard/dist/assets/{useEventHooks-BdWYm63U.js.map → useEventHooks-D0C5yke4.js.map} +1 -1
  221. package/dashboard/dist/assets/{useNamespace-C238M4Qn.js → useNamespace-LG52DTT-.js} +2 -2
  222. package/dashboard/dist/assets/{useNamespace-C238M4Qn.js.map → useNamespace-LG52DTT-.js.map} +1 -1
  223. package/dashboard/dist/assets/{useYamlActivityEvents-B2ryEK4S.js → useYamlActivityEvents-1IZGVpWC.js} +2 -2
  224. package/dashboard/dist/assets/{useYamlActivityEvents-B2ryEK4S.js.map → useYamlActivityEvents-1IZGVpWC.js.map} +1 -1
  225. package/dashboard/dist/assets/{users-BFaTe6Mt.js → users-C-eHT1i6.js} +2 -2
  226. package/dashboard/dist/assets/{users-BFaTe6Mt.js.map → users-C-eHT1i6.js.map} +1 -1
  227. package/dashboard/dist/assets/{workflows-DXz7tZxp.js → workflows-C16CeY4e.js} +2 -2
  228. package/dashboard/dist/assets/{workflows-DXz7tZxp.js.map → workflows-C16CeY4e.js.map} +1 -1
  229. package/dashboard/dist/assets/{yaml-workflows-u3xuRAnS.js → yaml-workflows-BBenayT9.js} +2 -2
  230. package/dashboard/dist/assets/{yaml-workflows-u3xuRAnS.js.map → yaml-workflows-BBenayT9.js.map} +1 -1
  231. package/dashboard/dist/index.html +2 -2
  232. package/docs/auth.md +26 -1
  233. package/docs/code-owned-configuration.md +27 -0
  234. package/docs/dashboard.md +15 -0
  235. package/docs/hitl/x-lt-footer.md +16 -4
  236. package/docs/hitl/x-lt-validation.md +23 -0
  237. package/docs/mcp.md +2 -0
  238. package/docs/scan-codes.md +24 -0
  239. package/package.json +1 -1
  240. package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js +0 -2
  241. package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js.map +0 -1
  242. package/dashboard/dist/assets/CountdownTimer-By4rbMDN.js +0 -2
  243. package/dashboard/dist/assets/CountdownTimer-By4rbMDN.js.map +0 -1
  244. package/dashboard/dist/assets/CustomDurationPicker-8Ao-1pKA.js +0 -2
  245. package/dashboard/dist/assets/CustomDurationPicker-8Ao-1pKA.js.map +0 -1
  246. package/dashboard/dist/assets/ScanSchemeDetailPage-vFqoe_P4.js +0 -2
  247. package/dashboard/dist/assets/ScanSchemeDetailPage-vFqoe_P4.js.map +0 -1
  248. package/dashboard/dist/assets/index-DBXm49S6.js.map +0 -1
  249. package/dashboard/dist/assets/index-DsgjFRvA.js +0 -3
  250. package/dashboard/dist/assets/index-DsgjFRvA.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import type { LTApiResult, LTApiAuth } from '../types/sdk';
2
+ /**
3
+ * Dashboard announcements — broadcast notices on the dashboard surface.
4
+ * Publishing is a role-manager act (superadmin/admin/engineer via the route
5
+ * guard); reading is any authenticated user, server-filtered to their roles.
6
+ * Role targeting is display scoping only: the live event reaches every
7
+ * authenticated subscriber, so bodies must never carry secrets.
8
+ */
9
+ /** Create an announcement. Only `body` is required — everything else defaults. */
10
+ export declare function createAnnouncement(input: {
11
+ body?: string;
12
+ title?: string;
13
+ layout?: string;
14
+ roles?: string[];
15
+ expiresAt?: string;
16
+ }, auth: LTApiAuth): Promise<LTApiResult>;
17
+ /** Active announcements for the caller — admins see all, others their roles' slice. */
18
+ export declare function listAnnouncements(auth: LTApiAuth): Promise<LTApiResult>;
19
+ /** Remove an announcement; subscribers see it drop live. */
20
+ export declare function deleteAnnouncement(input: {
21
+ id: string;
22
+ }, _auth: LTApiAuth): Promise<LTApiResult>;
@@ -0,0 +1,96 @@
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.createAnnouncement = createAnnouncement;
37
+ exports.listAnnouncements = listAnnouncements;
38
+ exports.deleteAnnouncement = deleteAnnouncement;
39
+ const announcementService = __importStar(require("../services/announcement"));
40
+ const publish_1 = require("../lib/events/publish");
41
+ const user_1 = require("../services/user");
42
+ /**
43
+ * Dashboard announcements — broadcast notices on the dashboard surface.
44
+ * Publishing is a role-manager act (superadmin/admin/engineer via the route
45
+ * guard); reading is any authenticated user, server-filtered to their roles.
46
+ * Role targeting is display scoping only: the live event reaches every
47
+ * authenticated subscriber, so bodies must never carry secrets.
48
+ */
49
+ /** Create an announcement. Only `body` is required — everything else defaults. */
50
+ async function createAnnouncement(input, auth) {
51
+ try {
52
+ if (!input.body?.trim()) {
53
+ return { status: 400, error: 'body is required' };
54
+ }
55
+ const announcement = await announcementService.createAnnouncement({
56
+ body: input.body,
57
+ title: input.title,
58
+ layout: input.layout,
59
+ roles: input.roles,
60
+ expiresAt: input.expiresAt,
61
+ createdBy: auth.userId,
62
+ });
63
+ await (0, publish_1.publishAnnouncementEvent)({ type: 'announcement.created', announcement });
64
+ return { status: 200, data: announcement };
65
+ }
66
+ catch (err) {
67
+ return { status: 500, error: err.message };
68
+ }
69
+ }
70
+ /** Active announcements for the caller — admins see all, others their roles' slice. */
71
+ async function listAnnouncements(auth) {
72
+ try {
73
+ const unscoped = auth.role === 'superadmin' || auth.role === 'admin';
74
+ const roles = unscoped
75
+ ? null
76
+ : (await (0, user_1.getUserRoles)(auth.userId)).map((r) => r.role);
77
+ const announcements = await announcementService.listActiveAnnouncements(roles);
78
+ return { status: 200, data: { announcements } };
79
+ }
80
+ catch (err) {
81
+ return { status: 500, error: err.message };
82
+ }
83
+ }
84
+ /** Remove an announcement; subscribers see it drop live. */
85
+ async function deleteAnnouncement(input, _auth) {
86
+ try {
87
+ const deleted = await announcementService.deleteAnnouncement(input.id);
88
+ if (!deleted)
89
+ return { status: 404, error: 'announcement not found' };
90
+ await (0, publish_1.publishAnnouncementEvent)({ type: 'announcement.deleted', announcement: deleted });
91
+ return { status: 200, data: { deleted: true, id: input.id } };
92
+ }
93
+ catch (err) {
94
+ return { status: 500, error: err.message };
95
+ }
96
+ }
@@ -1,12 +1,15 @@
1
- import type { Request } from 'express';
1
+ import type { Request, Response } from 'express';
2
2
  import type { LTApiResult } from '../types/sdk';
3
3
  /**
4
4
  * Exchange host authentication for a Long Tail JWT.
5
5
  *
6
- * Calls `sso.resolve(req)` to extract the host identity, JIT provisions
6
+ * Calls `sso.resolve(req, res)` to extract the host identity, JIT provisions
7
7
  * the user in `lt_users`, and returns a signed JWT the dashboard can
8
8
  * store for subsequent API calls.
9
9
  *
10
10
  * No request body required — the host's cookies/headers carry the auth.
11
+ * `res` gives cookie-owning hosts the response handle at the exchange
12
+ * boundary (login and every keepalive beat) to set/refresh their session
13
+ * cookie — headers only; the route writes the response body.
11
14
  */
12
- export declare function exchangeSSO(req: Request): Promise<LTApiResult>;
15
+ export declare function exchangeSSO(req: Request, res?: Response): Promise<LTApiResult>;
@@ -7,19 +7,22 @@ const auth_1 = require("../modules/auth");
7
7
  /**
8
8
  * Exchange host authentication for a Long Tail JWT.
9
9
  *
10
- * Calls `sso.resolve(req)` to extract the host identity, JIT provisions
10
+ * Calls `sso.resolve(req, res)` to extract the host identity, JIT provisions
11
11
  * the user in `lt_users`, and returns a signed JWT the dashboard can
12
12
  * store for subsequent API calls.
13
13
  *
14
14
  * No request body required — the host's cookies/headers carry the auth.
15
+ * `res` gives cookie-owning hosts the response handle at the exchange
16
+ * boundary (login and every keepalive beat) to set/refresh their session
17
+ * cookie — headers only; the route writes the response body.
15
18
  */
16
- async function exchangeSSO(req) {
19
+ async function exchangeSSO(req, res) {
17
20
  try {
18
21
  const ssoConfig = (0, sso_1.getSSOConfig)();
19
22
  if (!ssoConfig) {
20
23
  return { status: 404, error: 'SSO not configured' };
21
24
  }
22
- const identity = await ssoConfig.resolve(req);
25
+ const identity = await ssoConfig.resolve(req, res);
23
26
  if (!identity) {
24
27
  return { status: 401, error: 'Host authentication required' };
25
28
  }
@@ -11,6 +11,14 @@ export interface FacetInput {
11
11
  /** Only rows past their role's priority threshold — see FacetQuery.jeopardy. */
12
12
  jeopardy?: boolean;
13
13
  orderBy?: FacetOrder[];
14
+ /**
15
+ * List rows omit the two heavyweight JSON columns (`envelope`,
16
+ * `escalation_payload`) by default — at scale they dominate the payload.
17
+ * Pass `'envelope'` to restore both (list schemas interpolating
18
+ * `{{envelope.*}}`/`{{payload.*}}` need them). The single-item GET always
19
+ * carries the full record.
20
+ */
21
+ include?: string;
14
22
  }
15
23
  /**
16
24
  * List escalations with optional filters.
@@ -42,6 +42,16 @@ exports.getStationMetrics = getStationMetrics;
42
42
  const escalationService = __importStar(require("../../services/escalation"));
43
43
  const features_1 = require("../../modules/features");
44
44
  const helpers_1 = require("./helpers");
45
+ /** Strip the heavyweight JSON columns from list rows unless asked back. */
46
+ function projectListRows(rows, include) {
47
+ if (include === 'envelope')
48
+ return rows;
49
+ return rows.map(({ envelope: _e, escalation_payload: _p, ...rest }) => rest);
50
+ }
51
+ /** Apply the list projection to a { escalations, ... } service result. */
52
+ function projectListResult(result, include) {
53
+ return { ...result, escalations: projectListRows(result.escalations, include) };
54
+ }
45
55
  /** True when the caller asked for anything the plain list path can't express. */
46
56
  function hasFacetQuery(i) {
47
57
  return !!(i.facets ||
@@ -107,7 +117,7 @@ async function listEscalations(input, auth) {
107
117
  limit: input.limit ?? 50,
108
118
  offset: input.offset ?? 0,
109
119
  });
110
- return { status: 200, data: result };
120
+ return { status: 200, data: projectListResult(result, input.include) };
111
121
  }
112
122
  const result = await escalationService.listEscalations({
113
123
  status: input.status,
@@ -127,7 +137,7 @@ async function listEscalations(input, auth) {
127
137
  selfRoles: scope.global ? undefined : scope.selfRoles,
128
138
  meUserId: auth.userId,
129
139
  });
130
- return { status: 200, data: result };
140
+ return { status: 200, data: projectListResult(result, input.include) };
131
141
  }
132
142
  catch (err) {
133
143
  return { status: 500, error: err.message };
@@ -182,7 +192,7 @@ async function listAvailableEscalations(input, auth) {
182
192
  limit: input.limit ?? 50,
183
193
  offset: input.offset ?? 0,
184
194
  });
185
- return { status: 200, data: result };
195
+ return { status: 200, data: projectListResult(result, input.include) };
186
196
  }
187
197
  const result = await escalationService.listAvailableEscalations({
188
198
  role: input.role,
@@ -198,7 +208,7 @@ async function listAvailableEscalations(input, auth) {
198
208
  selfRoles: scope.global ? undefined : scope.selfRoles,
199
209
  meUserId: auth.userId,
200
210
  });
201
- return { status: 200, data: result };
211
+ return { status: 200, data: projectListResult(result, input.include) };
202
212
  }
203
213
  catch (err) {
204
214
  return { status: 500, error: err.message };
@@ -18,3 +18,4 @@ export * as workflowSets from './workflow-sets';
18
18
  export * as dba from './dba';
19
19
  export * as namespaces from './namespaces';
20
20
  export * as maintenance from './maintenance';
21
+ export * as announcements from './announcements';
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.maintenance = exports.namespaces = exports.dba = exports.workflowSets = exports.botAccounts = exports.controlplane = exports.exports = exports.settings = exports.insight = exports.mcpRuns = exports.pipelines = exports.mcp = exports.auth = exports.personas = exports.roles = exports.users = exports.yamlWorkflows = exports.workflows = exports.escalations = exports.tasks = void 0;
36
+ exports.announcements = exports.maintenance = exports.namespaces = exports.dba = exports.workflowSets = exports.botAccounts = exports.controlplane = exports.exports = exports.settings = exports.insight = exports.mcpRuns = exports.pipelines = exports.mcp = exports.auth = exports.personas = exports.roles = exports.users = exports.yamlWorkflows = exports.workflows = exports.escalations = exports.tasks = void 0;
37
37
  exports.tasks = __importStar(require("./tasks"));
38
38
  exports.escalations = __importStar(require("./escalations"));
39
39
  exports.workflows = __importStar(require("./workflows"));
@@ -54,3 +54,4 @@ exports.workflowSets = __importStar(require("./workflow-sets"));
54
54
  exports.dba = __importStar(require("./dba"));
55
55
  exports.namespaces = __importStar(require("./namespaces"));
56
56
  exports.maintenance = __importStar(require("./maintenance"));
57
+ exports.announcements = __importStar(require("./announcements"));
@@ -55,6 +55,7 @@ export declare function upsertWorkflowConfig(input: {
55
55
  envelope_schema?: any;
56
56
  resolver_schema?: any;
57
57
  cron_schedule?: string | null;
58
+ read_safe?: boolean;
58
59
  }): Promise<LTApiResult>;
59
60
  /**
60
61
  * Delete a workflow configuration.
@@ -120,6 +120,7 @@ async function upsertWorkflowConfig(input) {
120
120
  envelope_schema: input.envelope_schema ?? null,
121
121
  resolver_schema: input.resolver_schema ?? null,
122
122
  cron_schedule: input.cron_schedule ?? null,
123
+ read_safe: input.read_safe ?? false,
123
124
  });
124
125
  ltconfig_1.ltConfig.invalidate();
125
126
  await cron_1.cronRegistry.restartCron(config);
@@ -113,6 +113,7 @@ async function listDiscoveredWorkflows(input) {
113
113
  registered: !!config,
114
114
  active: !!worker,
115
115
  invocable: config?.invocable ?? !!worker,
116
+ read_safe: config?.read_safe ?? false,
116
117
  system: registry_1.SYSTEM_WORKFLOWS.has(workflowType),
117
118
  description: config?.description ?? null,
118
119
  roles: config?.roles ?? [],
@@ -0,0 +1,30 @@
1
+ -- Migration 031: Dashboard announcements
2
+ --
3
+ -- Broadcast notices for the dashboard surface (system.surfaces.dashboard).
4
+ -- Role targeting is display scoping only — live events reach every
5
+ -- authenticated socket, so a body must never carry secrets. Rows expire by
6
+ -- timestamp; dismissal is per-browser on the client.
7
+
8
+ CREATE TABLE IF NOT EXISTS lt_announcements (
9
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
10
+ title TEXT,
11
+ body TEXT NOT NULL,
12
+ layout TEXT NOT NULL DEFAULT 'banner',
13
+ roles TEXT[] NOT NULL DEFAULT '{}',
14
+ created_by TEXT,
15
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
16
+ expires_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '24 hours'
17
+ );
18
+
19
+ CREATE INDEX IF NOT EXISTS idx_lt_announcements_expires ON lt_announcements (expires_at);
20
+
21
+ -- The announcement topic (system.surfaces.dashboard) introduces the
22
+ -- 'surfaces' category to the topic catalog.
23
+ ALTER TABLE lt_topic_catalog
24
+ DROP CONSTRAINT IF EXISTS lt_topic_catalog_category_check;
25
+
26
+ ALTER TABLE lt_topic_catalog
27
+ ADD CONSTRAINT lt_topic_catalog_category_check
28
+ CHECK (category IN (
29
+ 'task','workflow','escalation','activity','knowledge','file','agent','app','milestone','surfaces'
30
+ ));
@@ -0,0 +1,9 @@
1
+ -- Migration 032: read-safe workflow flag
2
+ --
3
+ -- Marks a workflow as side-effect-free for external MCP callers: the
4
+ -- invoke_workflow_read_safe tool (manifest read_safe: true) starts only
5
+ -- workflows carrying this flag, extending the tool-manifest read-scope
6
+ -- contract to workflow invocation. Fail-closed: unset means not read-safe.
7
+
8
+ ALTER TABLE lt_config_workflows
9
+ ADD COLUMN IF NOT EXISTS read_safe BOOLEAN NOT NULL DEFAULT false;
@@ -64,6 +64,21 @@ export declare function publishActivityEvent(params: {
64
64
  activityName: string;
65
65
  data?: Record<string, any>;
66
66
  }): Promise<void>;
67
+ /**
68
+ * The dashboard-surface broadcast subject. Announcements publish here and the
69
+ * dashboard subscribes; the payload is the announcement row (small by
70
+ * nature). Delivery reaches every authenticated socket — role targeting is
71
+ * display scoping, never confidentiality.
72
+ */
73
+ export declare const ANNOUNCEMENT_TOPIC = "system.surfaces.dashboard";
74
+ /**
75
+ * Publish a dashboard announcement event.
76
+ * Subject: system.surfaces.dashboard (fixed — one surface, one channel)
77
+ */
78
+ export declare function publishAnnouncementEvent(params: {
79
+ type: 'announcement.created' | 'announcement.deleted';
80
+ announcement: Record<string, any>;
81
+ }): Promise<void>;
67
82
  /**
68
83
  * Publish a knowledge lifecycle event.
69
84
  * Subject: system.knowledge.{domain}.{action}
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ANNOUNCEMENT_TOPIC = void 0;
3
4
  exports.publishMilestoneEvent = publishMilestoneEvent;
4
5
  exports.publishTaskEvent = publishTaskEvent;
5
6
  exports.publishEscalationEvent = publishEscalationEvent;
6
7
  exports.publishActivityEvent = publishActivityEvent;
8
+ exports.publishAnnouncementEvent = publishAnnouncementEvent;
7
9
  exports.publishKnowledgeEvent = publishKnowledgeEvent;
8
10
  exports.publishFileEvent = publishFileEvent;
9
11
  exports.publishAgentEvent = publishAgentEvent;
@@ -104,6 +106,26 @@ function publishActivityEvent(params) {
104
106
  timestamp: new Date().toISOString(),
105
107
  });
106
108
  }
109
+ /**
110
+ * The dashboard-surface broadcast subject. Announcements publish here and the
111
+ * dashboard subscribes; the payload is the announcement row (small by
112
+ * nature). Delivery reaches every authenticated socket — role targeting is
113
+ * display scoping, never confidentiality.
114
+ */
115
+ exports.ANNOUNCEMENT_TOPIC = 'system.surfaces.dashboard';
116
+ /**
117
+ * Publish a dashboard announcement event.
118
+ * Subject: system.surfaces.dashboard (fixed — one surface, one channel)
119
+ */
120
+ function publishAnnouncementEvent(params) {
121
+ const action = params.type.split('.')[1];
122
+ return fireAndForget({
123
+ type: exports.ANNOUNCEMENT_TOPIC,
124
+ source: 'announcement',
125
+ data: { action, announcement: params.announcement },
126
+ timestamp: new Date().toISOString(),
127
+ });
128
+ }
107
129
  /**
108
130
  * Publish a knowledge lifecycle event.
109
131
  * Subject: system.knowledge.{domain}.{action}
@@ -43,6 +43,7 @@ exports.signToken = signToken;
43
43
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
44
44
  const config_1 = require("./config");
45
45
  const sso_1 = require("./sso");
46
+ const logger_1 = require("../lib/logger");
46
47
  const user_1 = require("../services/user");
47
48
  const sso_provision_1 = require("../services/user/sso-provision");
48
49
  const bot_api_key_1 = require("../services/auth/bot-api-key");
@@ -156,7 +157,10 @@ const requireAuth = async (req, res, next) => {
156
157
  const mw = _authMiddleware || createAuthMiddleware(new JwtAuthAdapter());
157
158
  return mw(req, res, next);
158
159
  }
159
- // SSO fallback: no Bearer, but host may have authenticated via cookies/headers
160
+ // SSO fallback: no Bearer, but host may have authenticated via cookies/headers.
161
+ // `res` is deliberately NOT passed to resolve here: this path runs on every
162
+ // cookie-bearing request, and ambient API traffic must never slide the host
163
+ // session — only the explicit exchange (login + gated keepalive beat) does.
160
164
  const ssoConfig = (0, sso_1.getSSOConfig)();
161
165
  if (ssoConfig) {
162
166
  try {
@@ -177,8 +181,10 @@ const requireAuth = async (req, res, next) => {
177
181
  return next();
178
182
  }
179
183
  }
180
- catch {
181
- // SSO resolve failed — fall through to 401
184
+ catch (err) {
185
+ // SSO resolve failed — fall through to 401, but leave a trace so host
186
+ // resolve errors are diagnosable.
187
+ logger_1.loggerRegistry.debug(`[long-tail] sso resolve failed on auth fallback: ${err?.message}`);
182
188
  }
183
189
  }
184
190
  // No Bearer, no SSO — delegate to standard middleware (returns 401)
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
@@ -0,0 +1,64 @@
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 api = __importStar(require("../api/announcements"));
38
+ const auth_1 = require("../modules/auth");
39
+ const router = (0, express_1.Router)();
40
+ /**
41
+ * Dashboard announcements. Publishing and removal are role-manager acts
42
+ * (superadmin, admin type, or engineer); any authenticated user reads their
43
+ * role-filtered slice. Targeting is display scoping — the live event
44
+ * broadcasts to every authenticated subscriber.
45
+ */
46
+ router.get('/', async (req, res) => {
47
+ const result = await api.listAnnouncements(req.auth);
48
+ res.status(result.status).json(result.data ?? { error: result.error });
49
+ });
50
+ router.post('/', auth_1.requireRoleManager, async (req, res) => {
51
+ const result = await api.createAnnouncement({
52
+ body: req.body?.body,
53
+ title: req.body?.title,
54
+ layout: req.body?.layout,
55
+ roles: req.body?.roles,
56
+ expiresAt: req.body?.expiresAt,
57
+ }, req.auth);
58
+ res.status(result.status).json(result.data ?? { error: result.error });
59
+ });
60
+ router.delete('/:id', auth_1.requireRoleManager, async (req, res) => {
61
+ const result = await api.deleteAnnouncement({ id: String(req.params.id) }, req.auth);
62
+ res.status(result.status).json(result.data ?? { error: result.error });
63
+ });
64
+ exports.default = router;
@@ -45,7 +45,12 @@ const router = (0, express_1.Router)();
45
45
  * login form with a transparent token exchange.
46
46
  */
47
47
  router.post('/sso', async (req, res) => {
48
- const result = await api.exchangeSSO(req);
48
+ const result = await api.exchangeSSO(req, res);
49
+ // A host's resolve may only set headers on `res`; if one violates the
50
+ // contract and writes the response, degrade to a skipped beat instead of
51
+ // a headers-after-send crash.
52
+ if (res.headersSent)
53
+ return;
49
54
  res.status(result.status).json(result.data ?? { error: result.error });
50
55
  });
51
56
  exports.default = router;
@@ -109,6 +109,7 @@ function registerListRoutes(router) {
109
109
  orderBy: jsonParam(req.query.orderBy),
110
110
  available: req.query.available != null ? req.query.available === 'true' : undefined,
111
111
  jeopardy: req.query.jeopardy === '1' || req.query.jeopardy === 'true' || undefined,
112
+ include: req.query.include,
112
113
  }, req.auth);
113
114
  res.status(result.status).json(result.data ?? { error: result.error });
114
115
  });
@@ -136,6 +137,7 @@ function registerListRoutes(router) {
136
137
  exists: jsonParam(req.query.exists),
137
138
  orderBy: jsonParam(req.query.orderBy),
138
139
  jeopardy: req.query.jeopardy === '1' || req.query.jeopardy === 'true' || undefined,
140
+ include: req.query.include,
139
141
  }, req.auth);
140
142
  res.status(result.status).json(result.data ?? { error: result.error });
141
143
  });
@@ -38,6 +38,7 @@ const topics_1 = __importDefault(require("./topics"));
38
38
  const nats_credentials_1 = __importDefault(require("./nats-credentials"));
39
39
  const scan_codes_1 = __importDefault(require("./scan-codes"));
40
40
  const domain_1 = __importDefault(require("./domain"));
41
+ const announcements_1 = __importDefault(require("./announcements"));
41
42
  const router = (0, express_1.Router)();
42
43
  // Public routes (no auth required — they handle their own auth)
43
44
  router.use('/auth', auth_2.default);
@@ -76,6 +77,7 @@ router.use('/capabilities', capabilities_1.default);
76
77
  router.use('/topics', topics_1.default);
77
78
  router.use('/scan-codes', scan_codes_1.default);
78
79
  router.use('/domain', domain_1.default);
80
+ router.use('/announcements', announcements_1.default);
79
81
  const overview_1 = __importDefault(require("./overview"));
80
82
  router.use('/overview', overview_1.default);
81
83
  const diagnostics_1 = __importDefault(require("./diagnostics"));
@@ -0,0 +1,30 @@
1
+ /**
2
+ * A dashboard announcement — a broadcast notice on the dashboard surface.
3
+ * Role targeting is display scoping only (live events reach every
4
+ * authenticated socket); bodies must never carry secrets.
5
+ */
6
+ export interface LTAnnouncement {
7
+ id: string;
8
+ title: string | null;
9
+ /** Markdown. */
10
+ body: string;
11
+ layout: string;
12
+ /** Empty = everyone; otherwise shown to holders of any named role. */
13
+ roles: string[];
14
+ created_by: string | null;
15
+ created_at: string;
16
+ expires_at: string;
17
+ }
18
+ /** Only the body is required; everything else has a liberal default (24h expiry). */
19
+ export declare function createAnnouncement(input: {
20
+ body: string;
21
+ title?: string;
22
+ layout?: string;
23
+ roles?: string[];
24
+ createdBy?: string;
25
+ expiresAt?: string;
26
+ }): Promise<LTAnnouncement>;
27
+ /** Active announcements visible to a viewer; null roles = the unscoped admin view. */
28
+ export declare function listActiveAnnouncements(userRoles: string[] | null): Promise<LTAnnouncement[]>;
29
+ /** Returns the deleted row so the caller can publish its removal, or null. */
30
+ export declare function deleteAnnouncement(id: string): Promise<LTAnnouncement | null>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAnnouncement = createAnnouncement;
4
+ exports.listActiveAnnouncements = listActiveAnnouncements;
5
+ exports.deleteAnnouncement = deleteAnnouncement;
6
+ const db_1 = require("../../lib/db");
7
+ const sql_1 = require("./sql");
8
+ /** Only the body is required; everything else has a liberal default (24h expiry). */
9
+ async function createAnnouncement(input) {
10
+ const { rows } = await (0, db_1.getPool)().query(sql_1.INSERT_ANNOUNCEMENT, [
11
+ input.title ?? null,
12
+ input.body,
13
+ input.layout ?? null,
14
+ input.roles ?? null,
15
+ input.createdBy ?? null,
16
+ input.expiresAt ?? null,
17
+ ]);
18
+ return rows[0];
19
+ }
20
+ /** Active announcements visible to a viewer; null roles = the unscoped admin view. */
21
+ async function listActiveAnnouncements(userRoles) {
22
+ const { rows } = await (0, db_1.getPool)().query(sql_1.LIST_ACTIVE_ANNOUNCEMENTS, [userRoles]);
23
+ return rows;
24
+ }
25
+ /** Returns the deleted row so the caller can publish its removal, or null. */
26
+ async function deleteAnnouncement(id) {
27
+ const { rows } = await (0, db_1.getPool)().query(sql_1.DELETE_ANNOUNCEMENT, [id]);
28
+ return rows[0] ?? null;
29
+ }
@@ -0,0 +1,8 @@
1
+ export declare const INSERT_ANNOUNCEMENT = "\n INSERT INTO lt_announcements (title, body, layout, roles, created_by, expires_at)\n VALUES ($1, $2, COALESCE($3, 'banner'), COALESCE($4::text[], '{}'), $5,\n COALESCE($6::timestamptz, NOW() + INTERVAL '24 hours'))\n RETURNING *";
2
+ /**
3
+ * Active announcements for a viewer. $1 = the viewer's role names, or NULL
4
+ * for the unscoped admin view. Untargeted rows (roles = '{}') reach everyone;
5
+ * targeted rows reach holders of any named role.
6
+ */
7
+ export declare const LIST_ACTIVE_ANNOUNCEMENTS = "\n SELECT * FROM lt_announcements\n WHERE expires_at > NOW()\n AND ($1::text[] IS NULL OR roles = '{}' OR roles && $1::text[])\n ORDER BY created_at DESC";
8
+ export declare const DELETE_ANNOUNCEMENT = "\n DELETE FROM lt_announcements WHERE id = $1\n RETURNING *";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ // ─── Announcement queries ────────────────────────────────────────────────────
3
+ // Liberal defaults live in the SQL so the service contract is self-describing:
4
+ // only the body is required; layout, targeting, and the 24-hour expiry fill in.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DELETE_ANNOUNCEMENT = exports.LIST_ACTIVE_ANNOUNCEMENTS = exports.INSERT_ANNOUNCEMENT = void 0;
7
+ exports.INSERT_ANNOUNCEMENT = `
8
+ INSERT INTO lt_announcements (title, body, layout, roles, created_by, expires_at)
9
+ VALUES ($1, $2, COALESCE($3, 'banner'), COALESCE($4::text[], '{}'), $5,
10
+ COALESCE($6::timestamptz, NOW() + INTERVAL '24 hours'))
11
+ RETURNING *`;
12
+ /**
13
+ * Active announcements for a viewer. $1 = the viewer's role names, or NULL
14
+ * for the unscoped admin view. Untargeted rows (roles = '{}') reach everyone;
15
+ * targeted rows reach holders of any named role.
16
+ */
17
+ exports.LIST_ACTIVE_ANNOUNCEMENTS = `
18
+ SELECT * FROM lt_announcements
19
+ WHERE expires_at > NOW()
20
+ AND ($1::text[] IS NULL OR roles = '{}' OR roles && $1::text[])
21
+ ORDER BY created_at DESC`;
22
+ exports.DELETE_ANNOUNCEMENT = `
23
+ DELETE FROM lt_announcements WHERE id = $1
24
+ RETURNING *`;
@@ -19,6 +19,7 @@ async function loadAllConfigs() {
19
19
  resolverSchema: c.resolver_schema ?? null,
20
20
  cronSchedule: c.cron_schedule ?? null,
21
21
  executeAs: c.execute_as ?? null,
22
+ readSafe: c.read_safe ?? false,
22
23
  });
23
24
  }
24
25
  return map;