shieldcortex 4.31.2 → 4.32.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 (353) hide show
  1. package/README.md +78 -2
  2. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  3. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
  35. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
  36. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
  38. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  39. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
  40. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  41. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
  42. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  43. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  44. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  45. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
  46. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
  47. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
  48. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
  49. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  50. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  51. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
  52. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
  53. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
  54. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
  55. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
  56. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
  57. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
  58. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
  59. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  60. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  61. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
  62. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
  63. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
  64. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
  65. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
  66. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
  67. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
  68. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
  69. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  70. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  71. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
  72. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
  73. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
  74. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
  75. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
  76. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
  77. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
  78. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
  79. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  80. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  81. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
  82. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
  83. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
  84. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
  85. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
  86. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
  87. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
  88. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
  89. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  90. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  91. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
  92. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
  93. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
  94. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
  95. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
  96. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
  97. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
  98. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
  99. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  100. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  101. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
  102. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
  103. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
  104. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
  105. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
  106. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
  107. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
  108. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  109. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  110. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
  111. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
  112. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
  113. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
  114. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
  115. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
  116. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
  117. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
  118. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  119. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
  120. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
  121. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
  122. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
  123. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
  125. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
  126. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
  127. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  128. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  129. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
  130. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
  131. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
  132. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
  133. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
  134. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
  135. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
  136. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
  137. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  138. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  139. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
  140. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
  141. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
  142. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
  143. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
  144. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
  145. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
  146. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
  147. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  148. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  149. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
  150. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
  151. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
  152. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
  153. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
  154. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
  155. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
  156. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
  157. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  158. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  159. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
  160. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
  161. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
  162. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
  163. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
  164. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
  165. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
  166. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
  167. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  168. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  169. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
  170. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
  171. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
  172. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
  173. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
  174. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
  175. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
  176. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  177. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  178. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
  179. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
  180. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
  181. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
  182. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
  183. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
  184. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
  185. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
  186. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  187. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  188. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  189. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  190. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  191. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
  192. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
  193. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
  194. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
  195. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  196. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  197. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
  198. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
  199. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
  200. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
  201. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
  202. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
  203. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
  204. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  205. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  206. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
  207. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
  208. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
  209. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
  210. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
  211. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
  212. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
  213. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
  214. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  215. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
  216. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
  217. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
  218. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
  219. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
  220. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  221. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  222. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  223. package/dist/api/control.d.ts +2 -0
  224. package/dist/api/control.js +119 -2
  225. package/dist/api/routes/memories.js +19 -14
  226. package/dist/api/routes/system.js +2 -3
  227. package/dist/api/visualization-server.d.ts +13 -1
  228. package/dist/api/visualization-server.js +57 -1
  229. package/dist/audit/env-scanner.js +5 -2
  230. package/dist/audit/index.d.ts +4 -1
  231. package/dist/audit/index.js +2 -1
  232. package/dist/audit/mcp-config-scanner.d.ts +23 -0
  233. package/dist/audit/mcp-config-scanner.js +110 -0
  234. package/dist/audit/mcp-tools-scanner.d.ts +112 -0
  235. package/dist/audit/mcp-tools-scanner.js +299 -0
  236. package/dist/cli/audit.d.ts +1 -0
  237. package/dist/cli/audit.js +12 -1
  238. package/dist/cli/doctor.js +4 -1
  239. package/dist/cli/mcp.d.ts +13 -0
  240. package/dist/cli/mcp.js +0 -0
  241. package/dist/cli/remember.d.ts +75 -0
  242. package/dist/cli/remember.js +195 -0
  243. package/dist/cli/repair.d.ts +8 -0
  244. package/dist/cli/repair.js +34 -0
  245. package/dist/cli/update.js +34 -0
  246. package/dist/cloud/config.d.ts +23 -1
  247. package/dist/cloud/config.js +453 -193
  248. package/dist/cloud/quarantine-sync.d.ts +12 -2
  249. package/dist/cloud/quarantine-sync.js +28 -6
  250. package/dist/cloud/sync-queue.d.ts +21 -2
  251. package/dist/cloud/sync-queue.js +124 -29
  252. package/dist/database/better-sqlite3-guard.d.ts +21 -2
  253. package/dist/database/better-sqlite3-guard.js +29 -5
  254. package/dist/database/init.js +68 -16
  255. package/dist/database/inline-schema.js +35 -1
  256. package/dist/database/migrations.js +104 -8
  257. package/dist/database/schema.sql +39 -1
  258. package/dist/defence/audit/queries.d.ts +10 -2
  259. package/dist/defence/audit/queries.js +30 -4
  260. package/dist/defence/audit/retention.d.ts +50 -0
  261. package/dist/defence/audit/retention.js +161 -0
  262. package/dist/defence/credential-leak/entropy.d.ts +11 -0
  263. package/dist/defence/credential-leak/entropy.js +27 -0
  264. package/dist/defence/credential-leak/index.js +27 -1
  265. package/dist/defence/credential-leak/patterns.d.ts +9 -0
  266. package/dist/defence/credential-leak/patterns.js +21 -0
  267. package/dist/defence/custom-patterns/store.js +8 -1
  268. package/dist/defence/custom-rules/store.d.ts +18 -0
  269. package/dist/defence/custom-rules/store.js +63 -0
  270. package/dist/defence/firewall/confusables.d.ts +30 -0
  271. package/dist/defence/firewall/confusables.js +87 -0
  272. package/dist/defence/firewall/encoding-detector.js +23 -9
  273. package/dist/defence/firewall/index.d.ts +11 -1
  274. package/dist/defence/firewall/index.js +34 -1
  275. package/dist/defence/firewall/instruction-detector.js +18 -7
  276. package/dist/defence/firewall/markdown-image-detector.d.ts +34 -0
  277. package/dist/defence/firewall/markdown-image-detector.js +83 -0
  278. package/dist/defence/fragmentation/entity-extractor.js +17 -6
  279. package/dist/defence/index.d.ts +5 -0
  280. package/dist/defence/index.js +8 -0
  281. package/dist/defence/iron-dome/index.js +7 -1
  282. package/dist/defence/pipeline.js +62 -10
  283. package/dist/defence/scan-windows.d.ts +41 -0
  284. package/dist/defence/scan-windows.js +61 -0
  285. package/dist/defence/semantic/attack-corpus.d.ts +22 -0
  286. package/dist/defence/semantic/attack-corpus.js +75 -0
  287. package/dist/defence/semantic/index.d.ts +67 -0
  288. package/dist/defence/semantic/index.js +138 -0
  289. package/dist/defence/skill-scanner/deep-scan.js +35 -15
  290. package/dist/defence/skill-scanner/patterns.d.ts +1 -1
  291. package/dist/defence/skill-scanner/patterns.js +8 -7
  292. package/dist/defence/tool-response-scanner.d.ts +21 -5
  293. package/dist/defence/tool-response-scanner.js +111 -22
  294. package/dist/defence/types.d.ts +11 -1
  295. package/dist/index.d.ts +29 -0
  296. package/dist/index.js +112 -21
  297. package/dist/memory/consolidate.js +1 -1
  298. package/dist/memory/decay.js +3 -1
  299. package/dist/memory/embedding.d.ts +18 -2
  300. package/dist/memory/embedding.js +32 -11
  301. package/dist/memory/expiry.js +1 -1
  302. package/dist/memory/search-recall.js +107 -49
  303. package/dist/memory/search.d.ts +19 -3
  304. package/dist/memory/search.js +25 -10
  305. package/dist/memory/store.d.ts +13 -2
  306. package/dist/memory/store.js +115 -11
  307. package/dist/scan-only.d.ts +64 -0
  308. package/dist/scan-only.js +173 -0
  309. package/dist/server.d.ts +5 -0
  310. package/dist/server.js +6 -4
  311. package/dist/setup/claude-md.js +39 -34
  312. package/dist/setup/codex.js +9 -2
  313. package/dist/setup/copilot.js +160 -47
  314. package/dist/setup/json-config.d.ts +99 -0
  315. package/dist/setup/json-config.js +167 -0
  316. package/dist/setup/migrate.js +1 -1
  317. package/dist/setup/native-binding.d.ts +75 -0
  318. package/dist/setup/native-binding.js +146 -0
  319. package/dist/setup/settings-hooks.js +8 -13
  320. package/dist/setup/uninstall.js +1 -21
  321. package/dist/tools/context.d.ts +8 -8
  322. package/dist/tools/forget.d.ts +9 -8
  323. package/dist/tools/forget.js +17 -4
  324. package/dist/tools/recall.d.ts +13 -13
  325. package/dist/tools/remember.d.ts +16 -16
  326. package/dist/tools/remember.js +19 -8
  327. package/dist/worker/brain-worker.d.ts +1 -0
  328. package/dist/worker/brain-worker.js +79 -16
  329. package/dist/worker/types.d.ts +8 -0
  330. package/dist/worker/types.js +8 -0
  331. package/dist/xray/dir-scanner.d.ts +18 -0
  332. package/dist/xray/dir-scanner.js +23 -1
  333. package/dist/xray/file-scanner.js +16 -1
  334. package/dist/xray/findings-store.js +9 -1
  335. package/dist/xray/index.d.ts +2 -0
  336. package/dist/xray/index.js +10 -1
  337. package/dist/xray/npm-inspector.d.ts +31 -0
  338. package/dist/xray/npm-inspector.js +135 -29
  339. package/dist/xray/patterns.d.ts +1 -1
  340. package/dist/xray/patterns.js +20 -23
  341. package/dist/xray/sarif.d.ts +78 -0
  342. package/dist/xray/sarif.js +166 -0
  343. package/dist/xray/watch.d.ts +1 -0
  344. package/dist/xray/watch.js +10 -1
  345. package/hooks/openclaw/cortex-memory/handler.ts +122 -18
  346. package/hooks/openclaw/cortex-memory/runtime.mjs +10 -4
  347. package/package.json +10 -3
  348. package/scripts/postinstall.mjs +8 -3
  349. package/dist/memory/embedding-cache.d.ts +0 -20
  350. package/dist/memory/embedding-cache.js +0 -91
  351. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → tjJ3X8xQ-2_WQTPGF3zCA}/_buildManifest.js +0 -0
  352. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → tjJ3X8xQ-2_WQTPGF3zCA}/_clientMiddlewareManifest.json +0 -0
  353. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → tjJ3X8xQ-2_WQTPGF3zCA}/_ssgManifest.js +0 -0
@@ -23,7 +23,6 @@
23
23
  * databases that have only partially run them.
24
24
  */
25
25
  import { randomUUID } from 'crypto';
26
- import { seedDefaultFirewallRules } from './seed-firewall-rules.js';
27
26
  /**
28
27
  * Log unexpected errors from idempotent DDL operations (v4.26.0).
29
28
  *
@@ -473,13 +472,10 @@ export function runMigrations(database) {
473
472
  logIfUnexpectedDdlError(err, 'firewall_rules.built_in column add');
474
473
  // (pipeline handles missing column gracefully; this is informational)
475
474
  }
476
- // Seed default built-in firewall rules on first init.
477
- try {
478
- seedDefaultFirewallRules(database);
479
- }
480
- catch {
481
- // Seeder runs idempotently; failures here should never block startup.
482
- }
475
+ // Built-in firewall rule seeding now lives in `initDatabase()` AFTER the
476
+ // schema is applied — `runMigrations()` returns early on fresh databases
477
+ // (no `memories` table), so a seed call here never fired for new installs.
478
+ // The init-level call is idempotent and covers both fresh and existing DBs.
483
479
  // Migration: session_events.content_hash + dedupe UNIQUE index (v4.17).
484
480
  // DBs created between the foundation commit and the importer commit have
485
481
  // session_events but no content_hash column. ALTER + idempotent index
@@ -654,4 +650,104 @@ export function runMigrations(database) {
654
650
  // Best-effort marker; the stderr line above carries the signal.
655
651
  }
656
652
  }
653
+ // Migration: control_state table (cross-process kill-switch / pause).
654
+ //
655
+ // Phase 2 hardening: the kill switch / pause mode used to live only in
656
+ // module-level memory, so a dashboard (API process) activation never reached
657
+ // the separate MCP server process. control_state is the single-row source of
658
+ // truth both processes read/write; api/control.ts persists to and refreshes
659
+ // from it. Existing DBs that predate the table get it here (schema.sql /
660
+ // inline-schema.ts cover fresh installs).
661
+ try {
662
+ database.exec(`
663
+ CREATE TABLE IF NOT EXISTS control_state (
664
+ id INTEGER PRIMARY KEY CHECK (id = 1),
665
+ mode TEXT NOT NULL DEFAULT 'active' CHECK (mode IN ('active','paused','kill_switch')),
666
+ meta_json TEXT,
667
+ updated_at TEXT NOT NULL
668
+ );
669
+ `);
670
+ }
671
+ catch (err) {
672
+ logIfUnexpectedDdlError(err, 'control_state');
673
+ }
674
+ // Migration: audit_aggregates table (Phase 8a — bound defence_audit growth).
675
+ //
676
+ // defence_audit grows on every pipeline run with no DELETE anywhere, so a busy
677
+ // agent eventually trips the 100MB hard block (init.ts MAX_DB_SIZE) and bricks
678
+ // its own memory store. Retention purges (src/defence/audit/retention.ts) now
679
+ // delete old rows — but getLifetimeStats() scans the whole table, so a naive
680
+ // purge would make lifetime totals silently undercount. This single-row
681
+ // cumulative aggregate is the rollup target: purges add the to-be-deleted
682
+ // rows' contributions here BEFORE deleting, and getLifetimeStats() returns
683
+ // aggregate + live so the numbers never go backwards.
684
+ try {
685
+ database.exec(`
686
+ CREATE TABLE IF NOT EXISTS audit_aggregates (
687
+ id INTEGER PRIMARY KEY CHECK (id = 1),
688
+ total_scans INTEGER NOT NULL DEFAULT 0,
689
+ threats_blocked INTEGER NOT NULL DEFAULT 0,
690
+ quarantined INTEGER NOT NULL DEFAULT 0,
691
+ memories_protected INTEGER NOT NULL DEFAULT 0,
692
+ credential_leaks INTEGER NOT NULL DEFAULT 0,
693
+ updated_at TEXT
694
+ );
695
+ `);
696
+ }
697
+ catch (err) {
698
+ logIfUnexpectedDdlError(err, 'audit_aggregates');
699
+ }
700
+ // Migration: Phase 10 — scope the memories_au FTS trigger to UPDATE OF the
701
+ // indexed columns only (title, content, tags).
702
+ //
703
+ // The trigger originally shipped as `AFTER UPDATE ON memories` with no `OF`
704
+ // column list, so it fired a full FTS5 external-content delete+reinsert on
705
+ // ANY column update. The hottest write path — accessMemory() bumping
706
+ // access_count / last_accessed / salience on every recalled memory, plus the
707
+ // 5-minute decay-score persistence — never touches indexed text, so each read
708
+ // was re-tokenising and rewriting the FTS index for nothing (write
709
+ // amplification + WAL churn + more surface for FTS drift).
710
+ //
711
+ // A `CREATE TRIGGER IF NOT EXISTS` alone CANNOT replace the existing unscoped
712
+ // trigger on an upgraded DB, so we DROP it first, then recreate with the
713
+ // scoped form. Fresh installs already get the scoped trigger from
714
+ // schema.sql / inline-schema.ts; this block only matters for existing DBs.
715
+ try {
716
+ database.exec('DROP TRIGGER IF EXISTS memories_au');
717
+ database.exec(`
718
+ CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE OF title, content, tags ON memories BEGIN
719
+ INSERT INTO memories_fts(memories_fts, rowid, title, content, tags)
720
+ VALUES('delete', old.id, old.title, old.content, old.tags);
721
+ INSERT INTO memories_fts(rowid, title, content, tags)
722
+ VALUES (new.id, new.title, new.content, new.tags);
723
+ END;
724
+ `);
725
+ }
726
+ catch (err) {
727
+ logIfUnexpectedDdlError(err, 'memories_au');
728
+ }
729
+ // Migration: Phase 14 — mcp_tool_hashes table (MCP tool-description drift /
730
+ // rug-pull detection). `shieldcortex mcp scan` stores a sha256 of each MCP
731
+ // server's advertised tool definition (name + description + inputSchema) and
732
+ // compares it on the next scan: a CHANGED hash for an already-seen tool is
733
+ // the classic rug-pull signal (a server silently altering an approved tool
734
+ // description). Mirrors the content-hash idempotency pattern used elsewhere
735
+ // (session_events.content_hash). Fresh installs get this from schema.sql /
736
+ // inline-schema.ts; this block only matters for existing DBs.
737
+ try {
738
+ database.exec(`
739
+ CREATE TABLE IF NOT EXISTS mcp_tool_hashes (
740
+ server_name TEXT NOT NULL,
741
+ tool_name TEXT NOT NULL,
742
+ content_hash TEXT NOT NULL,
743
+ first_seen TEXT,
744
+ last_seen TEXT,
745
+ last_changed TEXT,
746
+ PRIMARY KEY (server_name, tool_name)
747
+ );
748
+ `);
749
+ }
750
+ catch (err) {
751
+ logIfUnexpectedDdlError(err, 'mcp_tool_hashes');
752
+ }
657
753
  }
@@ -65,7 +65,7 @@ CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
65
65
  VALUES('delete', old.id, old.title, old.content, old.tags);
66
66
  END;
67
67
 
68
- CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
68
+ CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE OF title, content, tags ON memories BEGIN
69
69
  INSERT INTO memories_fts(memories_fts, rowid, title, content, tags)
70
70
  VALUES('delete', old.id, old.title, old.content, old.tags);
71
71
  INSERT INTO memories_fts(rowid, title, content, tags)
@@ -229,6 +229,21 @@ CREATE INDEX IF NOT EXISTS idx_audit_result ON defence_audit(firewall_result);
229
229
  CREATE INDEX IF NOT EXISTS idx_audit_source ON defence_audit(source_type);
230
230
  CREATE INDEX IF NOT EXISTS idx_audit_project ON defence_audit(project);
231
231
 
232
+ -- Defence: cumulative audit aggregate (single row, id=1). Retention purges roll
233
+ -- the to-be-deleted rows' lifetime-stat contributions into this row BEFORE
234
+ -- deleting, so getLifetimeStats() = this aggregate + a scan of the (bounded)
235
+ -- live defence_audit table. Without it, retention would make lifetime stats
236
+ -- silently undercount after every purge.
237
+ CREATE TABLE IF NOT EXISTS audit_aggregates (
238
+ id INTEGER PRIMARY KEY CHECK (id = 1),
239
+ total_scans INTEGER NOT NULL DEFAULT 0,
240
+ threats_blocked INTEGER NOT NULL DEFAULT 0,
241
+ quarantined INTEGER NOT NULL DEFAULT 0,
242
+ memories_protected INTEGER NOT NULL DEFAULT 0,
243
+ credential_leaks INTEGER NOT NULL DEFAULT 0,
244
+ updated_at TEXT
245
+ );
246
+
232
247
  -- Defence: Quarantine for blocked/suspicious memories pending review
233
248
  CREATE TABLE IF NOT EXISTS quarantine (
234
249
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -345,6 +360,7 @@ CREATE TABLE IF NOT EXISTS firewall_rules (
345
360
 
346
361
  CREATE INDEX IF NOT EXISTS idx_firewall_rules_priority ON firewall_rules(priority);
347
362
  CREATE INDEX IF NOT EXISTS idx_firewall_rules_enabled ON firewall_rules(enabled);
363
+ CREATE INDEX IF NOT EXISTS idx_firewall_rules_built_in ON firewall_rules(built_in);
348
364
 
349
365
  -- Rate limits (cross-process, persisted)
350
366
  CREATE TABLE IF NOT EXISTS rate_limits (
@@ -352,3 +368,25 @@ CREATE TABLE IF NOT EXISTS rate_limits (
352
368
  write_count INTEGER NOT NULL DEFAULT 1,
353
369
  window_start_ms INTEGER NOT NULL
354
370
  );
371
+
372
+ -- Control state (single row, cross-process kill-switch / pause)
373
+ CREATE TABLE IF NOT EXISTS control_state (
374
+ id INTEGER PRIMARY KEY CHECK (id = 1),
375
+ mode TEXT NOT NULL DEFAULT 'active' CHECK (mode IN ('active','paused','kill_switch')),
376
+ meta_json TEXT,
377
+ updated_at TEXT NOT NULL
378
+ );
379
+
380
+ -- Phase 14: MCP tool-description hashes (drift / rug-pull detection).
381
+ -- `shieldcortex mcp scan` stores a sha256 of each MCP server's advertised tool
382
+ -- definition; a CHANGED hash on a re-scan flags a silently-altered (rug-pulled)
383
+ -- tool description.
384
+ CREATE TABLE IF NOT EXISTS mcp_tool_hashes (
385
+ server_name TEXT NOT NULL,
386
+ tool_name TEXT NOT NULL,
387
+ content_hash TEXT NOT NULL,
388
+ first_seen TEXT,
389
+ last_seen TEXT,
390
+ last_changed TEXT,
391
+ PRIMARY KEY (server_name, tool_name)
392
+ );
@@ -76,8 +76,16 @@ export interface LifetimeStats {
76
76
  memoriesProtected: number;
77
77
  }
78
78
  /**
79
- * Get all-time aggregate stats from the defence_audit table.
80
- * Fast COUNT-only queries — no heavy computation.
79
+ * Get all-time aggregate stats.
80
+ *
81
+ * defence_audit is now retention-bounded (see src/defence/audit/retention.ts):
82
+ * old rows are periodically purged so the table can't grow until it bricks the
83
+ * DB at the 100MB hard limit. To keep these lifetime totals correct, every purge
84
+ * first rolls the to-be-deleted rows' contributions into the single-row
85
+ * `audit_aggregates` table. So the lifetime total is `aggregate + scan(live)` —
86
+ * the aggregate carries the purged history and the COUNT scan covers the
87
+ * (bounded) rows still on disk. This guarantees totals never go backwards after
88
+ * a purge. The credential LIKE scan is over a bounded table now, so it's fine.
81
89
  */
82
90
  export declare function getLifetimeStats(): LifetimeStats;
83
91
  /**
@@ -107,12 +107,20 @@ export function getAuditStats(timeRange, project) {
107
107
  };
108
108
  }
109
109
  /**
110
- * Get all-time aggregate stats from the defence_audit table.
111
- * Fast COUNT-only queries — no heavy computation.
110
+ * Get all-time aggregate stats.
111
+ *
112
+ * defence_audit is now retention-bounded (see src/defence/audit/retention.ts):
113
+ * old rows are periodically purged so the table can't grow until it bricks the
114
+ * DB at the 100MB hard limit. To keep these lifetime totals correct, every purge
115
+ * first rolls the to-be-deleted rows' contributions into the single-row
116
+ * `audit_aggregates` table. So the lifetime total is `aggregate + scan(live)` —
117
+ * the aggregate carries the purged history and the COUNT scan covers the
118
+ * (bounded) rows still on disk. This guarantees totals never go backwards after
119
+ * a purge. The credential LIKE scan is over a bounded table now, so it's fine.
112
120
  */
113
121
  export function getLifetimeStats() {
114
122
  const db = getDatabase();
115
- // Counts by firewall result
123
+ // Counts by firewall result (live, retention-bounded rows)
116
124
  const counts = db.prepare(`
117
125
  SELECT firewall_result, COUNT(*) as cnt
118
126
  FROM defence_audit
@@ -137,7 +145,25 @@ export function getLifetimeStats() {
137
145
  FROM defence_audit
138
146
  WHERE LOWER(threat_indicators) LIKE '%credential%'
139
147
  `).get();
140
- const credentialLeaks = credRow?.cnt ?? 0;
148
+ let credentialLeaks = credRow?.cnt ?? 0;
149
+ // Add the cumulative aggregate of all rows already purged by retention. The
150
+ // table may not exist on very old DBs mid-migration — treat absence as zero.
151
+ try {
152
+ const agg = db.prepare(`
153
+ SELECT total_scans, threats_blocked, quarantined, memories_protected, credential_leaks
154
+ FROM audit_aggregates WHERE id = 1
155
+ `).get();
156
+ if (agg) {
157
+ totalScans += agg.total_scans;
158
+ threatsBlocked += agg.threats_blocked;
159
+ quarantined += agg.quarantined;
160
+ memoriesProtected += agg.memories_protected;
161
+ credentialLeaks += agg.credential_leaks;
162
+ }
163
+ }
164
+ catch {
165
+ // No aggregate row / table yet — lifetime == live counts.
166
+ }
141
167
  return {
142
168
  totalScans,
143
169
  threatsBlocked,
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Audit retention + size-pressure valve (Phase 8a).
3
+ *
4
+ * `logAudit()` inserts a defence_audit row on EVERY pipeline run (including
5
+ * per-tool-response scans) and nothing ever deletes them — the table grows
6
+ * forever. The DB has a 100MB hard limit (init.ts MAX_DB_SIZE) that BLOCKS all
7
+ * writes once exceeded, and consolidation/vacuum can't shrink audit rows that
8
+ * are never deleted, so a busy agent bricks its own memory store with no
9
+ * recovery path.
10
+ *
11
+ * Retention alone would break lifetime stats: getLifetimeStats() scans the
12
+ * whole defence_audit table, so deleting old rows would make every lifetime
13
+ * total silently undercount after a purge. So retention is COUPLED with an
14
+ * aggregate rollup — before deleting, the to-be-deleted rows' stat
15
+ * contributions are folded into the single-row `audit_aggregates` table, and
16
+ * getLifetimeStats() returns `aggregate + scan(remaining)`. Totals never regress.
17
+ */
18
+ /** Default age-based retention window. */
19
+ export declare const DEFAULT_RETENTION_DAYS = 90;
20
+ /**
21
+ * Hard ceiling on live defence_audit rows under size pressure. When the DB file
22
+ * crosses the warning threshold, the valve trims the oldest rows down to (at
23
+ * most) this many so audit growth can't carry the file to the 100MB block.
24
+ */
25
+ export declare const AUDIT_PRESSURE_ROW_CAP = 100000;
26
+ /**
27
+ * Age-based retention: roll the contributions of rows older than the cutoff into
28
+ * audit_aggregates, then DELETE them. Aggregate + delete run in one transaction
29
+ * so a crash can't drop rows without first banking their stats (which would make
30
+ * lifetime totals regress). Returns the number of rows deleted.
31
+ */
32
+ export declare function purgeOldAuditEntries(retentionDays?: number): number;
33
+ /**
34
+ * Size-pressure valve. Cheap to call: it first checks the DB file size and bails
35
+ * unless the file has crossed the warning threshold (reusing the codebase's
36
+ * existing 50MB WARN_DB_SIZE via checkDatabaseSize(), so we don't keep a second
37
+ * copy of the threshold). When over pressure, it trims the OLDEST audit rows
38
+ * down to a row cap — same aggregate-then-delete path as age retention — so
39
+ * audit growth can never carry the DB to the 100MB block.
40
+ *
41
+ * Thresholds are injectable for tests. Simulating a real 50MB file (and, on a
42
+ * `:memory:` DB, ANY measurable file size) is impractical, so passing
43
+ * `warnBytes` BYPASSES the file-size gate entirely and drives the row-cap trim
44
+ * directly; `maxRows` sets the cap. In production neither is passed and the gate
45
+ * uses the live file size vs WARN_DB_SIZE.
46
+ */
47
+ export declare function purgeAuditUnderSizePressure(options?: {
48
+ warnBytes?: number;
49
+ maxRows?: number;
50
+ }): number;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Audit retention + size-pressure valve (Phase 8a).
3
+ *
4
+ * `logAudit()` inserts a defence_audit row on EVERY pipeline run (including
5
+ * per-tool-response scans) and nothing ever deletes them — the table grows
6
+ * forever. The DB has a 100MB hard limit (init.ts MAX_DB_SIZE) that BLOCKS all
7
+ * writes once exceeded, and consolidation/vacuum can't shrink audit rows that
8
+ * are never deleted, so a busy agent bricks its own memory store with no
9
+ * recovery path.
10
+ *
11
+ * Retention alone would break lifetime stats: getLifetimeStats() scans the
12
+ * whole defence_audit table, so deleting old rows would make every lifetime
13
+ * total silently undercount after a purge. So retention is COUPLED with an
14
+ * aggregate rollup — before deleting, the to-be-deleted rows' stat
15
+ * contributions are folded into the single-row `audit_aggregates` table, and
16
+ * getLifetimeStats() returns `aggregate + scan(remaining)`. Totals never regress.
17
+ */
18
+ import { getDatabase, checkDatabaseSize } from '../../database/init.js';
19
+ /** Default age-based retention window. */
20
+ export const DEFAULT_RETENTION_DAYS = 90;
21
+ /**
22
+ * Hard ceiling on live defence_audit rows under size pressure. When the DB file
23
+ * crosses the warning threshold, the valve trims the oldest rows down to (at
24
+ * most) this many so audit growth can't carry the file to the 100MB block.
25
+ */
26
+ export const AUDIT_PRESSURE_ROW_CAP = 100_000;
27
+ /**
28
+ * Compute the lifetime-stat contributions of a set of defence_audit rows
29
+ * identified by a WHERE clause + params. Mirrors getLifetimeStats's mapping
30
+ * EXACTLY (BLOCK→threats_blocked, QUARANTINE→quarantined, ALLOW→memories_protected,
31
+ * and the credential predicate is the same case-insensitive LIKE) so the
32
+ * aggregate + live split reproduces the pre-purge totals byte-for-byte.
33
+ */
34
+ function computeDelta(where, params) {
35
+ const db = getDatabase();
36
+ const counts = db.prepare(`
37
+ SELECT firewall_result, COUNT(*) AS cnt
38
+ FROM defence_audit
39
+ WHERE ${where}
40
+ GROUP BY firewall_result
41
+ `).all(...params);
42
+ const delta = {
43
+ total_scans: 0,
44
+ threats_blocked: 0,
45
+ quarantined: 0,
46
+ memories_protected: 0,
47
+ credential_leaks: 0,
48
+ };
49
+ for (const row of counts) {
50
+ delta.total_scans += row.cnt;
51
+ if (row.firewall_result === 'BLOCK')
52
+ delta.threats_blocked += row.cnt;
53
+ else if (row.firewall_result === 'QUARANTINE')
54
+ delta.quarantined += row.cnt;
55
+ else if (row.firewall_result === 'ALLOW')
56
+ delta.memories_protected += row.cnt;
57
+ }
58
+ const credRow = db.prepare(`
59
+ SELECT COUNT(*) AS cnt
60
+ FROM defence_audit
61
+ WHERE (${where}) AND LOWER(threat_indicators) LIKE '%credential%'
62
+ `).get(...params);
63
+ delta.credential_leaks = credRow?.cnt ?? 0;
64
+ return delta;
65
+ }
66
+ /**
67
+ * Fold a delta into the single-row audit_aggregates (id=1) cumulative totals.
68
+ * UPSERT so the row is created on first purge and incremented thereafter.
69
+ */
70
+ function rollIntoAggregate(delta) {
71
+ const db = getDatabase();
72
+ db.prepare(`
73
+ INSERT INTO audit_aggregates (
74
+ id, total_scans, threats_blocked, quarantined, memories_protected,
75
+ credential_leaks, updated_at
76
+ ) VALUES (1, @total_scans, @threats_blocked, @quarantined, @memories_protected, @credential_leaks, @updated_at)
77
+ ON CONFLICT(id) DO UPDATE SET
78
+ total_scans = total_scans + excluded.total_scans,
79
+ threats_blocked = threats_blocked + excluded.threats_blocked,
80
+ quarantined = quarantined + excluded.quarantined,
81
+ memories_protected = memories_protected + excluded.memories_protected,
82
+ credential_leaks = credential_leaks + excluded.credential_leaks,
83
+ updated_at = excluded.updated_at
84
+ `).run({
85
+ total_scans: delta.total_scans,
86
+ threats_blocked: delta.threats_blocked,
87
+ quarantined: delta.quarantined,
88
+ memories_protected: delta.memories_protected,
89
+ credential_leaks: delta.credential_leaks,
90
+ updated_at: new Date().toISOString(),
91
+ });
92
+ }
93
+ /**
94
+ * Age-based retention: roll the contributions of rows older than the cutoff into
95
+ * audit_aggregates, then DELETE them. Aggregate + delete run in one transaction
96
+ * so a crash can't drop rows without first banking their stats (which would make
97
+ * lifetime totals regress). Returns the number of rows deleted.
98
+ */
99
+ export function purgeOldAuditEntries(retentionDays = DEFAULT_RETENTION_DAYS) {
100
+ const db = getDatabase();
101
+ const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000).toISOString();
102
+ return db.transaction(() => {
103
+ const where = 'timestamp < ?';
104
+ const params = [cutoff];
105
+ const delta = computeDelta(where, params);
106
+ if (delta.total_scans === 0)
107
+ return 0; // nothing to do; skip the aggregate write
108
+ rollIntoAggregate(delta);
109
+ const res = db.prepare(`DELETE FROM defence_audit WHERE ${where}`).run(...params);
110
+ return Number(res.changes ?? 0);
111
+ })();
112
+ }
113
+ /**
114
+ * Size-pressure valve. Cheap to call: it first checks the DB file size and bails
115
+ * unless the file has crossed the warning threshold (reusing the codebase's
116
+ * existing 50MB WARN_DB_SIZE via checkDatabaseSize(), so we don't keep a second
117
+ * copy of the threshold). When over pressure, it trims the OLDEST audit rows
118
+ * down to a row cap — same aggregate-then-delete path as age retention — so
119
+ * audit growth can never carry the DB to the 100MB block.
120
+ *
121
+ * Thresholds are injectable for tests. Simulating a real 50MB file (and, on a
122
+ * `:memory:` DB, ANY measurable file size) is impractical, so passing
123
+ * `warnBytes` BYPASSES the file-size gate entirely and drives the row-cap trim
124
+ * directly; `maxRows` sets the cap. In production neither is passed and the gate
125
+ * uses the live file size vs WARN_DB_SIZE.
126
+ */
127
+ export function purgeAuditUnderSizePressure(options = {}) {
128
+ const db = getDatabase();
129
+ const maxRows = options.maxRows ?? AUDIT_PRESSURE_ROW_CAP;
130
+ // Size gate. In production: only proceed once the live DB file crosses the
131
+ // codebase's existing WARN_DB_SIZE (50MB), surfaced via checkDatabaseSize() —
132
+ // we reuse that rather than keep a second copy of the threshold. When tests
133
+ // inject `warnBytes`, the gate is bypassed (a `:memory:` DB has no measurable
134
+ // file size) so the row-cap path can be exercised directly.
135
+ if (options.warnBytes === undefined) {
136
+ if (!checkDatabaseSize().warning)
137
+ return 0;
138
+ }
139
+ return db.transaction(() => {
140
+ const total = db.prepare('SELECT COUNT(*) AS c FROM defence_audit').get().c;
141
+ if (total <= maxRows)
142
+ return 0;
143
+ // Trim down to the cap by deleting the OLDEST rows. Find the cutoff id: keep
144
+ // the newest `maxRows` by timestamp, purge everything older.
145
+ const cutoffRow = db.prepare(`
146
+ SELECT timestamp FROM defence_audit
147
+ ORDER BY timestamp DESC
148
+ LIMIT 1 OFFSET ?
149
+ `).get(maxRows);
150
+ if (!cutoffRow)
151
+ return 0;
152
+ const where = 'timestamp <= ?';
153
+ const params = [cutoffRow.timestamp];
154
+ const delta = computeDelta(where, params);
155
+ if (delta.total_scans === 0)
156
+ return 0;
157
+ rollIntoAggregate(delta);
158
+ const res = db.prepare(`DELETE FROM defence_audit WHERE ${where}`).run(...params);
159
+ return Number(res.changes ?? 0);
160
+ })();
161
+ }
@@ -39,3 +39,14 @@ export declare function extractHighEntropyTokens(content: string): Array<{
39
39
  entropy: number;
40
40
  confidence: number;
41
41
  }>;
42
+ /**
43
+ * Allowlist of well-known PUBLIC identifier shapes that are NOT secrets and
44
+ * must never be flagged as credentials — by ANY detector (pattern OR entropy).
45
+ *
46
+ * Conservative on purpose: only the exact canonical shapes below are excluded,
47
+ * so real secrets (sk_live_..., random base64 tokens) still trip detection.
48
+ * The token is matched on its own boundaries (anchored), so a SHA-shaped
49
+ * substring of a longer secret is NOT what gets matched here — callers pass the
50
+ * isolated token.
51
+ */
52
+ export declare function isWellKnownNonSecret(token: string): boolean;
@@ -80,10 +80,37 @@ export function extractHighEntropyTokens(content) {
80
80
  }
81
81
  return results;
82
82
  }
83
+ /**
84
+ * Allowlist of well-known PUBLIC identifier shapes that are NOT secrets and
85
+ * must never be flagged as credentials — by ANY detector (pattern OR entropy).
86
+ *
87
+ * Conservative on purpose: only the exact canonical shapes below are excluded,
88
+ * so real secrets (sk_live_..., random base64 tokens) still trip detection.
89
+ * The token is matched on its own boundaries (anchored), so a SHA-shaped
90
+ * substring of a longer secret is NOT what gets matched here — callers pass the
91
+ * isolated token.
92
+ */
93
+ export function isWellKnownNonSecret(token) {
94
+ const t = token.trim();
95
+ // Canonical UUID (any version), e.g. 550e8400-e29b-41d4-a716-446655440000.
96
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t))
97
+ return true;
98
+ // Git commit SHA-1 (40 hex) and SHA-256 (64 hex) — public revision ids.
99
+ if (/^[0-9a-f]{40}$/i.test(t))
100
+ return true;
101
+ if (/^[0-9a-f]{64}$/i.test(t))
102
+ return true;
103
+ // Abbreviated git SHA (7–12 hex, the `git rev-parse --short` range).
104
+ if (/^[0-9a-f]{7,12}$/i.test(t))
105
+ return true;
106
+ return false;
107
+ }
83
108
  /**
84
109
  * Heuristic filter to reduce false positives from entropy detection.
85
110
  */
86
111
  function isLikelyFalsePositive(token) {
112
+ if (isWellKnownNonSecret(token))
113
+ return true;
87
114
  // UUIDs — legitimate identifiers, not secrets
88
115
  if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(token))
89
116
  return true;
@@ -7,7 +7,7 @@
7
7
  * variable patterns, and high-entropy string heuristics.
8
8
  */
9
9
  import { ALL_CREDENTIAL_PATTERNS, } from './patterns.js';
10
- import { extractHighEntropyTokens } from './entropy.js';
10
+ import { extractHighEntropyTokens, isWellKnownNonSecret } from './entropy.js';
11
11
  export const DEFAULT_CREDENTIAL_CONFIG = {
12
12
  enabled: true,
13
13
  blockOnCritical: true,
@@ -49,6 +49,27 @@ function isAllowlisted(value, allowlist) {
49
49
  }
50
50
  return false;
51
51
  }
52
+ /**
53
+ * Expand a match span to the full contiguous identifier token it sits in, then
54
+ * test it against the well-known-non-secret allowlist (git SHA / UUID).
55
+ *
56
+ * Generic hex patterns (e.g. the 32-hex "Azure" rule) match a SUBSTRING of a
57
+ * 40-hex commit SHA, so checking only the captured value misses it — we must
58
+ * look at the surrounding contiguous run. The token boundary is the usual
59
+ * credential alphabet ([A-Za-z0-9-]); we deliberately do NOT cross `/`, `+`,
60
+ * `=` etc. so a real base64 secret that merely contains a hex-looking run is
61
+ * not whitelisted.
62
+ */
63
+ function matchIsWellKnownNonSecret(content, start, end) {
64
+ const tokenChar = /[A-Za-z0-9-]/;
65
+ let s = start;
66
+ let e = end;
67
+ while (s > 0 && tokenChar.test(content[s - 1]))
68
+ s--;
69
+ while (e < content.length && tokenChar.test(content[e]))
70
+ e++;
71
+ return isWellKnownNonSecret(content.slice(s, e));
72
+ }
52
73
  // ── Scanner ──
53
74
  /**
54
75
  * Scan content for credential leaks.
@@ -88,6 +109,11 @@ export function scanForCredentials(content, config) {
88
109
  const end = start + fullMatch.length;
89
110
  if (matchedRanges.some(r => start >= r.start && end <= r.end))
90
111
  continue;
112
+ // Skip well-known PUBLIC identifiers (git SHA / UUID). Generic hex rules
113
+ // match a substring of these, so expand to the full token before testing
114
+ // (Phase 17 A5).
115
+ if (matchIsWellKnownNonSecret(content, start, end))
116
+ continue;
91
117
  const action = actionForSeverity(pattern.severity, cfg);
92
118
  const redacted = redactMatch(secretValue, pattern.type);
93
119
  findings.push({
@@ -23,3 +23,12 @@ export declare const PRIVATE_KEY_PATTERNS: CredentialPattern[];
23
23
  export declare const CONNECTION_STRING_PATTERNS: CredentialPattern[];
24
24
  export declare const ENV_SECRET_PATTERNS: CredentialPattern[];
25
25
  export declare const ALL_CREDENTIAL_PATTERNS: CredentialPattern[];
26
+ /**
27
+ * Fetch specific credential pattern SOURCES by name from the single source of
28
+ * truth. Lets other detectors (e.g. fragmentation entity extraction) reuse the
29
+ * canonical token regexes instead of maintaining their own divergent copies —
30
+ * WITHOUT pulling in the broad/low-confidence heuristics, so detection scope is
31
+ * unchanged. Throws on an unknown name so a rename can never silently drop a
32
+ * provider.
33
+ */
34
+ export declare function getCredentialRegexesByName(names: string[]): RegExp[];
@@ -357,3 +357,24 @@ export const ALL_CREDENTIAL_PATTERNS = [
357
357
  ...GENERIC_SECRET_PATTERNS,
358
358
  ...ENV_SECRET_PATTERNS,
359
359
  ];
360
+ // ── Single Source of Truth — pattern lookup by name (Phase 17 C3) ──
361
+ /** Index of every credential pattern by its `name`, for cross-module reuse. */
362
+ const PATTERNS_BY_NAME = new Map(ALL_CREDENTIAL_PATTERNS.map((p) => [p.name, p]));
363
+ /**
364
+ * Fetch specific credential pattern SOURCES by name from the single source of
365
+ * truth. Lets other detectors (e.g. fragmentation entity extraction) reuse the
366
+ * canonical token regexes instead of maintaining their own divergent copies —
367
+ * WITHOUT pulling in the broad/low-confidence heuristics, so detection scope is
368
+ * unchanged. Throws on an unknown name so a rename can never silently drop a
369
+ * provider.
370
+ */
371
+ export function getCredentialRegexesByName(names) {
372
+ return names.map((name) => {
373
+ const pattern = PATTERNS_BY_NAME.get(name);
374
+ if (!pattern) {
375
+ throw new Error(`Unknown credential pattern name: "${name}"`);
376
+ }
377
+ // Fresh RegExp so callers don't share lastIndex state with the source.
378
+ return new RegExp(pattern.regex.source, pattern.regex.flags);
379
+ });
380
+ }
@@ -2,6 +2,13 @@
2
2
  * SQLite CRUD for custom injection patterns (Pro feature).
3
3
  */
4
4
  import { getDatabase } from '../../database/init.js';
5
+ import { createRequire } from 'module';
6
+ // safe-regex2 is require()d lazily (it may not be installed) behind a
7
+ // try/catch fallback. Under real Node ESM a bare require() throws
8
+ // ReferenceError, which the catch would swallow — quietly downgrading the
9
+ // ReDoS check to the weaker heuristic. createRequire() gives us a working
10
+ // require here.
11
+ const require = createRequire(import.meta.url);
5
12
  const MAX_PATTERNS = 50;
6
13
  const MAX_REGEX_LENGTH = 500;
7
14
  /**
@@ -23,7 +30,7 @@ export function validateRegex(pattern) {
23
30
  }
24
31
  // ReDoS check via safe-regex2
25
32
  try {
26
- // Dynamic import fallback safe-regex2 may not be installed
33
+ // Load the CommonJS safe-regex2 via createRequire (it may not be installed)
27
34
  // eslint-disable-next-line @typescript-eslint/no-require-imports
28
35
  const safe = require('safe-regex2');
29
36
  if (!safe(pattern)) {
@@ -36,3 +36,21 @@ export declare function deleteFirewallRule(id: number): boolean;
36
36
  * Get all enabled rules sorted by priority (used by the defence pipeline).
37
37
  */
38
38
  export declare function getEnabledFirewallRules(): FirewallRule[];
39
+ /**
40
+ * Evaluate a single firewall rule against candidate text(s), honouring the
41
+ * rule's `condition_type`. This is the single source of truth for rule
42
+ * matching — the defence pipeline calls it for every enabled rule.
43
+ *
44
+ * - `keyword`: case-insensitive LITERAL substring match. Regex metacharacters
45
+ * in the value (`a.b`, `x+y`) are treated literally, not as a pattern.
46
+ * - `domain`: the value is matched as a host/domain. It matches when the value
47
+ * appears as a hostname (or a suffix of one, so `evil.com` matches
48
+ * `api.evil.com`) anywhere in the text, including inside a URL.
49
+ * - `regex` (and any unknown type): compiled as a case-insensitive RegExp.
50
+ * Invalid patterns never match (returns false) rather than throwing.
51
+ *
52
+ * `condition_value` is assumed to have already been vetted by safe-regex2 at
53
+ * creation time for regex rules (see createFirewallRule callers); we still
54
+ * guard compilation here so a malformed stored value can't crash the pipeline.
55
+ */
56
+ export declare function ruleMatches(rule: Pick<FirewallRule, 'condition_type' | 'condition_value'>, ...texts: Array<string | undefined | null>): boolean;