shieldcortex 4.31.2 → 4.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) 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/mcp.d.ts +13 -0
  239. package/dist/cli/mcp.js +0 -0
  240. package/dist/cli/remember.d.ts +75 -0
  241. package/dist/cli/remember.js +195 -0
  242. package/dist/cloud/config.d.ts +23 -1
  243. package/dist/cloud/config.js +453 -193
  244. package/dist/cloud/quarantine-sync.d.ts +12 -2
  245. package/dist/cloud/quarantine-sync.js +28 -6
  246. package/dist/cloud/sync-queue.d.ts +21 -2
  247. package/dist/cloud/sync-queue.js +124 -29
  248. package/dist/database/better-sqlite3-guard.d.ts +21 -2
  249. package/dist/database/better-sqlite3-guard.js +29 -5
  250. package/dist/database/init.js +68 -16
  251. package/dist/database/inline-schema.js +35 -1
  252. package/dist/database/migrations.js +104 -8
  253. package/dist/database/schema.sql +39 -1
  254. package/dist/defence/audit/queries.d.ts +10 -2
  255. package/dist/defence/audit/queries.js +30 -4
  256. package/dist/defence/audit/retention.d.ts +50 -0
  257. package/dist/defence/audit/retention.js +161 -0
  258. package/dist/defence/credential-leak/entropy.d.ts +11 -0
  259. package/dist/defence/credential-leak/entropy.js +27 -0
  260. package/dist/defence/credential-leak/index.js +27 -1
  261. package/dist/defence/credential-leak/patterns.d.ts +9 -0
  262. package/dist/defence/credential-leak/patterns.js +21 -0
  263. package/dist/defence/custom-patterns/store.js +8 -1
  264. package/dist/defence/custom-rules/store.d.ts +18 -0
  265. package/dist/defence/custom-rules/store.js +63 -0
  266. package/dist/defence/firewall/confusables.d.ts +30 -0
  267. package/dist/defence/firewall/confusables.js +87 -0
  268. package/dist/defence/firewall/encoding-detector.js +23 -9
  269. package/dist/defence/firewall/index.d.ts +11 -1
  270. package/dist/defence/firewall/index.js +34 -1
  271. package/dist/defence/firewall/instruction-detector.js +18 -7
  272. package/dist/defence/firewall/markdown-image-detector.d.ts +34 -0
  273. package/dist/defence/firewall/markdown-image-detector.js +83 -0
  274. package/dist/defence/fragmentation/entity-extractor.js +17 -6
  275. package/dist/defence/index.d.ts +5 -0
  276. package/dist/defence/index.js +8 -0
  277. package/dist/defence/iron-dome/index.js +7 -1
  278. package/dist/defence/pipeline.js +62 -10
  279. package/dist/defence/scan-windows.d.ts +41 -0
  280. package/dist/defence/scan-windows.js +61 -0
  281. package/dist/defence/semantic/attack-corpus.d.ts +22 -0
  282. package/dist/defence/semantic/attack-corpus.js +75 -0
  283. package/dist/defence/semantic/index.d.ts +67 -0
  284. package/dist/defence/semantic/index.js +138 -0
  285. package/dist/defence/skill-scanner/deep-scan.js +35 -15
  286. package/dist/defence/skill-scanner/patterns.d.ts +1 -1
  287. package/dist/defence/skill-scanner/patterns.js +8 -7
  288. package/dist/defence/tool-response-scanner.d.ts +21 -5
  289. package/dist/defence/tool-response-scanner.js +111 -22
  290. package/dist/defence/types.d.ts +11 -1
  291. package/dist/index.d.ts +29 -0
  292. package/dist/index.js +104 -20
  293. package/dist/memory/consolidate.js +1 -1
  294. package/dist/memory/decay.js +3 -1
  295. package/dist/memory/embedding.d.ts +18 -2
  296. package/dist/memory/embedding.js +32 -11
  297. package/dist/memory/expiry.js +1 -1
  298. package/dist/memory/search-recall.js +107 -49
  299. package/dist/memory/search.d.ts +19 -3
  300. package/dist/memory/search.js +25 -10
  301. package/dist/memory/store.d.ts +13 -2
  302. package/dist/memory/store.js +115 -11
  303. package/dist/scan-only.d.ts +64 -0
  304. package/dist/scan-only.js +173 -0
  305. package/dist/server.d.ts +5 -0
  306. package/dist/server.js +6 -4
  307. package/dist/setup/claude-md.js +39 -34
  308. package/dist/setup/codex.js +9 -2
  309. package/dist/setup/copilot.js +160 -47
  310. package/dist/setup/json-config.d.ts +99 -0
  311. package/dist/setup/json-config.js +167 -0
  312. package/dist/setup/migrate.js +1 -1
  313. package/dist/setup/settings-hooks.js +8 -13
  314. package/dist/setup/uninstall.js +1 -21
  315. package/dist/tools/context.d.ts +8 -8
  316. package/dist/tools/forget.d.ts +9 -8
  317. package/dist/tools/forget.js +17 -4
  318. package/dist/tools/recall.d.ts +13 -13
  319. package/dist/tools/remember.d.ts +16 -16
  320. package/dist/tools/remember.js +19 -8
  321. package/dist/worker/brain-worker.d.ts +1 -0
  322. package/dist/worker/brain-worker.js +79 -16
  323. package/dist/worker/types.d.ts +8 -0
  324. package/dist/worker/types.js +8 -0
  325. package/dist/xray/dir-scanner.d.ts +18 -0
  326. package/dist/xray/dir-scanner.js +23 -1
  327. package/dist/xray/file-scanner.js +16 -1
  328. package/dist/xray/findings-store.js +9 -1
  329. package/dist/xray/index.d.ts +2 -0
  330. package/dist/xray/index.js +10 -1
  331. package/dist/xray/npm-inspector.d.ts +31 -0
  332. package/dist/xray/npm-inspector.js +135 -29
  333. package/dist/xray/patterns.d.ts +1 -1
  334. package/dist/xray/patterns.js +20 -23
  335. package/dist/xray/sarif.d.ts +78 -0
  336. package/dist/xray/sarif.js +166 -0
  337. package/dist/xray/watch.d.ts +1 -0
  338. package/dist/xray/watch.js +10 -1
  339. package/hooks/openclaw/cortex-memory/handler.ts +122 -18
  340. package/hooks/openclaw/cortex-memory/runtime.mjs +10 -4
  341. package/package.json +10 -3
  342. package/dist/memory/embedding-cache.d.ts +0 -20
  343. package/dist/memory/embedding-cache.js +0 -91
  344. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_buildManifest.js +0 -0
  345. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_clientMiddlewareManifest.json +0 -0
  346. /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_ssgManifest.js +0 -0
@@ -115,8 +115,24 @@ export function clearQueryEmbeddingCache() {
115
115
  queryEmbeddingCache.clear();
116
116
  }
117
117
  /**
118
- * Embed the query, compute similarity against all memory embeddings,
119
- * return top K (default 10) sorted by score desc.
118
+ * Embed the query, compute similarity against the candidate memories' PERSISTED
119
+ * embeddings, return top K (default 10) sorted by score desc.
120
+ *
121
+ * Candidate embeddings are read from the canonical `memories.embedding` column —
122
+ * the same vector addMemory persists on write and vectorSearch scores against —
123
+ * in ONE batched `WHERE id IN (...)` query, decoded with the shared
124
+ * `decodeEmbeddingBlob`. This is a reuse, not a recompute: previously every
125
+ * candidate was routed through `getOrComputeEmbedding`, which checked a SEPARATE,
126
+ * perpetually-cold `memory_embeddings` cache and re-embedded each candidate's text
127
+ * through the worker on the (near-universal) miss — up to 200 sequential worker
128
+ * round-trips per cold recall, all redundant.
129
+ *
130
+ * Candidates that genuinely lack a persisted embedding (rare — writes populate it;
131
+ * only possible when the model was unavailable at write time, or for legacy rows)
132
+ * are skipped, not re-embedded: re-embedding here would reintroduce exactly the
133
+ * per-candidate worker storm this change removed, and `addMemory` already
134
+ * (re)populates the column out of band. They simply don't contribute to the
135
+ * vector-similarity fallback this turn; FTS and the next write still cover them.
120
136
  *
121
137
  * Non-throwing: returns empty array on failure.
122
138
  */
@@ -125,17 +141,22 @@ export async function findSimilarMemories(query, memories, topK = 10, queryEmbed
125
141
  const activeQueryEmbedding = queryEmbedding ?? await getCachedQueryEmbedding(query);
126
142
  if (!activeQueryEmbedding)
127
143
  return [];
128
- // We need embeddings for each memory — caller should provide pre-computed
129
- // embeddings via the cache. For memories without cached embeddings, we
130
- // compute on the fly (text = title + content).
131
- const { getOrComputeEmbedding } = await import('./embedding-cache.js');
144
+ if (memories.length === 0)
145
+ return [];
146
+ const { getDatabase } = await import('../database/init.js');
147
+ const { decodeEmbeddingBlob } = await import('./search.js');
148
+ const db = getDatabase();
149
+ // ONE batched read of the persisted embeddings for the candidate set.
150
+ const ids = memories.map((m) => m.id);
151
+ const placeholders = ids.map(() => '?').join(',');
152
+ const rows = db.prepare(`SELECT id, embedding FROM memories WHERE id IN (${placeholders}) AND embedding IS NOT NULL`).all(...ids);
132
153
  const scored = [];
133
- for (const mem of memories) {
134
- const memEmbedding = await getOrComputeEmbedding(mem.id, `${mem.title}\n${mem.content}`);
135
- if (!memEmbedding)
136
- continue;
154
+ for (const row of rows) {
155
+ const memEmbedding = decodeEmbeddingBlob(row.embedding);
156
+ // Dimension guard: a vector from a different model version won't match the
157
+ // query's dimensionality. cosineSimilarity returns 0 on length mismatch.
137
158
  const score = cosineSimilarity(activeQueryEmbedding, memEmbedding);
138
- scored.push({ id: mem.id, score });
159
+ scored.push({ id: row.id, score });
139
160
  }
140
161
  scored.sort((a, b) => b.score - a.score);
141
162
  return scored.slice(0, topK);
@@ -38,7 +38,7 @@ export function applyExpiryRules() {
38
38
  for (const rule of expiryRules) {
39
39
  const cutoffDate = new Date(Date.now() - rule.maxAgeDays * 24 * 60 * 60 * 1000).toISOString();
40
40
  // Build WHERE clause for this rule
41
- let where = 'WHERE createdAt < ?';
41
+ let where = 'WHERE created_at < ?';
42
42
  const params = [cutoffDate];
43
43
  if (rule.category) {
44
44
  where += ' AND category = ?';
@@ -55,9 +55,9 @@ async function searchMemoriesInternal(options, config, source, execution) {
55
55
  if (!queryEmbedding) {
56
56
  throw new Error('query embedding unavailable');
57
57
  }
58
- const vectorHits = vectorSearch(db, rowToMemory, queryEmbedding, limit * 2, options.project, includeGlobal);
58
+ const vectorHits = vectorSearch(db, queryEmbedding, limit * 2, options.project, includeGlobal);
59
59
  for (const hit of vectorHits) {
60
- vectorResults.set(hit.memory.id, hit.similarity);
60
+ vectorResults.set(hit.id, hit.similarity);
61
61
  }
62
62
  }
63
63
  catch {
@@ -116,7 +116,13 @@ async function searchMemoriesInternal(options, config, source, execution) {
116
116
  )`;
117
117
  params.push(...options.tags);
118
118
  }
119
- sql += ' ORDER BY m.salience DESC, m.last_accessed DESC LIMIT ?';
119
+ // Prefilter on the persisted decayed-score index (CLAUDE.md: "Persisted decay
120
+ // scores for efficient sorting", idx_memories_decayed_score). decayed_score is
121
+ // NULL until updateDecayScores() persists it (addMemory leaves it unset), so
122
+ // COALESCE back to raw salience for un-scored rows — identical to rowToMemory's
123
+ // `decayed_score ?? salience`. Without the COALESCE, NULL sorts last under DESC
124
+ // and would bury freshly-written high-salience memories out of the prefilter.
125
+ sql += ' ORDER BY COALESCE(m.decayed_score, m.salience) DESC, m.last_accessed DESC LIMIT ?';
120
126
  params.push(limit);
121
127
  const rows = db.prepare(sql).all(...params);
122
128
  const scoringContext = {
@@ -171,29 +177,15 @@ async function searchMemoriesInternal(options, config, source, execution) {
171
177
  for (const result of topResults) {
172
178
  reinforceFromSearch(result.memory.id);
173
179
  }
174
- if (topResults.length >= 2) {
175
- for (let i = 0; i < topResults.length; i++) {
176
- for (let j = i + 1; j < topResults.length; j++) {
177
- const idA = topResults[i].memory.id;
178
- const idB = topResults[j].memory.id;
179
- const existing = db.prepare('SELECT strength FROM memory_links WHERE (source_id = ? AND target_id = ?) OR (source_id = ? AND target_id = ?)').get(idA, idB, idB, idA);
180
- if (existing) {
181
- const newStrength = Math.min(1.0, existing.strength + 0.03);
182
- db.prepare('UPDATE memory_links SET strength = ? WHERE (source_id = ? AND target_id = ?) OR (source_id = ? AND target_id = ?)').run(newStrength, idA, idB, idB, idA);
183
- }
184
- else {
185
- try {
186
- db.prepare('INSERT INTO memory_links (source_id, target_id, relationship, strength) VALUES (?, ?, ?, ?)').run(idA, idB, 'related', 0.2);
187
- }
188
- catch (e) {
189
- if (!(e instanceof Error && e.message.includes('UNIQUE constraint'))) {
190
- console.warn('[shieldcortex] Unexpected error linking co-returned memories:', e);
191
- }
192
- }
193
- }
194
- }
195
- }
196
- }
180
+ // NOTE (Phase 17 B2): the automatic all-pairs "co-access" linking that used
181
+ // to run here was removed. It linked every pair of the top-K results as
182
+ // `related` (strength 0.2), creating C(K,2) spurious graph edges and
183
+ // running one `SELECT existing` + INSERT/UPDATE per pair on every recall.
184
+ // Co-appearing in a single search is not a genuine relationship — these
185
+ // edges polluted the knowledge graph and drove an per-pair query storm.
186
+ // Genuine links are still created elsewhere (addMemory similarity links,
187
+ // explicit contradiction/relationship links); recall now only reinforces
188
+ // individual results above.
197
189
  if (sortedResults.length > 0 && options.query && options.query.length > 30) {
198
190
  const topResult = sortedResults[0];
199
191
  const queryWords = new Set(options.query.toLowerCase().split(/\s+/).filter(w => w.length > 3));
@@ -210,6 +202,12 @@ async function searchMemoriesInternal(options, config, source, execution) {
210
202
  }
211
203
  }
212
204
  const finalResults = sortedResults.slice(0, limit);
205
+ // Per-result contradiction links, then their counterpart titles. The title
206
+ // lookup was an N+1-within-N+1 (one SELECT title per contradiction per
207
+ // result); collect every counterpart id first and resolve all titles with a
208
+ // single `WHERE id IN (...)`, then read from the id→title map below.
209
+ const contradictionsByResult = new Map();
210
+ const counterpartIds = new Set();
213
211
  for (const result of finalResults) {
214
212
  const contradictions = db.prepare(`
215
213
  SELECT ml.strength,
@@ -219,10 +217,27 @@ async function searchMemoriesInternal(options, config, source, execution) {
219
217
  AND (ml.source_id = ? OR ml.target_id = ?)
220
218
  `).all(result.memory.id, result.memory.id, result.memory.id);
221
219
  if (contradictions.length > 0) {
222
- result.contradictions = contradictions.map((contradiction) => {
223
- const other = db.prepare('SELECT title FROM memories WHERE id = ?').get(contradiction.other_id);
224
- return { memoryId: contradiction.other_id, title: other?.title || 'Unknown', score: contradiction.strength };
225
- });
220
+ contradictionsByResult.set(result.memory.id, contradictions);
221
+ for (const c of contradictions)
222
+ counterpartIds.add(c.other_id);
223
+ }
224
+ }
225
+ const counterpartTitles = new Map();
226
+ if (counterpartIds.size > 0) {
227
+ const ids = [...counterpartIds];
228
+ const placeholders = ids.map(() => '?').join(',');
229
+ const titleRows = db.prepare(`SELECT id, title FROM memories WHERE id IN (${placeholders})`).all(...ids);
230
+ for (const tr of titleRows)
231
+ counterpartTitles.set(tr.id, tr.title);
232
+ }
233
+ for (const result of finalResults) {
234
+ const contradictions = contradictionsByResult.get(result.memory.id);
235
+ if (contradictions && contradictions.length > 0) {
236
+ result.contradictions = contradictions.map((contradiction) => ({
237
+ memoryId: contradiction.other_id,
238
+ title: counterpartTitles.get(contradiction.other_id) || 'Unknown',
239
+ score: contradiction.strength,
240
+ }));
226
241
  if (result.explanation) {
227
242
  result.explanation.reasons.push(`${contradictions.length} contradiction link${contradictions.length === 1 ? '' : 's'} attached`);
228
243
  }
@@ -230,8 +245,20 @@ async function searchMemoriesInternal(options, config, source, execution) {
230
245
  }
231
246
  if (source) {
232
247
  const db2 = getDatabase();
248
+ // ACL lookup was an N+1 (one `SELECT source, sensitivity_level WHERE id = ?`
249
+ // per result); fetch all result rows in one `WHERE id IN (...)` and read the
250
+ // per-result source/sensitivity from the map. checkAccess/logAccessDenial
251
+ // logic and filter order are unchanged.
252
+ const aclIds = finalResults.map((result) => result.memory.id);
253
+ const aclRows = new Map();
254
+ if (aclIds.length > 0) {
255
+ const placeholders = aclIds.map(() => '?').join(',');
256
+ const fetched = db2.prepare(`SELECT id, source, sensitivity_level FROM memories WHERE id IN (${placeholders})`).all(...aclIds);
257
+ for (const row of fetched)
258
+ aclRows.set(row.id, row);
259
+ }
233
260
  return finalResults.filter(result => {
234
- const row = db2.prepare('SELECT source, sensitivity_level FROM memories WHERE id = ?').get(result.memory.id);
261
+ const row = aclRows.get(result.memory.id);
235
262
  const policy = checkAccess({ id: result.memory.id, source: row?.source, sensitivity_level: row?.sensitivity_level }, source, 'read');
236
263
  if (!policy.canRead) {
237
264
  logAccessDenial(result.memory.id, source, policy.reason);
@@ -334,10 +361,37 @@ function scoreWithRrf(input) {
334
361
  }
335
362
  // Vector and graph rank lists may contain ids the FTS WHERE would have
336
363
  // filtered out — fetch + filter to enforce the same constraints.
364
+ const sortedVectorIds = Array.from(vectorResults.entries())
365
+ .sort((a, b) => b[1] - a[1])
366
+ .map(([id]) => id);
367
+ const graphLimit = Math.max(limit * 3, 50);
368
+ const graphResults = query && query.trim()
369
+ ? graphRankFromQuery(query, db, { project: options.project, limit: graphLimit })
370
+ : [];
371
+ const candidateGraphIds = graphResults.map((r) => r.memoryId);
372
+ // Batch-hydrate every candidate not already covered by the FTS rows in ONE
373
+ // query (was an N+1: one `SELECT * WHERE id = ?` per vector/graph candidate).
374
+ // considerCandidate then reads from this prefetched map, keeping the exact
375
+ // per-id filter semantics, list order, and memoryMap side effect.
376
+ const candidateIdsToFetch = new Set();
377
+ for (const id of sortedVectorIds)
378
+ if (!memoryMap.has(id))
379
+ candidateIdsToFetch.add(id);
380
+ for (const id of candidateGraphIds)
381
+ if (!memoryMap.has(id))
382
+ candidateIdsToFetch.add(id);
383
+ const prefetchedRows = new Map();
384
+ if (candidateIdsToFetch.size > 0) {
385
+ const ids = [...candidateIdsToFetch];
386
+ const placeholders = ids.map(() => '?').join(',');
387
+ const fetched = db.prepare(`SELECT * FROM memories WHERE id IN (${placeholders})`).all(...ids);
388
+ for (const row of fetched)
389
+ prefetchedRows.set(row.id, row);
390
+ }
337
391
  const considerCandidate = (id) => {
338
392
  if (memoryMap.has(id))
339
393
  return true;
340
- const row = db.prepare('SELECT * FROM memories WHERE id = ?').get(id);
394
+ const row = prefetchedRows.get(id);
341
395
  if (!row)
342
396
  return false;
343
397
  const memory = rowToMemory(row);
@@ -346,15 +400,8 @@ function scoreWithRrf(input) {
346
400
  memoryMap.set(memory.id, memory);
347
401
  return true;
348
402
  };
349
- const vectorIds = Array.from(vectorResults.entries())
350
- .sort((a, b) => b[1] - a[1])
351
- .map(([id]) => id)
352
- .filter(considerCandidate);
353
- const graphLimit = Math.max(limit * 3, 50);
354
- const graphResults = query && query.trim()
355
- ? graphRankFromQuery(query, db, { project: options.project, limit: graphLimit })
356
- : [];
357
- const graphIds = graphResults.map((r) => r.memoryId).filter(considerCandidate);
403
+ const vectorIds = sortedVectorIds.filter(considerCandidate);
404
+ const graphIds = candidateGraphIds.filter(considerCandidate);
358
405
  return runHybridRanker({
359
406
  rankLists: [
360
407
  { name: 'fts', ids: ftsIds, weight: rankerConfig.weights.fts },
@@ -462,7 +509,10 @@ export async function recallWithEmbeddings(query, options) {
462
509
  sql += ` AND (project = ? OR scope = 'global')`;
463
510
  params.push(options.project);
464
511
  }
465
- sql += ' ORDER BY salience DESC, last_accessed DESC LIMIT 200';
512
+ // Prefilter the embedding-fallback candidate pool on the persisted decayed
513
+ // score (COALESCE to raw salience for rows not yet scored — see the FTS
514
+ // prefilter above for the NULL rationale).
515
+ sql += ' ORDER BY COALESCE(decayed_score, salience) DESC, last_accessed DESC LIMIT 200';
466
516
  const candidates = db.prepare(sql).all(...params);
467
517
  // Filter out memories already returned by FTS
468
518
  const newCandidates = candidates.filter(c => !ftsIds.has(c.id));
@@ -476,14 +526,22 @@ export async function recallWithEmbeddings(query, options) {
476
526
  // Find similar memories using embeddings
477
527
  const remainingSlots = limit - ftsMemories.length;
478
528
  const similar = await findSimilarMemories(query, newCandidates, remainingSlots, queryEmbedding);
479
- // Filter by threshold and fetch full Memory objects
529
+ // Filter by threshold, then hydrate the survivors in ONE query. Was an N+1
530
+ // (one `SELECT * WHERE id = ?` per hit); now a single `WHERE id IN (...)`
531
+ // with an id→row map, mapping the threshold-passing ids through it so the
532
+ // original similarity order (and the skip-missing-row behaviour) is kept.
533
+ const hitIds = similar.filter((hit) => hit.score >= threshold).map((hit) => hit.id);
480
534
  const embeddingMemories = [];
481
- for (const hit of similar) {
482
- if (hit.score < threshold)
483
- continue;
484
- const row = db.prepare('SELECT * FROM memories WHERE id = ?').get(hit.id);
485
- if (row) {
486
- embeddingMemories.push(rowToMemory(row));
535
+ if (hitIds.length > 0) {
536
+ const placeholders = hitIds.map(() => '?').join(',');
537
+ const rowsById = new Map();
538
+ const fetched = db.prepare(`SELECT * FROM memories WHERE id IN (${placeholders})`).all(...hitIds);
539
+ for (const row of fetched)
540
+ rowsById.set(row.id, row);
541
+ for (const id of hitIds) {
542
+ const row = rowsById.get(id);
543
+ if (row)
544
+ embeddingMemories.push(rowToMemory(row));
487
545
  }
488
546
  }
489
547
  // Step 4: Merge — FTS results first, then embedding results
@@ -26,13 +26,29 @@ export interface SearchScoreValues {
26
26
  contradictionPenalty: number;
27
27
  finalScore: number;
28
28
  }
29
- export type MemoryRowConverter = (row: Record<string, unknown>) => Memory;
30
29
  export declare function detectQueryCategory(query: string): MemoryCategory | null;
31
30
  export declare function calculateLinkBoost(memoryId: number, db: Database.Database): number;
32
31
  export declare function calculateTagScore(queryTags: string[], memoryTags: string[]): number;
33
32
  export declare function extractQueryTags(query: string): string[];
34
- export declare function vectorSearch(db: Database.Database, rowToMemory: MemoryRowConverter, queryEmbedding: Float32Array, limit: number, project?: string, includeGlobal?: boolean): Array<{
35
- memory: Memory;
33
+ /**
34
+ * Decode a persisted `memories.embedding` BLOB into a Float32Array view.
35
+ *
36
+ * The embedding column is written as the raw little-endian bytes of a 384-dim
37
+ * Float32Array (addMemory: `Buffer.from(embedding.buffer)`). better-sqlite3 hands
38
+ * it back as a Node Buffer; this returns a zero-copy Float32Array view over those
39
+ * bytes. Shared by `vectorSearch` and the recall reuse path (`findSimilarMemories`)
40
+ * so the BLOB→vector decode lives in exactly one place.
41
+ */
42
+ export declare function decodeEmbeddingBlob(buf: Buffer): Float32Array;
43
+ /**
44
+ * Score embedded memories against a query embedding and return the top-k by
45
+ * cosine similarity. Selects ONLY `id, embedding` and returns lean
46
+ * `{ id, similarity }` pairs — the sole caller (search-recall) needs nothing
47
+ * more, so per-row Memory hydration (rowToMemory: 2 JSON parses + several
48
+ * `new Date()` per row) is deferred to whoever actually loads the survivors.
49
+ */
50
+ export declare function vectorSearch(db: Database.Database, queryEmbedding: Float32Array, limit: number, project?: string, includeGlobal?: boolean): Array<{
51
+ id: number;
36
52
  similarity: number;
37
53
  }>;
38
54
  export declare function buildSearchExplanation(memory: Memory, context: SearchScoringContext, values: SearchScoreValues): SearchResult['explanation'];
@@ -63,9 +63,28 @@ export function extractQueryTags(query) {
63
63
  /^[a-z][a-z0-9-]*$/.test(word) &&
64
64
  !['the', 'and', 'for', 'with', 'how', 'what', 'when', 'where', 'why'].includes(word));
65
65
  }
66
- export function vectorSearch(db, rowToMemory, queryEmbedding, limit, project, includeGlobal = true) {
66
+ /**
67
+ * Decode a persisted `memories.embedding` BLOB into a Float32Array view.
68
+ *
69
+ * The embedding column is written as the raw little-endian bytes of a 384-dim
70
+ * Float32Array (addMemory: `Buffer.from(embedding.buffer)`). better-sqlite3 hands
71
+ * it back as a Node Buffer; this returns a zero-copy Float32Array view over those
72
+ * bytes. Shared by `vectorSearch` and the recall reuse path (`findSimilarMemories`)
73
+ * so the BLOB→vector decode lives in exactly one place.
74
+ */
75
+ export function decodeEmbeddingBlob(buf) {
76
+ return new Float32Array(buf.buffer, buf.byteOffset, buf.length / 4);
77
+ }
78
+ /**
79
+ * Score embedded memories against a query embedding and return the top-k by
80
+ * cosine similarity. Selects ONLY `id, embedding` and returns lean
81
+ * `{ id, similarity }` pairs — the sole caller (search-recall) needs nothing
82
+ * more, so per-row Memory hydration (rowToMemory: 2 JSON parses + several
83
+ * `new Date()` per row) is deferred to whoever actually loads the survivors.
84
+ */
85
+ export function vectorSearch(db, queryEmbedding, limit, project, includeGlobal = true) {
67
86
  let query = `
68
- SELECT * FROM memories
87
+ SELECT id, embedding FROM memories
69
88
  WHERE embedding IS NOT NULL
70
89
  `;
71
90
  const params = [];
@@ -79,14 +98,10 @@ export function vectorSearch(db, rowToMemory, queryEmbedding, limit, project, in
79
98
  }
80
99
  const rows = db.prepare(query).all(...params);
81
100
  return rows
82
- .map((row) => {
83
- const embeddingBuffer = row.embedding;
84
- const embedding = new Float32Array(embeddingBuffer.buffer, embeddingBuffer.byteOffset, embeddingBuffer.length / 4);
85
- return {
86
- memory: rowToMemory(row),
87
- similarity: cosineSimilarity(queryEmbedding, embedding),
88
- };
89
- })
101
+ .map((row) => ({
102
+ id: row.id,
103
+ similarity: cosineSimilarity(queryEmbedding, decodeEmbeddingBlob(row.embedding)),
104
+ }))
90
105
  .filter((result) => result.similarity > 0.3)
91
106
  .sort((a, b) => b.similarity - a.similarity)
92
107
  .slice(0, limit);
@@ -58,7 +58,16 @@ export declare function getProjectMemories(project: string, config?: MemoryConfi
58
58
  /**
59
59
  * Get recent memories
60
60
  */
61
- export declare function getRecentMemories(limit?: number, project?: string, source?: DefenceSource): Memory[];
61
+ export interface MemoryListFilters {
62
+ type?: string;
63
+ category?: string;
64
+ }
65
+ /**
66
+ * Count memories matching the project + type/category filters. Used by the
67
+ * dashboard memories route so `total`/`hasMore` reflect the filtered set.
68
+ */
69
+ export declare function countMemories(project?: string, filters?: MemoryListFilters): number;
70
+ export declare function getRecentMemories(limit?: number, project?: string, source?: DefenceSource, filters?: MemoryListFilters): Memory[];
62
71
  /**
63
72
  * Get memories by type
64
73
  */
@@ -66,7 +75,9 @@ export declare function getMemoriesByType(type: MemoryType, limit?: number): Mem
66
75
  /**
67
76
  * Get high-priority memories (for context injection)
68
77
  */
69
- export declare function getHighPriorityMemories(limit?: number, project?: string, source?: DefenceSource): Memory[];
78
+ export declare function getHighPriorityMemories(limit?: number, project?: string, source?: DefenceSource, filters?: MemoryListFilters): Memory[];
79
+ /** Count high-priority (salience >= 0.6) memories matching the filters. */
80
+ export declare function countHighPriorityMemories(project?: string, filters?: MemoryListFilters): number;
70
81
  /**
71
82
  * Get memory statistics
72
83
  */
@@ -350,6 +350,8 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
350
350
  threat_indicators: indicators,
351
351
  anomaly_score: defenceResult.firewall.anomalyScore,
352
352
  firewall_result: defenceResult.firewall.result,
353
+ project: input.project ?? null,
354
+ sensitivity_level: defenceResult.sensitivity.level,
353
355
  });
354
356
  }
355
357
  catch {
@@ -539,6 +541,39 @@ export function getMemoryById(id, source) {
539
541
  }
540
542
  return rowToMemory(row);
541
543
  }
544
+ /**
545
+ * Recompute and persist the `memories.embedding` vector for a memory whose
546
+ * embedded text (title/content) just changed. Fire-and-forget, mirroring
547
+ * addMemory's write: the caller is expected to have already cleared the column
548
+ * (`embedding = NULL`) synchronously so no stale vector is readable in the gap
549
+ * before this lands. No-ops cleanly when embeddings are disabled/unavailable.
550
+ */
551
+ function refreshEmbeddingAsync(memoryId, title, content) {
552
+ const db = getDatabase();
553
+ generateEmbedding(title + ' ' + content)
554
+ .then((embedding) => {
555
+ try {
556
+ if (embedding && embedding.buffer) {
557
+ db.prepare('UPDATE memories SET embedding = ? WHERE id = ?')
558
+ .run(Buffer.from(embedding.buffer), memoryId);
559
+ }
560
+ }
561
+ catch (e) {
562
+ const errMsg = e instanceof Error ? e.message : String(e);
563
+ if (/database connection is not open/i.test(errMsg))
564
+ return;
565
+ console.error('[shieldcortex] Failed to store refreshed embedding:', e);
566
+ }
567
+ })
568
+ .catch((e) => {
569
+ if (e instanceof Error &&
570
+ (e.message.includes('Embedding worker unavailable') ||
571
+ e.message.includes('Embeddings disabled via SHIELDCORTEX_SKIP_EMBEDDINGS=1'))) {
572
+ return;
573
+ }
574
+ console.error('[shieldcortex] Failed to regenerate embedding:', e);
575
+ });
576
+ }
542
577
  /**
543
578
  * Update a memory
544
579
  */
@@ -635,11 +670,26 @@ export function updateMemory(id, updates) {
635
670
  fields.push('memory_scope = ?');
636
671
  values.push(updates.memoryScope);
637
672
  }
673
+ // STALENESS: if the embedded text (title/content) changes, the persisted
674
+ // `memories.embedding` no longer reflects the current content. The recall reuse
675
+ // path (findSimilarMemories) scores candidates straight off this column, so a
676
+ // stale vector would let recall match on outdated content. Clear it in the SAME
677
+ // UPDATE — no window where the old vector is readable — then recompute below,
678
+ // mirroring addMemory's fire-and-forget embedding write. Cleared-but-not-yet-
679
+ // recomputed rows are simply absent from vector recall until the recompute
680
+ // lands (FTS still covers them); a stale match is the unacceptable outcome.
681
+ const embeddedTextChanged = updates.title !== undefined || updates.content !== undefined;
682
+ if (embeddedTextChanged) {
683
+ fields.push('embedding = NULL');
684
+ }
638
685
  if (fields.length === 0)
639
686
  return existing;
640
687
  values.push(id);
641
688
  db.prepare(`UPDATE memories SET ${fields.join(', ')}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`).run(...values);
642
689
  const updatedMemory = getMemoryById(id);
690
+ if (embeddedTextChanged) {
691
+ refreshEmbeddingAsync(updatedMemory.id, updatedMemory.title, updatedMemory.content);
692
+ }
643
693
  const shouldRefreshGraph = updates.title !== undefined ||
644
694
  updates.content !== undefined ||
645
695
  updates.category !== undefined;
@@ -750,6 +800,7 @@ export function mergeMemories(keptId, removedId, options, source = { type: 'cli'
750
800
  cloud_excluded = ?,
751
801
  access_count = ?,
752
802
  last_accessed = ?,
803
+ embedding = NULL,
753
804
  updated_at = CURRENT_TIMESTAMP
754
805
  WHERE id = ?
755
806
  `).run(mergedContent, JSON.stringify(mergedTags), mergedSalience, mergedProject, JSON.stringify(mergedMetadata), mergedScope, mergedTransferable ? 1 : 0, mergedStatus, mergedPinned ? 1 : 0, mergedReviewedBy, new Date().toISOString(), mergedTrustScore, mergedSensitivity, mergedCloudExcluded ? 1 : 0, mergedAccessCount, mergedLastAccessed, kept.id);
@@ -761,6 +812,10 @@ export function mergeMemories(keptId, removedId, options, source = { type: 'cli'
761
812
  catch (e) {
762
813
  console.error('[shieldcortex] Entity extraction refresh failed after merge:', e);
763
814
  }
815
+ // The merge UPDATE cleared `embedding` (the merged content differs from the
816
+ // pre-merge vector); recompute it for the new canonical content so the recall
817
+ // reuse path never scores against a stale pre-merge vector.
818
+ refreshEmbeddingAsync(updatedMemory.id, updatedMemory.title, updatedMemory.content);
764
819
  emitMemoryUpdated(updatedMemory);
765
820
  persistEvent('memory_updated', { memory: updatedMemory, mergedFromId: removed.id });
766
821
  if (isFeatureEnabled('cloud_sync')) {
@@ -827,18 +882,43 @@ export function getProjectMemories(project, config = DEFAULT_CONFIG) {
827
882
  });
828
883
  }
829
884
  /**
830
- * Get recent memories
885
+ * Build the shared `WHERE` fragment for project + type + category filters.
886
+ * Returned `clause` is the full `WHERE ...` string (empty when no filters),
887
+ * so the SAME predicate drives both the page query and its COUNT(*) — keeping
888
+ * pagination `total`/`hasMore` honest under filters (Phase 17 A3).
831
889
  */
832
- export function getRecentMemories(limit = 10, project, source) {
833
- const db = getDatabase();
834
- let sql = 'SELECT * FROM memories';
890
+ function buildMemoryFilterClause(project, filters) {
891
+ const conds = [];
835
892
  const params = [];
836
893
  if (project) {
837
- sql += ' WHERE project = ?';
894
+ conds.push('project = ?');
838
895
  params.push(project);
839
896
  }
897
+ if (filters?.type) {
898
+ conds.push('type = ?');
899
+ params.push(filters.type);
900
+ }
901
+ if (filters?.category) {
902
+ conds.push('category = ?');
903
+ params.push(filters.category);
904
+ }
905
+ return { clause: conds.length ? `WHERE ${conds.join(' AND ')}` : '', params };
906
+ }
907
+ /**
908
+ * Count memories matching the project + type/category filters. Used by the
909
+ * dashboard memories route so `total`/`hasMore` reflect the filtered set.
910
+ */
911
+ export function countMemories(project, filters) {
912
+ const db = getDatabase();
913
+ const { clause, params } = buildMemoryFilterClause(project, filters);
914
+ return db.prepare(`SELECT COUNT(*) as count FROM memories ${clause}`).get(...params).count;
915
+ }
916
+ export function getRecentMemories(limit = 10, project, source, filters) {
917
+ const db = getDatabase();
918
+ const { clause, params } = buildMemoryFilterClause(project, filters);
919
+ let sql = `SELECT * FROM memories ${clause}`;
840
920
  sql += ' ORDER BY last_accessed DESC LIMIT ?';
841
- params.push(source ? limit * 2 : limit); // over-fetch when filtering
921
+ params.push(source ? limit * 2 : limit); // over-fetch when access-filtering
842
922
  let rows = db.prepare(sql).all(...params);
843
923
  if (source)
844
924
  rows = filterRowsByAccess(rows, source);
@@ -860,17 +940,22 @@ export function getMemoriesByType(type, limit = 50) {
860
940
  /**
861
941
  * Get high-priority memories (for context injection)
862
942
  */
863
- export function getHighPriorityMemories(limit = 10, project, source) {
943
+ export function getHighPriorityMemories(limit = 10, project, source, filters) {
864
944
  const db = getDatabase();
865
- let sql = `
866
- SELECT * FROM memories
867
- WHERE salience >= 0.6
868
- `;
945
+ let sql = `SELECT * FROM memories WHERE salience >= 0.6`;
869
946
  const params = [];
870
947
  if (project) {
871
948
  sql += ' AND project = ?';
872
949
  params.push(project);
873
950
  }
951
+ if (filters?.type) {
952
+ sql += ' AND type = ?';
953
+ params.push(filters.type);
954
+ }
955
+ if (filters?.category) {
956
+ sql += ' AND category = ?';
957
+ params.push(filters.category);
958
+ }
874
959
  sql += ' ORDER BY salience DESC, last_accessed DESC LIMIT ?';
875
960
  params.push(source ? limit * 2 : limit);
876
961
  let rows = db.prepare(sql).all(...params);
@@ -878,6 +963,25 @@ export function getHighPriorityMemories(limit = 10, project, source) {
878
963
  rows = filterRowsByAccess(rows, source);
879
964
  return rows.slice(0, limit).map(rowToMemory);
880
965
  }
966
+ /** Count high-priority (salience >= 0.6) memories matching the filters. */
967
+ export function countHighPriorityMemories(project, filters) {
968
+ const db = getDatabase();
969
+ let sql = `SELECT COUNT(*) as count FROM memories WHERE salience >= 0.6`;
970
+ const params = [];
971
+ if (project) {
972
+ sql += ' AND project = ?';
973
+ params.push(project);
974
+ }
975
+ if (filters?.type) {
976
+ sql += ' AND type = ?';
977
+ params.push(filters.type);
978
+ }
979
+ if (filters?.category) {
980
+ sql += ' AND category = ?';
981
+ params.push(filters.category);
982
+ }
983
+ return db.prepare(sql).get(...params).count;
984
+ }
881
985
  /**
882
986
  * Get memory statistics
883
987
  */