@hotmeshio/long-tail 0.12.1 → 0.13.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 (234) hide show
  1. package/README.md +1 -0
  2. package/build/api/auth-sso.d.ts +6 -3
  3. package/build/api/auth-sso.js +6 -3
  4. package/build/api/escalations/helpers.js +4 -2
  5. package/build/api/settings.js +3 -0
  6. package/build/modules/auth.js +9 -3
  7. package/build/routes/auth-sso.js +6 -1
  8. package/build/services/agent/index.d.ts +11 -0
  9. package/build/services/agent/index.js +32 -0
  10. package/build/services/agent/sql.d.ts +7 -0
  11. package/build/services/agent/sql.js +32 -1
  12. package/build/services/agent/subscription-sql.d.ts +6 -0
  13. package/build/services/agent/subscription-sql.js +32 -1
  14. package/build/services/agent/subscriptions.d.ts +6 -0
  15. package/build/services/agent/subscriptions.js +23 -0
  16. package/build/services/config/index.d.ts +1 -1
  17. package/build/services/config/index.js +2 -1
  18. package/build/services/config/write.d.ts +10 -0
  19. package/build/services/config/write.js +49 -2
  20. package/build/services/domain/seed.d.ts +12 -5
  21. package/build/services/domain/seed.js +25 -6
  22. package/build/services/mcp/db.d.ts +16 -0
  23. package/build/services/mcp/db.js +24 -0
  24. package/build/services/mcp/sql.d.ts +8 -0
  25. package/build/services/mcp/sql.js +24 -1
  26. package/build/services/role/seed.d.ts +21 -0
  27. package/build/services/role/seed.js +113 -0
  28. package/build/services/role/sql.d.ts +8 -0
  29. package/build/services/role/sql.js +24 -1
  30. package/build/services/scan-code/index.d.ts +1 -1
  31. package/build/services/scan-code/index.js +3 -1
  32. package/build/services/scan-code/sql.d.ts +7 -0
  33. package/build/services/scan-code/sql.js +55 -1
  34. package/build/services/scan-code/write.d.ts +8 -0
  35. package/build/services/scan-code/write.js +23 -1
  36. package/build/services/topics/index.d.ts +2 -0
  37. package/build/services/topics/index.js +7 -0
  38. package/build/services/topics/sql.d.ts +2 -0
  39. package/build/services/topics/sql.js +5 -1
  40. package/build/services/topics/system-topics.d.ts +3 -2
  41. package/build/services/topics/system-topics.js +4 -3
  42. package/build/services/user/index.d.ts +1 -1
  43. package/build/services/user/index.js +2 -1
  44. package/build/services/user/roles.d.ts +8 -0
  45. package/build/services/user/roles.js +29 -0
  46. package/build/services/user/sql.d.ts +6 -0
  47. package/build/services/user/sql.js +9 -1
  48. package/build/services/user/sso-provision.js +14 -3
  49. package/build/start/apply-report.d.ts +26 -0
  50. package/build/start/apply-report.js +65 -0
  51. package/build/start/config.js +8 -1
  52. package/build/start/workers.js +222 -33
  53. package/build/tsconfig.tsbuildinfo +1 -1
  54. package/build/types/auth.d.ts +44 -4
  55. package/build/types/index.d.ts +1 -1
  56. package/build/types/startup.d.ts +160 -4
  57. package/dashboard/dist/assets/{AdminDashboard-DpTZG5EL.js → AdminDashboard-D2unnS2b.js} +2 -2
  58. package/dashboard/dist/assets/{AdminDashboard-DpTZG5EL.js.map → AdminDashboard-D2unnS2b.js.map} +1 -1
  59. package/dashboard/dist/assets/{AgentConfigPage-DVTL0NvC.js → AgentConfigPage-CBkf403g.js} +2 -2
  60. package/dashboard/dist/assets/{AgentConfigPage-DVTL0NvC.js.map → AgentConfigPage-CBkf403g.js.map} +1 -1
  61. package/dashboard/dist/assets/{AgentDetailPage-DOLKNPJl.js → AgentDetailPage-CAIU3yzo.js} +2 -2
  62. package/dashboard/dist/assets/{AgentDetailPage-DOLKNPJl.js.map → AgentDetailPage-CAIU3yzo.js.map} +1 -1
  63. package/dashboard/dist/assets/{AgentsPage-DiOZu6Xb.js → AgentsPage-qP9fWMyT.js} +2 -2
  64. package/dashboard/dist/assets/{AgentsPage-DiOZu6Xb.js.map → AgentsPage-qP9fWMyT.js.map} +1 -1
  65. package/dashboard/dist/assets/{AvailableEscalationsPage-CY5lfx27.js → AvailableEscalationsPage-DvWaiafI.js} +2 -2
  66. package/dashboard/dist/assets/{AvailableEscalationsPage-CY5lfx27.js.map → AvailableEscalationsPage-DvWaiafI.js.map} +1 -1
  67. package/dashboard/dist/assets/{BotPicker-ButjLJr2.js → BotPicker-BN-MKITV.js} +2 -2
  68. package/dashboard/dist/assets/{BotPicker-ButjLJr2.js.map → BotPicker-BN-MKITV.js.map} +1 -1
  69. package/dashboard/dist/assets/{CapabilitiesPage-CW_r2OlX.js → CapabilitiesPage-CJfmWokN.js} +2 -2
  70. package/dashboard/dist/assets/{CapabilitiesPage-CW_r2OlX.js.map → CapabilitiesPage-CJfmWokN.js.map} +1 -1
  71. package/dashboard/dist/assets/{CollapsibleSection-BOGRyCfm.js → CollapsibleSection-BvMHlHyt.js} +2 -2
  72. package/dashboard/dist/assets/{CollapsibleSection-BOGRyCfm.js.map → CollapsibleSection-BvMHlHyt.js.map} +1 -1
  73. package/dashboard/dist/assets/{CountdownTimer-UcHYZSg1.js → CountdownTimer-By4rbMDN.js} +2 -2
  74. package/dashboard/dist/assets/{CountdownTimer-UcHYZSg1.js.map → CountdownTimer-By4rbMDN.js.map} +1 -1
  75. package/dashboard/dist/assets/{CredentialsPage-A7OFYVsX.js → CredentialsPage-2TvvRwGJ.js} +2 -2
  76. package/dashboard/dist/assets/{CredentialsPage-A7OFYVsX.js.map → CredentialsPage-2TvvRwGJ.js.map} +1 -1
  77. package/dashboard/dist/assets/{CronLabel-Dve2Udsm.js → CronLabel-HxmsDSnV.js} +2 -2
  78. package/dashboard/dist/assets/{CronLabel-Dve2Udsm.js.map → CronLabel-HxmsDSnV.js.map} +1 -1
  79. package/dashboard/dist/assets/{CustomDurationPicker-BoPrA-Em.js → CustomDurationPicker-8Ao-1pKA.js} +2 -2
  80. package/dashboard/dist/assets/{CustomDurationPicker-BoPrA-Em.js.map → CustomDurationPicker-8Ao-1pKA.js.map} +1 -1
  81. package/dashboard/dist/assets/{ElapsedCell-B114P5mb.js → ElapsedCell-BkRu9Xpd.js} +2 -2
  82. package/dashboard/dist/assets/{ElapsedCell-B114P5mb.js.map → ElapsedCell-BkRu9Xpd.js.map} +1 -1
  83. package/dashboard/dist/assets/{EntityTimelinePanel-BqDWyOa9.js → EntityTimelinePanel--E6hLMCM.js} +2 -2
  84. package/dashboard/dist/assets/{EntityTimelinePanel-BqDWyOa9.js.map → EntityTimelinePanel--E6hLMCM.js.map} +1 -1
  85. package/dashboard/dist/assets/{EscalationListSchemaPage-DyyTyghx.js → EscalationListSchemaPage-CdFtqEEX.js} +2 -2
  86. package/dashboard/dist/assets/{EscalationListSchemaPage-DyyTyghx.js.map → EscalationListSchemaPage-CdFtqEEX.js.map} +1 -1
  87. package/dashboard/dist/assets/{EscalationSchemaPage-DLQG6EXQ.js → EscalationSchemaPage-BsjS2axz.js} +2 -2
  88. package/dashboard/dist/assets/{EscalationSchemaPage-DLQG6EXQ.js.map → EscalationSchemaPage-BsjS2axz.js.map} +1 -1
  89. package/dashboard/dist/assets/{EscalationsOverview-RrbkkEU0.js → EscalationsOverview-FL-xteVc.js} +2 -2
  90. package/dashboard/dist/assets/{EscalationsOverview-RrbkkEU0.js.map → EscalationsOverview-FL-xteVc.js.map} +1 -1
  91. package/dashboard/dist/assets/{EventTable-DOxubt7O.js → EventTable-BOcgZ78i.js} +2 -2
  92. package/dashboard/dist/assets/{EventTable-DOxubt7O.js.map → EventTable-BOcgZ78i.js.map} +1 -1
  93. package/dashboard/dist/assets/{FilterBar-y659Gc3X.js → FilterBar-DfCiCmm-.js} +2 -2
  94. package/dashboard/dist/assets/{FilterBar-y659Gc3X.js.map → FilterBar-DfCiCmm-.js.map} +1 -1
  95. package/dashboard/dist/assets/{GraphInvokePage-oHLgSAl6.js → GraphInvokePage-DfVeiN-8.js} +2 -2
  96. package/dashboard/dist/assets/{GraphInvokePage-oHLgSAl6.js.map → GraphInvokePage-DfVeiN-8.js.map} +1 -1
  97. package/dashboard/dist/assets/{HomePage-C9FUpD7x.js → HomePage-C2IhF9WB.js} +2 -2
  98. package/dashboard/dist/assets/{HomePage-C9FUpD7x.js.map → HomePage-C2IhF9WB.js.map} +1 -1
  99. package/dashboard/dist/assets/{ListToolbar-DfpSgWYU.js → ListToolbar-DA0PTOl5.js} +2 -2
  100. package/dashboard/dist/assets/{ListToolbar-DfpSgWYU.js.map → ListToolbar-DA0PTOl5.js.map} +1 -1
  101. package/dashboard/dist/assets/{McpOverview-6Ubpr9QS.js → McpOverview-DstPch5M.js} +2 -2
  102. package/dashboard/dist/assets/{McpOverview-6Ubpr9QS.js.map → McpOverview-DstPch5M.js.map} +1 -1
  103. package/dashboard/dist/assets/{McpQueryDetailPage-DFt-vQEp.js → McpQueryDetailPage-Csv0PKE0.js} +2 -2
  104. package/dashboard/dist/assets/{McpQueryDetailPage-DFt-vQEp.js.map → McpQueryDetailPage-Csv0PKE0.js.map} +1 -1
  105. package/dashboard/dist/assets/{McpQueryPage-DQiG0AE3.js → McpQueryPage-DxmqCkly.js} +2 -2
  106. package/dashboard/dist/assets/{McpQueryPage-DQiG0AE3.js.map → McpQueryPage-DxmqCkly.js.map} +1 -1
  107. package/dashboard/dist/assets/{McpRunDetailPage-BgsSegyP.js → McpRunDetailPage-CcJOlp_B.js} +2 -2
  108. package/dashboard/dist/assets/{McpRunDetailPage-BgsSegyP.js.map → McpRunDetailPage-CcJOlp_B.js.map} +1 -1
  109. package/dashboard/dist/assets/{McpRunsPage-tCMxspqS.js → McpRunsPage-BZCR043j.js} +2 -2
  110. package/dashboard/dist/assets/{McpRunsPage-tCMxspqS.js.map → McpRunsPage-BZCR043j.js.map} +1 -1
  111. package/dashboard/dist/assets/{OperationsPage-DUaRmEPa.js → OperationsPage-DMsPXITh.js} +2 -2
  112. package/dashboard/dist/assets/{OperationsPage-DUaRmEPa.js.map → OperationsPage-DMsPXITh.js.map} +1 -1
  113. package/dashboard/dist/assets/{OperatorDashboard-CayyjMcf.js → OperatorDashboard-DSloftQ5.js} +2 -2
  114. package/dashboard/dist/assets/{OperatorDashboard-CayyjMcf.js.map → OperatorDashboard-DSloftQ5.js.map} +1 -1
  115. package/dashboard/dist/assets/{PersonaDetailPage-DBcxfdbN.js → PersonaDetailPage-jDVRCLbU.js} +2 -2
  116. package/dashboard/dist/assets/{PersonaDetailPage-DBcxfdbN.js.map → PersonaDetailPage-jDVRCLbU.js.map} +1 -1
  117. package/dashboard/dist/assets/{PersonasPage-DPq0HQAB.js → PersonasPage-DnDDwXoy.js} +2 -2
  118. package/dashboard/dist/assets/{PersonasPage-DPq0HQAB.js.map → PersonasPage-DnDDwXoy.js.map} +1 -1
  119. package/dashboard/dist/assets/{ProcessDetailPage-QQZNNNMw.js → ProcessDetailPage-CfAUU6q2.js} +2 -2
  120. package/dashboard/dist/assets/{ProcessDetailPage-QQZNNNMw.js.map → ProcessDetailPage-CfAUU6q2.js.map} +1 -1
  121. package/dashboard/dist/assets/{ProcessesListPage-UKQMJ4Te.js → ProcessesListPage-CnAXzaVv.js} +2 -2
  122. package/dashboard/dist/assets/{ProcessesListPage-UKQMJ4Te.js.map → ProcessesListPage-CnAXzaVv.js.map} +1 -1
  123. package/dashboard/dist/assets/{RoleDetailPage-DT-3sSRD.js → RoleDetailPage-Dg1p6Qz_.js} +2 -2
  124. package/dashboard/dist/assets/{RoleDetailPage-DT-3sSRD.js.map → RoleDetailPage-Dg1p6Qz_.js.map} +1 -1
  125. package/dashboard/dist/assets/{RolesPage-DZg4niqL.js → RolesPage-DeRVQux8.js} +2 -2
  126. package/dashboard/dist/assets/{RolesPage-DZg4niqL.js.map → RolesPage-DeRVQux8.js.map} +1 -1
  127. package/dashboard/dist/assets/{RunAsSelector-DkcNR7L6.js → RunAsSelector-BFNqQGuG.js} +2 -2
  128. package/dashboard/dist/assets/{RunAsSelector-DkcNR7L6.js.map → RunAsSelector-BFNqQGuG.js.map} +1 -1
  129. package/dashboard/dist/assets/{ScanCodesPage-U-alpwWF.js → ScanCodesPage-D0GOdk5m.js} +2 -2
  130. package/dashboard/dist/assets/{ScanCodesPage-U-alpwWF.js.map → ScanCodesPage-D0GOdk5m.js.map} +1 -1
  131. package/dashboard/dist/assets/{ScanSchemeDetailPage-lXwlcraS.js → ScanSchemeDetailPage-vFqoe_P4.js} +2 -2
  132. package/dashboard/dist/assets/{ScanSchemeDetailPage-lXwlcraS.js.map → ScanSchemeDetailPage-vFqoe_P4.js.map} +1 -1
  133. package/dashboard/dist/assets/{ScanStationPage-DYMiTp-v.js → ScanStationPage-DH1ynTX9.js} +2 -2
  134. package/dashboard/dist/assets/{ScanStationPage-DYMiTp-v.js.map → ScanStationPage-DH1ynTX9.js.map} +1 -1
  135. package/dashboard/dist/assets/{StickyPagination-D896Wquq.js → StickyPagination-B99hVu95.js} +2 -2
  136. package/dashboard/dist/assets/{StickyPagination-D896Wquq.js.map → StickyPagination-B99hVu95.js.map} +1 -1
  137. package/dashboard/dist/assets/{StreamMessageDetail-DIh5qEGJ.js → StreamMessageDetail-DcDGISrv.js} +2 -2
  138. package/dashboard/dist/assets/{StreamMessageDetail-DIh5qEGJ.js.map → StreamMessageDetail-DcDGISrv.js.map} +1 -1
  139. package/dashboard/dist/assets/{SwimlaneTimeline-B8SucVj5.js → SwimlaneTimeline-BP3mSQAg.js} +2 -2
  140. package/dashboard/dist/assets/{SwimlaneTimeline-B8SucVj5.js.map → SwimlaneTimeline-BP3mSQAg.js.map} +1 -1
  141. package/dashboard/dist/assets/{TaskDetailPage-Di-z_ZE2.js → TaskDetailPage-_XWLJzt-.js} +2 -2
  142. package/dashboard/dist/assets/{TaskDetailPage-Di-z_ZE2.js.map → TaskDetailPage-_XWLJzt-.js.map} +1 -1
  143. package/dashboard/dist/assets/{TasksListPage-ClHGEdin.js → TasksListPage-iGriKiO2.js} +2 -2
  144. package/dashboard/dist/assets/{TasksListPage-ClHGEdin.js.map → TasksListPage-iGriKiO2.js.map} +1 -1
  145. package/dashboard/dist/assets/{TimeAgo-BSDHd9Xo.js → TimeAgo-BO33VeFl.js} +2 -2
  146. package/dashboard/dist/assets/{TimeAgo-BSDHd9Xo.js.map → TimeAgo-BO33VeFl.js.map} +1 -1
  147. package/dashboard/dist/assets/{TimestampCell-WQL3FxWl.js → TimestampCell-KAjX7w35.js} +2 -2
  148. package/dashboard/dist/assets/{TimestampCell-WQL3FxWl.js.map → TimestampCell-KAjX7w35.js.map} +1 -1
  149. package/dashboard/dist/assets/{ToolTestPanel-IVIkqZTi.js → ToolTestPanel-BchG2yC6.js} +2 -2
  150. package/dashboard/dist/assets/{ToolTestPanel-IVIkqZTi.js.map → ToolTestPanel-BchG2yC6.js.map} +1 -1
  151. package/dashboard/dist/assets/{TopicDetailPage-BOasQo68.js → TopicDetailPage-BaK8H0o1.js} +2 -2
  152. package/dashboard/dist/assets/{TopicDetailPage-BOasQo68.js.map → TopicDetailPage-BaK8H0o1.js.map} +1 -1
  153. package/dashboard/dist/assets/{TopicsPage-DV_orf_V.js → TopicsPage-DEyvm669.js} +2 -2
  154. package/dashboard/dist/assets/{TopicsPage-DV_orf_V.js.map → TopicsPage-DEyvm669.js.map} +1 -1
  155. package/dashboard/dist/assets/{UserName-rshjKBtm.js → UserName-BV6SKI9P.js} +2 -2
  156. package/dashboard/dist/assets/{UserName-rshjKBtm.js.map → UserName-BV6SKI9P.js.map} +1 -1
  157. package/dashboard/dist/assets/{WorkflowExecutionPage-BpNGLwbK.js → WorkflowExecutionPage-1sKoEFNC.js} +2 -2
  158. package/dashboard/dist/assets/{WorkflowExecutionPage-BpNGLwbK.js.map → WorkflowExecutionPage-1sKoEFNC.js.map} +1 -1
  159. package/dashboard/dist/assets/{WorkflowsDashboard-BAXt8gv_.js → WorkflowsDashboard-YTHDZZOD.js} +2 -2
  160. package/dashboard/dist/assets/{WorkflowsDashboard-BAXt8gv_.js.map → WorkflowsDashboard-YTHDZZOD.js.map} +1 -1
  161. package/dashboard/dist/assets/{WorkflowsOverview-DvOyzL6y.js → WorkflowsOverview-ucXPLTtm.js} +2 -2
  162. package/dashboard/dist/assets/{WorkflowsOverview-DvOyzL6y.js.map → WorkflowsOverview-ucXPLTtm.js.map} +1 -1
  163. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CraijGy6.js → YamlWorkflowDetailPage-C_RTZKqZ.js} +2 -2
  164. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CraijGy6.js.map → YamlWorkflowDetailPage-C_RTZKqZ.js.map} +1 -1
  165. package/dashboard/dist/assets/{YamlWorkflowsPage-CNz3ptmj.js → YamlWorkflowsPage-Usid3w2W.js} +2 -2
  166. package/dashboard/dist/assets/{YamlWorkflowsPage-CNz3ptmj.js.map → YamlWorkflowsPage-Usid3w2W.js.map} +1 -1
  167. package/dashboard/dist/assets/{agents-BswSJR-t.js → agents-BTDsRK8e.js} +2 -2
  168. package/dashboard/dist/assets/{agents-BswSJR-t.js.map → agents-BTDsRK8e.js.map} +1 -1
  169. package/dashboard/dist/assets/{bots-VzlLx_GQ.js → bots-DxLrfdfr.js} +2 -2
  170. package/dashboard/dist/assets/{bots-VzlLx_GQ.js.map → bots-DxLrfdfr.js.map} +1 -1
  171. package/dashboard/dist/assets/{capabilities-B0bNlTTA.js → capabilities-DbTmeW-S.js} +2 -2
  172. package/dashboard/dist/assets/{capabilities-B0bNlTTA.js.map → capabilities-DbTmeW-S.js.map} +1 -1
  173. package/dashboard/dist/assets/{controlplane-DBESTVZS.js → controlplane-CEBntAL4.js} +2 -2
  174. package/dashboard/dist/assets/{controlplane-DBESTVZS.js.map → controlplane-CEBntAL4.js.map} +1 -1
  175. package/dashboard/dist/assets/{escalation-columns-CoqsCdbP.js → escalation-columns-Carqdwoh.js} +2 -2
  176. package/dashboard/dist/assets/{escalation-columns-CoqsCdbP.js.map → escalation-columns-Carqdwoh.js.map} +1 -1
  177. package/dashboard/dist/assets/{index-DUfdCp8e.js → index-B2hz0pUh.js} +2 -2
  178. package/dashboard/dist/assets/{index-DUfdCp8e.js.map → index-B2hz0pUh.js.map} +1 -1
  179. package/dashboard/dist/assets/{index-DJS-hvDt.js → index-B9m7fA3M.js} +2 -2
  180. package/dashboard/dist/assets/{index-DJS-hvDt.js.map → index-B9m7fA3M.js.map} +1 -1
  181. package/dashboard/dist/assets/{index-C_lA7ghl.js → index-BhapT-Vl.js} +2 -2
  182. package/dashboard/dist/assets/{index-C_lA7ghl.js.map → index-BhapT-Vl.js.map} +1 -1
  183. package/dashboard/dist/assets/{index-DsDFZzqr.js → index-Bqm4zu46.js} +2 -2
  184. package/dashboard/dist/assets/{index-DsDFZzqr.js.map → index-Bqm4zu46.js.map} +1 -1
  185. package/dashboard/dist/assets/{index-Cd7jZylO.js → index-C0hSttF5.js} +2 -2
  186. package/dashboard/dist/assets/{index-Cd7jZylO.js.map → index-C0hSttF5.js.map} +1 -1
  187. package/dashboard/dist/assets/{index-ByUjwu37.js → index-CDkg6iOE.js} +2 -2
  188. package/dashboard/dist/assets/{index-ByUjwu37.js.map → index-CDkg6iOE.js.map} +1 -1
  189. package/dashboard/dist/assets/{index-Ci4lxPwS.js → index-CVBBkW8V.js} +2 -2
  190. package/dashboard/dist/assets/{index-Ci4lxPwS.js.map → index-CVBBkW8V.js.map} +1 -1
  191. package/dashboard/dist/assets/{index-DYDcjn-b.js → index-CgIBjZta.js} +2 -2
  192. package/dashboard/dist/assets/{index-DYDcjn-b.js.map → index-CgIBjZta.js.map} +1 -1
  193. package/dashboard/dist/assets/{index-Cqrp5B5S.js → index-DBXm49S6.js} +25 -25
  194. package/dashboard/dist/assets/index-DBXm49S6.js.map +1 -0
  195. package/dashboard/dist/assets/{index-BBXmIWKx.js → index-De8iV1y2.js} +2 -2
  196. package/dashboard/dist/assets/{index-BBXmIWKx.js.map → index-De8iV1y2.js.map} +1 -1
  197. package/dashboard/dist/assets/{index-D8ljRGIb.js → index-DsgjFRvA.js} +2 -2
  198. package/dashboard/dist/assets/{index-D8ljRGIb.js.map → index-DsgjFRvA.js.map} +1 -1
  199. package/dashboard/dist/assets/{index-BLzwfbZV.js → index-kes8V4Xw.js} +2 -2
  200. package/dashboard/dist/assets/{index-BLzwfbZV.js.map → index-kes8V4Xw.js.map} +1 -1
  201. package/dashboard/dist/assets/{index-CALocCAr.js → index-nwLh3CK2.js} +2 -2
  202. package/dashboard/dist/assets/{index-CALocCAr.js.map → index-nwLh3CK2.js.map} +1 -1
  203. package/dashboard/dist/assets/{knowledge-DB2DgDa_.js → knowledge-oFYAanUp.js} +2 -2
  204. package/dashboard/dist/assets/{knowledge-DB2DgDa_.js.map → knowledge-oFYAanUp.js.map} +1 -1
  205. package/dashboard/dist/assets/{mcp-D72yCeuf.js → mcp-C9Kw4Ow8.js} +2 -2
  206. package/dashboard/dist/assets/{mcp-D72yCeuf.js.map → mcp-C9Kw4Ow8.js.map} +1 -1
  207. package/dashboard/dist/assets/{mcp-query-Cyyc_0E8.js → mcp-query-BwzpZ91Z.js} +2 -2
  208. package/dashboard/dist/assets/{mcp-query-Cyyc_0E8.js.map → mcp-query-BwzpZ91Z.js.map} +1 -1
  209. package/dashboard/dist/assets/{personas-xMDV7yXb.js → personas-D5ehmtRb.js} +2 -2
  210. package/dashboard/dist/assets/{personas-xMDV7yXb.js.map → personas-D5ehmtRb.js.map} +1 -1
  211. package/dashboard/dist/assets/{pipelines-mlxfmi6m.js → pipelines-xgPKGEdD.js} +2 -2
  212. package/dashboard/dist/assets/{pipelines-mlxfmi6m.js.map → pipelines-xgPKGEdD.js.map} +1 -1
  213. package/dashboard/dist/assets/{tasks-CxgOp_9H.js → tasks-CLyrl-MU.js} +2 -2
  214. package/dashboard/dist/assets/{tasks-CxgOp_9H.js.map → tasks-CLyrl-MU.js.map} +1 -1
  215. package/dashboard/dist/assets/{topics-CFb_L0Vs.js → topics-B_gO7CQ0.js} +2 -2
  216. package/dashboard/dist/assets/{topics-CFb_L0Vs.js.map → topics-B_gO7CQ0.js.map} +1 -1
  217. package/dashboard/dist/assets/{useEventHooks-nC5kH-QW.js → useEventHooks-BdWYm63U.js} +2 -2
  218. package/dashboard/dist/assets/{useEventHooks-nC5kH-QW.js.map → useEventHooks-BdWYm63U.js.map} +1 -1
  219. package/dashboard/dist/assets/{useNamespace-DQeDgRFR.js → useNamespace-C238M4Qn.js} +2 -2
  220. package/dashboard/dist/assets/{useNamespace-DQeDgRFR.js.map → useNamespace-C238M4Qn.js.map} +1 -1
  221. package/dashboard/dist/assets/{useYamlActivityEvents-BuGC3oBE.js → useYamlActivityEvents-B2ryEK4S.js} +2 -2
  222. package/dashboard/dist/assets/{useYamlActivityEvents-BuGC3oBE.js.map → useYamlActivityEvents-B2ryEK4S.js.map} +1 -1
  223. package/dashboard/dist/assets/{users-BZUTtM_6.js → users-BFaTe6Mt.js} +2 -2
  224. package/dashboard/dist/assets/{users-BZUTtM_6.js.map → users-BFaTe6Mt.js.map} +1 -1
  225. package/dashboard/dist/assets/{workflows-DWhaZWVK.js → workflows-DXz7tZxp.js} +2 -2
  226. package/dashboard/dist/assets/{workflows-DWhaZWVK.js.map → workflows-DXz7tZxp.js.map} +1 -1
  227. package/dashboard/dist/assets/{yaml-workflows-C1TeDIIk.js → yaml-workflows-u3xuRAnS.js} +2 -2
  228. package/dashboard/dist/assets/{yaml-workflows-C1TeDIIk.js.map → yaml-workflows-u3xuRAnS.js.map} +1 -1
  229. package/dashboard/dist/index.html +1 -1
  230. package/docs/auth.md +26 -1
  231. package/docs/code-owned-configuration.md +158 -0
  232. package/docs/scan-codes.md +24 -0
  233. package/package.json +1 -1
  234. package/dashboard/dist/assets/index-Cqrp5B5S.js.map +0 -1
@@ -10,6 +10,7 @@ exports.listMcpServers = listMcpServers;
10
10
  exports.getAutoConnectServers = getAutoConnectServers;
11
11
  exports.findServersByTags = findServersByTags;
12
12
  exports.seedMcpServer = seedMcpServer;
13
+ exports.applyMcpServer = applyMcpServer;
13
14
  exports.cleanStaleBuiltinServers = cleanStaleBuiltinServers;
14
15
  const db_1 = require("../../lib/db");
15
16
  const logger_1 = require("../../lib/logger");
@@ -190,6 +191,29 @@ async function seedMcpServer(input) {
190
191
  }
191
192
  return inserted;
192
193
  }
194
+ /**
195
+ * Apply an MCP server declaration at startup (code is source of truth).
196
+ * Config fields — description, tags, category, compile hints, credential
197
+ * providers — are written when they differ; runtime state (tool manifest,
198
+ * connection status) is never touched. Returns 'applied' when the row was
199
+ * inserted or updated, 'unchanged' when the declaration already matches.
200
+ */
201
+ async function applyMcpServer(input) {
202
+ const pool = (0, db_1.getPool)();
203
+ const { rowCount } = await pool.query(sql_1.APPLY_MCP_SERVER, [
204
+ input.name,
205
+ input.description || null,
206
+ 'stdio',
207
+ JSON.stringify({ builtin: true, process: 'in-memory' }),
208
+ JSON.stringify(input.toolManifest || []),
209
+ JSON.stringify({ builtin: true }),
210
+ input.tags || [],
211
+ input.compileHints || null,
212
+ input.credentialProviders || [],
213
+ input.category || null,
214
+ ]);
215
+ return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
216
+ }
193
217
  /**
194
218
  * Remove builtin MCP servers that are no longer declared in factory config.
195
219
  */
@@ -19,3 +19,11 @@ export declare const DELETE_STALE_BUILTIN_SERVERS = "\n DELETE FROM lt_mcp_serv
19
19
  export declare const UPSERT_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, NOW())\n ON CONFLICT (name) DO UPDATE SET\n tool_manifest = EXCLUDED.tool_manifest,\n metadata = EXCLUDED.metadata,\n description = EXCLUDED.description,\n tags = EXCLUDED.tags,\n compile_hints = EXCLUDED.compile_hints,\n credential_providers = EXCLUDED.credential_providers,\n status = 'connected',\n last_connected_at = NOW()";
20
20
  /** Seed — insert-if-absent. DB is source of truth after first boot. */
21
21
  export declare const SEED_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())\n ON CONFLICT (name) DO NOTHING";
22
+ /**
23
+ * Apply — code is source of truth for the CONFIG fields only. On conflict the
24
+ * update rewrites description/tags/category/compile_hints/credential_providers
25
+ * and leaves runtime state (tool_manifest, status, last_connected_at,
26
+ * transport_config) untouched; the IS DISTINCT FROM guard makes an unchanged
27
+ * declaration a zero-row no-op. `(xmax = 0)` distinguishes insert from update.
28
+ */
29
+ export declare const APPLY_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())\n ON CONFLICT (name) DO UPDATE SET\n description = EXCLUDED.description,\n tags = EXCLUDED.tags,\n category = EXCLUDED.category,\n compile_hints = EXCLUDED.compile_hints,\n credential_providers = EXCLUDED.credential_providers\n WHERE (lt_mcp_servers.description, lt_mcp_servers.tags, lt_mcp_servers.category,\n lt_mcp_servers.compile_hints, lt_mcp_servers.credential_providers)\n IS DISTINCT FROM\n (EXCLUDED.description, EXCLUDED.tags, EXCLUDED.category,\n EXCLUDED.compile_hints, EXCLUDED.credential_providers)\n RETURNING (xmax = 0) AS inserted";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // ─── MCP server CRUD ────────────────────────────────────────────────────────
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.SEED_MCP_SERVER = exports.UPSERT_MCP_SERVER = exports.DELETE_STALE_BUILTIN_SERVERS = exports.HEALTH_DURABLE_WORKFLOWS = exports.HEALTH_WORKFLOW_CONFIGS = exports.HEALTH_COMPILED_WORKFLOWS = exports.HEALTH_MCP_SERVER_LIST = exports.HEALTH_MCP_SERVERS = exports.HEALTH_RECENT_ACTIVITY = exports.HEALTH_ACTIVE_WORKFLOW_TYPES = exports.HEALTH_ESCALATION_COUNTS = exports.HEALTH_TASK_COUNTS = exports.GET_AUTO_CONNECT_SERVERS = exports.UPDATE_STATUS = exports.UPDATE_STATUS_CONNECTED = exports.DELETE_MCP_SERVER = exports.GET_MCP_SERVER_BY_NAME = exports.GET_MCP_SERVER = exports.CREATE_MCP_SERVER = void 0;
4
+ exports.APPLY_MCP_SERVER = exports.SEED_MCP_SERVER = exports.UPSERT_MCP_SERVER = exports.DELETE_STALE_BUILTIN_SERVERS = exports.HEALTH_DURABLE_WORKFLOWS = exports.HEALTH_WORKFLOW_CONFIGS = exports.HEALTH_COMPILED_WORKFLOWS = exports.HEALTH_MCP_SERVER_LIST = exports.HEALTH_MCP_SERVERS = exports.HEALTH_RECENT_ACTIVITY = exports.HEALTH_ACTIVE_WORKFLOW_TYPES = exports.HEALTH_ESCALATION_COUNTS = exports.HEALTH_TASK_COUNTS = exports.GET_AUTO_CONNECT_SERVERS = exports.UPDATE_STATUS = exports.UPDATE_STATUS_CONNECTED = exports.DELETE_MCP_SERVER = exports.GET_MCP_SERVER_BY_NAME = exports.GET_MCP_SERVER = exports.CREATE_MCP_SERVER = void 0;
5
5
  exports.CREATE_MCP_SERVER = `
6
6
  INSERT INTO lt_mcp_servers
7
7
  (name, description, transport_type, transport_config, auto_connect, metadata, tags, compile_hints, credential_providers)
@@ -97,3 +97,26 @@ exports.SEED_MCP_SERVER = `
97
97
  (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)
98
98
  VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())
99
99
  ON CONFLICT (name) DO NOTHING`;
100
+ /**
101
+ * Apply — code is source of truth for the CONFIG fields only. On conflict the
102
+ * update rewrites description/tags/category/compile_hints/credential_providers
103
+ * and leaves runtime state (tool_manifest, status, last_connected_at,
104
+ * transport_config) untouched; the IS DISTINCT FROM guard makes an unchanged
105
+ * declaration a zero-row no-op. `(xmax = 0)` distinguishes insert from update.
106
+ */
107
+ exports.APPLY_MCP_SERVER = `
108
+ INSERT INTO lt_mcp_servers
109
+ (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)
110
+ VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())
111
+ ON CONFLICT (name) DO UPDATE SET
112
+ description = EXCLUDED.description,
113
+ tags = EXCLUDED.tags,
114
+ category = EXCLUDED.category,
115
+ compile_hints = EXCLUDED.compile_hints,
116
+ credential_providers = EXCLUDED.credential_providers
117
+ WHERE (lt_mcp_servers.description, lt_mcp_servers.tags, lt_mcp_servers.category,
118
+ lt_mcp_servers.compile_hints, lt_mcp_servers.credential_providers)
119
+ IS DISTINCT FROM
120
+ (EXCLUDED.description, EXCLUDED.tags, EXCLUDED.category,
121
+ EXCLUDED.compile_hints, EXCLUDED.credential_providers)
122
+ RETURNING (xmax = 0) AS inserted`;
@@ -0,0 +1,21 @@
1
+ import type { LTRoleConfig } from '../../types/startup';
2
+ export type RoleApplyOutcome = 'applied' | 'unchanged' | 'db-owned';
3
+ /** Recorded on schema snapshots written by the startup apply. */
4
+ export declare const STARTUP_CHANGE_SUMMARY = "startup apply (code)";
5
+ /**
6
+ * Roles carrying real configuration (title or form schema) — the candidate
7
+ * set for the startup orphan report. Bare FK-ensured rows are excluded.
8
+ */
9
+ export declare function listConfiguredRoles(): Promise<string[]>;
10
+ /**
11
+ * Register one declared role at startup.
12
+ *
13
+ * The role is created if missing. Under code ownership its declared fields
14
+ * are compared against the stored row and written through the versioned
15
+ * PATCH path when they differ — a changed form/metadata schema advances the
16
+ * role's schema version and snapshots the pair; an unchanged declaration is
17
+ * a no-op. Under db ownership the metadata is written exactly once (at
18
+ * creation); afterwards the DB owns the row and drift is warn-logged only.
19
+ * Escalation targets use replace semantics when declared.
20
+ */
21
+ export declare function applyRoleConfig(cfg: LTRoleConfig, codeOwned: boolean): Promise<RoleApplyOutcome>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.STARTUP_CHANGE_SUMMARY = void 0;
4
+ exports.listConfiguredRoles = listConfiguredRoles;
5
+ exports.applyRoleConfig = applyRoleConfig;
6
+ const node_util_1 = require("node:util");
7
+ const db_1 = require("../../lib/db");
8
+ const logger_1 = require("../../lib/logger");
9
+ const index_1 = require("./index");
10
+ const sql_1 = require("./sql");
11
+ /** Recorded on schema snapshots written by the startup apply. */
12
+ exports.STARTUP_CHANGE_SUMMARY = 'startup apply (code)';
13
+ /** Metadata fields shared 1:1 between LTRoleConfig and UpdateRoleInput. */
14
+ const METADATA_FIELDS = [
15
+ 'title', 'description', 'form_schema', 'metadata_schema', 'list_schema',
16
+ 'properties', 'ops_visible', 'ops_home_default', 'parent_role',
17
+ 'upstream_roles', 'default_pins', 'enforce_schema', 'sla_minutes',
18
+ 'target_per_hour', 'worker_count', 'priority_threshold_minutes',
19
+ 'priority_facet', 'entity_facet', 'entity_state_source',
20
+ ];
21
+ /**
22
+ * Compare one declared field against the stored row. jsonb round-trips lose
23
+ * key order, so structured values must be compared as parsed values — never
24
+ * by string. Arrays compare order-insensitively (sorted).
25
+ */
26
+ function fieldDiffers(field, declared, row) {
27
+ const stored = row[field];
28
+ if (Array.isArray(declared)) {
29
+ const a = [...declared].sort();
30
+ const b = Array.isArray(stored) ? [...stored].sort() : [];
31
+ return !(0, node_util_1.isDeepStrictEqual)(a, b);
32
+ }
33
+ if (declared !== null && typeof declared === 'object') {
34
+ return !(0, node_util_1.isDeepStrictEqual)(declared, stored ?? null);
35
+ }
36
+ // Numeric columns round-trip as strings from the driver — compare as numbers
37
+ // or every declared dial would read as changed on every boot.
38
+ if (typeof declared === 'number') {
39
+ return stored == null || Number(stored) !== declared;
40
+ }
41
+ return declared !== (stored ?? undefined);
42
+ }
43
+ /** The declared fields that differ from the stored row (PATCH-shaped). */
44
+ function diffDeclaredFields(cfg, row) {
45
+ const changed = {};
46
+ for (const field of METADATA_FIELDS) {
47
+ const declared = cfg[field];
48
+ if (declared === undefined)
49
+ continue;
50
+ if (fieldDiffers(field, declared, row)) {
51
+ changed[field] = declared;
52
+ }
53
+ }
54
+ return changed;
55
+ }
56
+ /**
57
+ * Roles carrying real configuration (title or form schema) — the candidate
58
+ * set for the startup orphan report. Bare FK-ensured rows are excluded.
59
+ */
60
+ async function listConfiguredRoles() {
61
+ const pool = (0, db_1.getPool)();
62
+ const { rows } = await pool.query(sql_1.LIST_CONFIGURED_ROLES);
63
+ return rows.map((r) => r.role);
64
+ }
65
+ /**
66
+ * Register one declared role at startup.
67
+ *
68
+ * The role is created if missing. Under code ownership its declared fields
69
+ * are compared against the stored row and written through the versioned
70
+ * PATCH path when they differ — a changed form/metadata schema advances the
71
+ * role's schema version and snapshots the pair; an unchanged declaration is
72
+ * a no-op. Under db ownership the metadata is written exactly once (at
73
+ * creation); afterwards the DB owns the row and drift is warn-logged only.
74
+ * Escalation targets use replace semantics when declared.
75
+ */
76
+ async function applyRoleConfig(cfg, codeOwned) {
77
+ const created = await (0, index_1.createRole)(cfg.role);
78
+ const pool = (0, db_1.getPool)();
79
+ const { rows } = await pool.query(sql_1.GET_ROLE_ROW, [cfg.role]);
80
+ const row = rows[0];
81
+ const changed = diffDeclaredFields(cfg, row);
82
+ const changedFields = Object.keys(changed);
83
+ const declaredTargets = cfg.escalation_targets != null ? [...cfg.escalation_targets].sort() : null;
84
+ const storedTargets = declaredTargets != null ? await (0, index_1.getEscalationTargets)(cfg.role) : null;
85
+ const targetsDiffer = declaredTargets != null && !(0, node_util_1.isDeepStrictEqual)(declaredTargets, [...storedTargets].sort());
86
+ if (!codeOwned) {
87
+ if (created) {
88
+ // First boot for this role — write the declared metadata once. From
89
+ // here the DB owns the row (the dependents' "only if unconfigured"
90
+ // guard, moved into core).
91
+ if (changedFields.length > 0) {
92
+ await (0, index_1.updateRoleMetadata)(cfg.role, changed);
93
+ }
94
+ if (targetsDiffer)
95
+ await (0, index_1.replaceEscalationTargets)(cfg.role, declaredTargets);
96
+ return 'applied';
97
+ }
98
+ if (changedFields.length > 0 || targetsDiffer) {
99
+ const drifts = [...changedFields, ...(targetsDiffer ? ['escalation_targets'] : [])];
100
+ logger_1.loggerRegistry.warn(`[long-tail] config drift: role ${cfg.role} — ${drifts.join(', ')} differ between code and DB`);
101
+ }
102
+ return 'db-owned';
103
+ }
104
+ if (changedFields.length === 0 && !targetsDiffer)
105
+ return 'unchanged';
106
+ if (changedFields.length > 0) {
107
+ await (0, index_1.updateRoleMetadata)(cfg.role, { ...changed, change_summary: exports.STARTUP_CHANGE_SUMMARY });
108
+ }
109
+ if (targetsDiffer) {
110
+ await (0, index_1.replaceEscalationTargets)(cfg.role, declaredTargets);
111
+ }
112
+ return 'applied';
113
+ }
@@ -14,6 +14,14 @@ export declare const DELETE_ESCALATION_CHAINS_BY_SOURCE = "\n DELETE FROM lt_co
14
14
  export declare const CHECK_ESCALATION_CHAIN_EXISTS = "\n SELECT 1\n FROM lt_config_role_escalations\n WHERE source_role = $1 AND target_role = $2";
15
15
  export declare const ENSURE_ROLE_EXISTS = "\n INSERT INTO lt_roles (role) VALUES ($1)\n ON CONFLICT DO NOTHING";
16
16
  export declare const LIST_ROLES = "\n SELECT role FROM lt_roles ORDER BY role";
17
+ /**
18
+ * Roles carrying real configuration (a title or a form schema). Bare FK rows
19
+ * and membership-only roles are excluded — the startup orphan report uses
20
+ * this so auto-ensured rows never read as drift.
21
+ */
22
+ export declare const LIST_CONFIGURED_ROLES = "\n SELECT role FROM lt_roles\n WHERE title IS NOT NULL OR form_schema IS NOT NULL\n ORDER BY role";
23
+ /** One role's full metadata row (plus upstream inputs) for startup diffing. */
24
+ export declare const GET_ROLE_ROW = "\n SELECT\n r.role, r.title, r.description, r.form_schema, r.metadata_schema,\n r.properties, r.ops_visible, r.ops_home_default, r.parent_role,\n r.sla_minutes, r.target_per_hour, r.worker_count,\n r.priority_threshold_minutes, r.priority_facet,\n r.entity_facet, r.entity_state_source,\n r.list_schema, r.default_pins, r.enforce_schema,\n r.current_schema_version, r.current_list_schema_version,\n COALESCE((SELECT array_agg(u.upstream_role ORDER BY u.upstream_role)\n FROM lt_role_upstreams u WHERE u.role = r.role), '{}') AS upstream_roles\n FROM lt_roles r\n WHERE r.role = $1";
17
25
  export declare const DELETE_ROLE = "\n DELETE FROM lt_roles WHERE role = $1";
18
26
  /**
19
27
  * PATCH semantics in ONE atomic statement: each column has a boolean
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // ─── Escalation chain queries ───────────────────────────────────────────────
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_PROPERTIES = exports.GET_ROLE_METADATA_SCHEMA = exports.LIST_ENFORCING_ROLES = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
4
+ exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_PROPERTIES = exports.GET_ROLE_METADATA_SCHEMA = exports.LIST_ENFORCING_ROLES = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.GET_ROLE_ROW = exports.LIST_CONFIGURED_ROLES = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
5
5
  exports.GET_ESCALATION_TARGETS = `
6
6
  SELECT target_role
7
7
  FROM lt_config_role_escalations
@@ -47,6 +47,29 @@ exports.ENSURE_ROLE_EXISTS = `
47
47
  ON CONFLICT DO NOTHING`;
48
48
  exports.LIST_ROLES = `
49
49
  SELECT role FROM lt_roles ORDER BY role`;
50
+ /**
51
+ * Roles carrying real configuration (a title or a form schema). Bare FK rows
52
+ * and membership-only roles are excluded — the startup orphan report uses
53
+ * this so auto-ensured rows never read as drift.
54
+ */
55
+ exports.LIST_CONFIGURED_ROLES = `
56
+ SELECT role FROM lt_roles
57
+ WHERE title IS NOT NULL OR form_schema IS NOT NULL
58
+ ORDER BY role`;
59
+ /** One role's full metadata row (plus upstream inputs) for startup diffing. */
60
+ exports.GET_ROLE_ROW = `
61
+ SELECT
62
+ r.role, r.title, r.description, r.form_schema, r.metadata_schema,
63
+ r.properties, r.ops_visible, r.ops_home_default, r.parent_role,
64
+ r.sla_minutes, r.target_per_hour, r.worker_count,
65
+ r.priority_threshold_minutes, r.priority_facet,
66
+ r.entity_facet, r.entity_state_source,
67
+ r.list_schema, r.default_pins, r.enforce_schema,
68
+ r.current_schema_version, r.current_list_schema_version,
69
+ COALESCE((SELECT array_agg(u.upstream_role ORDER BY u.upstream_role)
70
+ FROM lt_role_upstreams u WHERE u.role = r.role), '{}') AS upstream_roles
71
+ FROM lt_roles r
72
+ WHERE r.role = $1`;
50
73
  exports.DELETE_ROLE = `
51
74
  DELETE FROM lt_roles WHERE role = $1`;
52
75
  /**
@@ -1,4 +1,4 @@
1
1
  export { listScanSchemes, getScanScheme, listScanRules, getScanRule, } from './read';
2
- export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
2
+ export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
3
3
  export { parseScanCode, interpolateScanTemplate, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
4
4
  export { assertValidScheme, assertValidSteps } from './validate';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assertValidSteps = exports.assertValidScheme = exports.interpolateScanTemplate = exports.parseScanCode = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
3
+ exports.assertValidSteps = exports.assertValidScheme = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
4
4
  var read_1 = require("./read");
5
5
  Object.defineProperty(exports, "listScanSchemes", { enumerable: true, get: function () { return read_1.listScanSchemes; } });
6
6
  Object.defineProperty(exports, "getScanScheme", { enumerable: true, get: function () { return read_1.getScanScheme; } });
@@ -13,6 +13,8 @@ Object.defineProperty(exports, "upsertScanRule", { enumerable: true, get: functi
13
13
  Object.defineProperty(exports, "deleteScanRule", { enumerable: true, get: function () { return write_1.deleteScanRule; } });
14
14
  Object.defineProperty(exports, "seedScanScheme", { enumerable: true, get: function () { return write_1.seedScanScheme; } });
15
15
  Object.defineProperty(exports, "seedScanRule", { enumerable: true, get: function () { return write_1.seedScanRule; } });
16
+ Object.defineProperty(exports, "applyScanScheme", { enumerable: true, get: function () { return write_1.applyScanScheme; } });
17
+ Object.defineProperty(exports, "applyScanRule", { enumerable: true, get: function () { return write_1.applyScanRule; } });
16
18
  var parse_1 = require("./parse");
17
19
  Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
18
20
  Object.defineProperty(exports, "interpolateScanTemplate", { enumerable: true, get: function () { return parse_1.interpolateScanTemplate; } });
@@ -8,3 +8,10 @@ export declare const UPSERT_ACTION = "INSERT INTO lt_config_scan_actions\n (sch
8
8
  export declare const DELETE_ACTION = "DELETE FROM lt_config_scan_actions WHERE scheme_version = $1 AND category = $2";
9
9
  export declare const SEED_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length,\n kind, grant_ttl_seconds, grant_max_uses, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)\nON CONFLICT (version) DO NOTHING";
10
10
  export declare const SEED_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, not_primed, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7)\nON CONFLICT (scheme_version, category) DO NOTHING";
11
+ /**
12
+ * Apply — same column set as the upsert, guarded by IS DISTINCT FROM so an
13
+ * unchanged declaration is a zero-row no-op. `(xmax = 0)` distinguishes
14
+ * insert from update. jsonb columns compare content-wise in SQL.
15
+ */
16
+ export declare const APPLY_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length,\n kind, grant_ttl_seconds, grant_max_uses, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)\nON CONFLICT (version) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n target_facet = EXCLUDED.target_facet,\n encoding = EXCLUDED.encoding,\n delimiter = EXCLUDED.delimiter,\n target_length = EXCLUDED.target_length,\n kind = EXCLUDED.kind,\n grant_ttl_seconds = EXCLUDED.grant_ttl_seconds,\n grant_max_uses = EXCLUDED.grant_max_uses,\n enabled = EXCLUDED.enabled,\n updated_at = NOW()\nWHERE (lt_config_scan_schemes.name, lt_config_scan_schemes.description,\n lt_config_scan_schemes.target_facet, lt_config_scan_schemes.encoding,\n lt_config_scan_schemes.delimiter, lt_config_scan_schemes.target_length,\n lt_config_scan_schemes.kind, lt_config_scan_schemes.grant_ttl_seconds,\n lt_config_scan_schemes.grant_max_uses, lt_config_scan_schemes.enabled)\n IS DISTINCT FROM\n (EXCLUDED.name, EXCLUDED.description, EXCLUDED.target_facet,\n EXCLUDED.encoding, EXCLUDED.delimiter, EXCLUDED.target_length,\n EXCLUDED.kind, EXCLUDED.grant_ttl_seconds, EXCLUDED.grant_max_uses,\n EXCLUDED.enabled)\nRETURNING (xmax = 0) AS inserted";
17
+ export declare const APPLY_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, not_primed, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7)\nON CONFLICT (scheme_version, category) DO UPDATE SET\n name = EXCLUDED.name,\n steps = EXCLUDED.steps,\n fallback = EXCLUDED.fallback,\n not_primed = EXCLUDED.not_primed,\n enabled = EXCLUDED.enabled,\n updated_at = NOW()\nWHERE (lt_config_scan_actions.name, lt_config_scan_actions.steps,\n lt_config_scan_actions.fallback, lt_config_scan_actions.not_primed,\n lt_config_scan_actions.enabled)\n IS DISTINCT FROM\n (EXCLUDED.name, EXCLUDED.steps, EXCLUDED.fallback,\n EXCLUDED.not_primed, EXCLUDED.enabled)\nRETURNING (xmax = 0) AS inserted";
@@ -3,7 +3,7 @@
3
3
  // Read queries //
4
4
  // ------------------------------------------------------------------ //
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SEED_ACTION = exports.SEED_SCHEME = exports.DELETE_ACTION = exports.UPSERT_ACTION = exports.DELETE_SCHEME = exports.UPSERT_SCHEME = exports.GET_ACTION = exports.LIST_ACTIONS = exports.GET_SCHEME = exports.LIST_SCHEMES = void 0;
6
+ exports.APPLY_ACTION = exports.APPLY_SCHEME = exports.SEED_ACTION = exports.SEED_SCHEME = exports.DELETE_ACTION = exports.UPSERT_ACTION = exports.DELETE_SCHEME = exports.UPSERT_SCHEME = exports.GET_ACTION = exports.LIST_ACTIONS = exports.GET_SCHEME = exports.LIST_SCHEMES = void 0;
7
7
  exports.LIST_SCHEMES = `\
8
8
  SELECT * FROM lt_config_scan_schemes ORDER BY version`;
9
9
  exports.GET_SCHEME = `\
@@ -61,3 +61,57 @@ INSERT INTO lt_config_scan_actions
61
61
  (scheme_version, category, name, steps, fallback, not_primed, enabled)
62
62
  VALUES ($1, $2, $3, $4, $5, $6, $7)
63
63
  ON CONFLICT (scheme_version, category) DO NOTHING`;
64
+ // ------------------------------------------------------------------ //
65
+ // Apply (code-owned startup pass — code is source of truth) //
66
+ // ------------------------------------------------------------------ //
67
+ /**
68
+ * Apply — same column set as the upsert, guarded by IS DISTINCT FROM so an
69
+ * unchanged declaration is a zero-row no-op. `(xmax = 0)` distinguishes
70
+ * insert from update. jsonb columns compare content-wise in SQL.
71
+ */
72
+ exports.APPLY_SCHEME = `\
73
+ INSERT INTO lt_config_scan_schemes
74
+ (version, name, description, target_facet, encoding, delimiter, target_length,
75
+ kind, grant_ttl_seconds, grant_max_uses, enabled)
76
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
77
+ ON CONFLICT (version) DO UPDATE SET
78
+ name = EXCLUDED.name,
79
+ description = EXCLUDED.description,
80
+ target_facet = EXCLUDED.target_facet,
81
+ encoding = EXCLUDED.encoding,
82
+ delimiter = EXCLUDED.delimiter,
83
+ target_length = EXCLUDED.target_length,
84
+ kind = EXCLUDED.kind,
85
+ grant_ttl_seconds = EXCLUDED.grant_ttl_seconds,
86
+ grant_max_uses = EXCLUDED.grant_max_uses,
87
+ enabled = EXCLUDED.enabled,
88
+ updated_at = NOW()
89
+ WHERE (lt_config_scan_schemes.name, lt_config_scan_schemes.description,
90
+ lt_config_scan_schemes.target_facet, lt_config_scan_schemes.encoding,
91
+ lt_config_scan_schemes.delimiter, lt_config_scan_schemes.target_length,
92
+ lt_config_scan_schemes.kind, lt_config_scan_schemes.grant_ttl_seconds,
93
+ lt_config_scan_schemes.grant_max_uses, lt_config_scan_schemes.enabled)
94
+ IS DISTINCT FROM
95
+ (EXCLUDED.name, EXCLUDED.description, EXCLUDED.target_facet,
96
+ EXCLUDED.encoding, EXCLUDED.delimiter, EXCLUDED.target_length,
97
+ EXCLUDED.kind, EXCLUDED.grant_ttl_seconds, EXCLUDED.grant_max_uses,
98
+ EXCLUDED.enabled)
99
+ RETURNING (xmax = 0) AS inserted`;
100
+ exports.APPLY_ACTION = `\
101
+ INSERT INTO lt_config_scan_actions
102
+ (scheme_version, category, name, steps, fallback, not_primed, enabled)
103
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
104
+ ON CONFLICT (scheme_version, category) DO UPDATE SET
105
+ name = EXCLUDED.name,
106
+ steps = EXCLUDED.steps,
107
+ fallback = EXCLUDED.fallback,
108
+ not_primed = EXCLUDED.not_primed,
109
+ enabled = EXCLUDED.enabled,
110
+ updated_at = NOW()
111
+ WHERE (lt_config_scan_actions.name, lt_config_scan_actions.steps,
112
+ lt_config_scan_actions.fallback, lt_config_scan_actions.not_primed,
113
+ lt_config_scan_actions.enabled)
114
+ IS DISTINCT FROM
115
+ (EXCLUDED.name, EXCLUDED.steps, EXCLUDED.fallback,
116
+ EXCLUDED.not_primed, EXCLUDED.enabled)
117
+ RETURNING (xmax = 0) AS inserted`;
@@ -28,3 +28,11 @@ export declare function deleteScanRule(schemeVersion: number, category: string):
28
28
  /** Insert-if-absent seeding — DB is the source of truth, never overwrite. */
29
29
  export declare function seedScanScheme(input: ScanSchemeInput): Promise<boolean>;
30
30
  export declare function seedScanRule(input: ScanRuleInput): Promise<boolean>;
31
+ /**
32
+ * Apply a scheme declaration at startup (code is source of truth). Same
33
+ * validation as the upsert; the IS DISTINCT FROM guard makes an unchanged
34
+ * declaration a zero-row no-op.
35
+ */
36
+ export declare function applyScanScheme(input: ScanSchemeInput): Promise<'applied' | 'unchanged'>;
37
+ /** Apply a rule declaration at startup (code is source of truth). */
38
+ export declare function applyScanRule(input: ScanRuleInput): Promise<'applied' | 'unchanged'>;
@@ -6,6 +6,8 @@ exports.upsertScanRule = upsertScanRule;
6
6
  exports.deleteScanRule = deleteScanRule;
7
7
  exports.seedScanScheme = seedScanScheme;
8
8
  exports.seedScanRule = seedScanRule;
9
+ exports.applyScanScheme = applyScanScheme;
10
+ exports.applyScanRule = applyScanRule;
9
11
  const db_1 = require("../../lib/db");
10
12
  const types_1 = require("../../types");
11
13
  const sql_1 = require("./sql");
@@ -55,7 +57,8 @@ async function deleteScanScheme(version) {
55
57
  const { rowCount } = await (0, db_1.getPool)().query(sql_1.DELETE_SCHEME, [version]);
56
58
  return (rowCount ?? 0) > 0;
57
59
  }
58
- async function upsertScanRule(input) {
60
+ /** Shared rule-input validation — the upsert and startup-apply paths enforce the same contract. */
61
+ async function assertValidRuleInput(input) {
59
62
  if (!/^[0-9]$/.test(input.category)) {
60
63
  throw new Error('category must be a single digit (0-9)');
61
64
  }
@@ -65,6 +68,9 @@ async function upsertScanRule(input) {
65
68
  if (input.steps.length === 0 && !input.fallback?.markdown && !input.fallback?.route) {
66
69
  throw new Error('a rule needs at least one step or a fallback');
67
70
  }
71
+ }
72
+ async function upsertScanRule(input) {
73
+ await assertValidRuleInput(input);
68
74
  const { rows } = await (0, db_1.getPool)().query(sql_1.UPSERT_ACTION, ruleParams(input));
69
75
  return rows[0];
70
76
  }
@@ -83,3 +89,19 @@ async function seedScanRule(input) {
83
89
  const { rowCount } = await (0, db_1.getPool)().query(sql_1.SEED_ACTION, ruleParams(input));
84
90
  return (rowCount ?? 0) > 0;
85
91
  }
92
+ /**
93
+ * Apply a scheme declaration at startup (code is source of truth). Same
94
+ * validation as the upsert; the IS DISTINCT FROM guard makes an unchanged
95
+ * declaration a zero-row no-op.
96
+ */
97
+ async function applyScanScheme(input) {
98
+ (0, validate_1.assertValidScheme)(input);
99
+ const { rowCount } = await (0, db_1.getPool)().query(sql_1.APPLY_SCHEME, schemeParams(input));
100
+ return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
101
+ }
102
+ /** Apply a rule declaration at startup (code is source of truth). */
103
+ async function applyScanRule(input) {
104
+ await assertValidRuleInput(input);
105
+ const { rowCount } = await (0, db_1.getPool)().query(sql_1.APPLY_ACTION, ruleParams(input));
106
+ return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
107
+ }
@@ -20,6 +20,8 @@ export interface TopicSubscriber {
20
20
  topic: string;
21
21
  reaction_type: string;
22
22
  }
23
+ /** Config-declared topic names — the startup orphan report's candidate set. */
24
+ export declare function listConfigTopicNames(): Promise<string[]>;
23
25
  export declare function listTopics(filters?: {
24
26
  category?: string;
25
27
  search?: string;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listConfigTopicNames = listConfigTopicNames;
3
4
  exports.listTopics = listTopics;
4
5
  exports.getTopic = getTopic;
5
6
  exports.createTopic = createTopic;
@@ -10,6 +11,12 @@ exports.seedTopic = seedTopic;
10
11
  exports.resetTopic = resetTopic;
11
12
  const db_1 = require("../../lib/db");
12
13
  const sql_1 = require("./sql");
14
+ /** Config-declared topic names — the startup orphan report's candidate set. */
15
+ async function listConfigTopicNames() {
16
+ const pool = (0, db_1.getPool)();
17
+ const { rows } = await pool.query(sql_1.LIST_CONFIG_TOPIC_NAMES);
18
+ return rows.map((r) => r.topic);
19
+ }
13
20
  async function listTopics(filters = {}) {
14
21
  const pool = (0, db_1.getPool)();
15
22
  const limit = filters.limit ?? 50;
@@ -1,5 +1,7 @@
1
1
  export declare const LIST_TOPICS = "\n SELECT t.*,\n COALESCE(s.sub_count, 0)::int AS subscriber_count\n FROM lt_topic_catalog t\n LEFT JOIN LATERAL (\n SELECT COUNT(*)::int AS sub_count\n FROM lt_agent_subscriptions\n WHERE enabled = true\n AND (\n topic = t.topic\n OR t.topic LIKE REPLACE(REPLACE(topic, '*', '%'), '>', '%')\n )\n ) s ON true\n WHERE ($1::text IS NULL OR t.category = $1)\n AND ($2::text IS NULL OR t.topic ILIKE '%' || $2 || '%' OR t.description ILIKE '%' || $2 || '%')\n ORDER BY t.category, t.topic\n LIMIT $3 OFFSET $4\n";
2
2
  export declare const COUNT_TOPICS = "\n SELECT COUNT(*)::int AS total FROM lt_topic_catalog\n WHERE ($1::text IS NULL OR category = $1)\n AND ($2::text IS NULL OR topic ILIKE '%' || $2 || '%' OR description ILIKE '%' || $2 || '%')\n";
3
+ /** Config-declared topic names — the startup orphan report's candidate set. */
4
+ export declare const LIST_CONFIG_TOPIC_NAMES = "\n SELECT topic FROM lt_topic_catalog WHERE source = 'config' ORDER BY topic\n";
3
5
  export declare const GET_TOPIC = "\n SELECT * FROM lt_topic_catalog WHERE topic = $1\n";
4
6
  export declare const INSERT_TOPIC = "\n INSERT INTO lt_topic_catalog\n (topic, description, category, payload_schema, example_payload, source, tags)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n RETURNING *\n";
5
7
  export declare const UPDATE_TOPIC = "\n UPDATE lt_topic_catalog SET\n description = COALESCE($2, description),\n category = COALESCE($3, category),\n payload_schema = COALESCE($4, payload_schema),\n example_payload = COALESCE($5, example_payload),\n tags = COALESCE($6, tags)\n WHERE topic = $1\n RETURNING *\n";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LIST_SUBSCRIBERS = exports.RESET_TOPIC = exports.SEED_TOPIC = exports.UPSERT_ON_PUBLISH = exports.DELETE_TOPIC = exports.UPDATE_TOPIC = exports.INSERT_TOPIC = exports.GET_TOPIC = exports.COUNT_TOPICS = exports.LIST_TOPICS = void 0;
3
+ exports.LIST_SUBSCRIBERS = exports.RESET_TOPIC = exports.SEED_TOPIC = exports.UPSERT_ON_PUBLISH = exports.DELETE_TOPIC = exports.UPDATE_TOPIC = exports.INSERT_TOPIC = exports.GET_TOPIC = exports.LIST_CONFIG_TOPIC_NAMES = exports.COUNT_TOPICS = exports.LIST_TOPICS = void 0;
4
4
  exports.LIST_TOPICS = `
5
5
  SELECT t.*,
6
6
  COALESCE(s.sub_count, 0)::int AS subscriber_count
@@ -24,6 +24,10 @@ exports.COUNT_TOPICS = `
24
24
  WHERE ($1::text IS NULL OR category = $1)
25
25
  AND ($2::text IS NULL OR topic ILIKE '%' || $2 || '%' OR description ILIKE '%' || $2 || '%')
26
26
  `;
27
+ /** Config-declared topic names — the startup orphan report's candidate set. */
28
+ exports.LIST_CONFIG_TOPIC_NAMES = `
29
+ SELECT topic FROM lt_topic_catalog WHERE source = 'config' ORDER BY topic
30
+ `;
27
31
  exports.GET_TOPIC = `
28
32
  SELECT * FROM lt_topic_catalog WHERE topic = $1
29
33
  `;
@@ -2,6 +2,7 @@ import type { LTTopicConfig } from '../../types';
2
2
  export declare function seedSystemTopics(): Promise<void>;
3
3
  /**
4
4
  * Seed user-declared topics from startConfig.topics[].
5
- * Respects `reset: true` — overwrites DB from config on every boot.
5
+ * Ownership per entry: `reset ?? defaultReset` — code-owned topics are
6
+ * overwritten from config on every boot; db-owned topics are insert-if-absent.
6
7
  */
7
- export declare function seedConfigTopics(topics: LTTopicConfig[]): Promise<void>;
8
+ export declare function seedConfigTopics(topics: LTTopicConfig[], defaultReset?: boolean): Promise<void>;
@@ -314,9 +314,10 @@ async function seedSystemTopics() {
314
314
  }
315
315
  /**
316
316
  * Seed user-declared topics from startConfig.topics[].
317
- * Respects `reset: true` — overwrites DB from config on every boot.
317
+ * Ownership per entry: `reset ?? defaultReset` — code-owned topics are
318
+ * overwritten from config on every boot; db-owned topics are insert-if-absent.
318
319
  */
319
- async function seedConfigTopics(topics) {
320
+ async function seedConfigTopics(topics, defaultReset = false) {
320
321
  for (const def of topics) {
321
322
  try {
322
323
  const payload = {
@@ -328,7 +329,7 @@ async function seedConfigTopics(topics) {
328
329
  source: 'config',
329
330
  tags: def.tags ?? [],
330
331
  };
331
- if (def.reset) {
332
+ if (def.reset ?? defaultReset) {
332
333
  await (0, index_1.resetTopic)(payload);
333
334
  logger_1.loggerRegistry.info(`[long-tail] topic reset: ${def.topic} (config)`);
334
335
  }
@@ -1,6 +1,6 @@
1
1
  export { CreateUserInput, UpdateUserInput, VALID_ROLE_TYPES } from './types';
2
2
  export { createUser, getUser, getUserByExternalId, getUserByEmail, getUserByMetadataValue, updateUser, deleteUser, listUsers, } from './crud';
3
- export { isValidRoleType, addUserRole, removeUserRole, getUserRoles, hasRole, hasRoleType, } from './roles';
3
+ export { isValidRoleType, addUserRole, grantRoleIfAbsent, removeUserRole, getUserRoles, hasRole, hasRoleType, } from './roles';
4
4
  export { isSuperAdmin, isGroupAdmin, canManageRole, hasGlobalEscalationAccess, hasRolesAsAdmin, getRoleScope, getRoleWriteScope } from './rbac';
5
5
  export { READ_SCOPES, WRITE_SCOPES, DEFAULT_READ_SCOPE, DEFAULT_WRITE_SCOPE, isValidReadScope, isValidWriteScope, isValidScopePair, effectiveScope, } from './scope';
6
6
  export { verifyPassword } from './auth';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PREFERENCES_MAX_BYTES = exports.patchPreferences = exports.getPreferences = exports.seedAdmin = exports.verifyPassword = exports.effectiveScope = exports.isValidScopePair = exports.isValidWriteScope = exports.isValidReadScope = exports.DEFAULT_WRITE_SCOPE = exports.DEFAULT_READ_SCOPE = exports.WRITE_SCOPES = exports.READ_SCOPES = exports.getRoleWriteScope = exports.getRoleScope = exports.hasRolesAsAdmin = exports.hasGlobalEscalationAccess = exports.canManageRole = exports.isGroupAdmin = exports.isSuperAdmin = exports.hasRoleType = exports.hasRole = exports.getUserRoles = exports.removeUserRole = exports.addUserRole = exports.isValidRoleType = exports.listUsers = exports.deleteUser = exports.updateUser = exports.getUserByMetadataValue = exports.getUserByEmail = exports.getUserByExternalId = exports.getUser = exports.createUser = exports.VALID_ROLE_TYPES = void 0;
3
+ exports.PREFERENCES_MAX_BYTES = exports.patchPreferences = exports.getPreferences = exports.seedAdmin = exports.verifyPassword = exports.effectiveScope = exports.isValidScopePair = exports.isValidWriteScope = exports.isValidReadScope = exports.DEFAULT_WRITE_SCOPE = exports.DEFAULT_READ_SCOPE = exports.WRITE_SCOPES = exports.READ_SCOPES = exports.getRoleWriteScope = exports.getRoleScope = exports.hasRolesAsAdmin = exports.hasGlobalEscalationAccess = exports.canManageRole = exports.isGroupAdmin = exports.isSuperAdmin = exports.hasRoleType = exports.hasRole = exports.getUserRoles = exports.removeUserRole = exports.grantRoleIfAbsent = exports.addUserRole = exports.isValidRoleType = exports.listUsers = exports.deleteUser = exports.updateUser = exports.getUserByMetadataValue = exports.getUserByEmail = exports.getUserByExternalId = exports.getUser = exports.createUser = exports.VALID_ROLE_TYPES = void 0;
4
4
  var types_1 = require("./types");
5
5
  Object.defineProperty(exports, "VALID_ROLE_TYPES", { enumerable: true, get: function () { return types_1.VALID_ROLE_TYPES; } });
6
6
  var crud_1 = require("./crud");
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "listUsers", { enumerable: true, get: function ()
15
15
  var roles_1 = require("./roles");
16
16
  Object.defineProperty(exports, "isValidRoleType", { enumerable: true, get: function () { return roles_1.isValidRoleType; } });
17
17
  Object.defineProperty(exports, "addUserRole", { enumerable: true, get: function () { return roles_1.addUserRole; } });
18
+ Object.defineProperty(exports, "grantRoleIfAbsent", { enumerable: true, get: function () { return roles_1.grantRoleIfAbsent; } });
18
19
  Object.defineProperty(exports, "removeUserRole", { enumerable: true, get: function () { return roles_1.removeUserRole; } });
19
20
  Object.defineProperty(exports, "getUserRoles", { enumerable: true, get: function () { return roles_1.getUserRoles; } });
20
21
  Object.defineProperty(exports, "hasRole", { enumerable: true, get: function () { return roles_1.hasRole; } });
@@ -6,6 +6,14 @@ export interface RoleScopeInput {
6
6
  write_scope?: LTWriteScope;
7
7
  }
8
8
  export declare function addUserRole(userId: string, role: string, type: LTRoleType, scope?: RoleScopeInput): Promise<LTUserRole>;
9
+ /**
10
+ * Grant a role ONLY when the user does not already hold it — the scope-safe
11
+ * add for sync paths (SSO provisioning, claim-time provisioning). An existing
12
+ * grant is never touched: identity sync adds missing memberships, it never
13
+ * mutates the type/scope/provenance an admin set. Returns the inserted row, or
14
+ * null when the membership already existed.
15
+ */
16
+ export declare function grantRoleIfAbsent(userId: string, role: string, type: LTRoleType, scope?: RoleScopeInput): Promise<LTUserRole | null>;
9
17
  export declare function removeUserRole(userId: string, role: string): Promise<boolean>;
10
18
  export declare function getUserRoles(userId: string): Promise<LTUserRole[]>;
11
19
  export declare function hasRole(userId: string, role: string): Promise<boolean>;