shieldcortex 4.27.2 → 4.28.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 (248) hide show
  1. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  2. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  3. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
  35. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
  36. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
  38. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  39. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
  40. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  41. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  42. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  43. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
  44. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
  45. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
  46. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
  47. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  48. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  49. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
  50. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
  51. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
  52. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
  53. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
  54. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
  55. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
  56. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
  57. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  58. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  59. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
  60. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
  61. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
  62. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
  63. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
  64. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
  65. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
  66. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
  67. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  68. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  69. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
  70. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
  71. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
  72. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
  73. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
  74. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
  75. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
  76. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
  77. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  78. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  79. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
  80. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
  81. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
  82. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
  83. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
  84. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
  85. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
  86. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
  87. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  88. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  89. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
  90. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
  91. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
  92. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
  93. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
  94. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
  95. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
  96. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
  97. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  98. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  99. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
  100. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
  101. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
  102. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
  103. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
  104. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
  105. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
  106. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  107. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  108. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
  109. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
  110. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
  111. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
  112. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
  113. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
  114. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
  115. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
  116. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  117. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
  118. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
  119. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
  120. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
  121. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
  122. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
  123. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
  125. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  126. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  127. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
  128. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
  129. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
  130. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
  131. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
  132. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
  133. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
  134. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
  135. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  136. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  137. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
  138. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
  139. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
  140. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
  141. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
  142. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
  143. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
  144. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
  145. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  146. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  147. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
  148. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
  149. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
  150. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
  151. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
  152. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
  153. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
  154. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
  155. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  156. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  157. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
  158. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
  159. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
  160. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
  161. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
  162. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
  163. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
  164. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
  165. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  166. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  167. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
  168. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
  169. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
  170. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
  171. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
  172. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
  173. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
  174. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  175. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  176. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
  177. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
  178. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
  179. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
  180. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
  181. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
  182. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
  183. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
  184. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  185. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  186. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  187. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  188. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  189. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
  190. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
  191. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
  192. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
  193. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  194. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  195. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
  196. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
  197. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
  198. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
  199. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
  200. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
  201. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
  202. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  203. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  204. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
  205. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
  206. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
  207. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
  208. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
  209. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
  210. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
  211. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
  212. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  213. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
  214. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
  215. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
  216. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
  217. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
  218. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  219. package/dist/api/routes/memories.js +1 -1
  220. package/dist/api/sql-classifier.d.ts +32 -0
  221. package/dist/api/sql-classifier.js +277 -0
  222. package/dist/api/visualization-server.d.ts +39 -0
  223. package/dist/api/visualization-server.js +152 -91
  224. package/dist/cloud/cli.js +20 -1
  225. package/dist/cloud/config.js +21 -1
  226. package/dist/cloud/memory-sync.d.ts +5 -0
  227. package/dist/cloud/memory-sync.js +5 -1
  228. package/dist/cloud/verify.js +2 -1
  229. package/dist/database/inline-schema.js +3 -0
  230. package/dist/database/migrations.js +25 -0
  231. package/dist/database/schema.sql +5 -0
  232. package/dist/defence/trust/env-detector.d.ts +31 -0
  233. package/dist/defence/trust/env-detector.js +50 -0
  234. package/dist/defence/trust/index.d.ts +4 -1
  235. package/dist/defence/trust/index.js +2 -1
  236. package/dist/defence/trust/resolve-tool-source.d.ts +27 -0
  237. package/dist/defence/trust/resolve-tool-source.js +80 -0
  238. package/dist/memory/consolidate.js +13 -0
  239. package/dist/memory/store.d.ts +1 -1
  240. package/dist/memory/store.js +13 -1
  241. package/dist/server.js +22 -32
  242. package/package.json +3 -2
  243. package/scripts/lib/capture-prompt.mjs +160 -0
  244. package/scripts/lib/session-capture.mjs +8 -2
  245. package/scripts/prompt-recall-hook.mjs +11 -2
  246. /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_buildManifest.js +0 -0
  247. /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_clientMiddlewareManifest.json +0 -0
  248. /package/dashboard/.next/standalone/dashboard/.next/static/{x2AmqK_Ci5s40_dIsKhc_ → 3HiFjAMoQUDn05ZMNC0Ae}/_ssgManifest.js +0 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Resolve and harden the source of an MCP tool call.
3
+ *
4
+ * MCP callers can self-declare any source they like. This module:
5
+ * 1. Always computes the environment-inferred trust ceiling first.
6
+ * 2. Clamps any over-claimed declared source down to that ceiling.
7
+ * 3. Writes a `SOURCE_ELEVATION_BLOCKED` row to defence_audit when a clamp
8
+ * happens, so operators can spot prompt-injection trying to escalate
9
+ * its own trust.
10
+ * 4. Writes a `SOURCE_MISSING` row when no source was declared, preserving
11
+ * the existing visibility into unconfigured callers.
12
+ */
13
+ import { clampSourceToCeiling } from './env-detector.js';
14
+ import { logAudit } from '../audit/logger.js';
15
+ /**
16
+ * Resolve the effective source for an MCP tool call.
17
+ *
18
+ * Returns the source the rest of the pipeline should use. When a caller
19
+ * over-claims trust the declared source is dropped, an audit row is written,
20
+ * and the env-inferred source is returned instead.
21
+ */
22
+ export function resolveToolSource(declaredSource, options) {
23
+ const clampResult = clampSourceToCeiling(declaredSource);
24
+ const { source, clamped, declaredScore, ceilingScore, detection } = clampResult;
25
+ if (clamped && declaredSource) {
26
+ try {
27
+ logAudit({
28
+ memory_id: null,
29
+ project: options.project,
30
+ timestamp: new Date().toISOString(),
31
+ source_type: source.type,
32
+ source_identifier: source.identifier,
33
+ trust_score: ceilingScore,
34
+ sensitivity_level: 'PUBLIC',
35
+ firewall_result: 'BLOCK',
36
+ anomaly_score: 0,
37
+ threat_indicators: JSON.stringify(['privilege_escalation']),
38
+ blocked_patterns: '[]',
39
+ reason: `SOURCE_ELEVATION_BLOCKED: tool=${options.toolName}, ` +
40
+ `declared=${declaredSource.type}:${declaredSource.identifier} (score=${declaredScore}), ` +
41
+ `clamped=${source.type}:${source.identifier} (score=${ceilingScore}) ` +
42
+ `via ${detection.method} (confidence: ${detection.confidence})`,
43
+ fragmentation_score: null,
44
+ pipeline_duration_ms: null,
45
+ });
46
+ }
47
+ catch {
48
+ // Audit logging must never break tool execution.
49
+ }
50
+ return source;
51
+ }
52
+ // No declared source — inferred from environment. Preserve the existing
53
+ // SOURCE_MISSING visibility so operators see unconfigured callers.
54
+ if (!declaredSource) {
55
+ try {
56
+ logAudit({
57
+ memory_id: null,
58
+ project: options.project,
59
+ timestamp: new Date().toISOString(),
60
+ source_type: source.type,
61
+ source_identifier: source.identifier,
62
+ trust_score: 0,
63
+ sensitivity_level: 'PUBLIC',
64
+ firewall_result: 'ALLOW',
65
+ anomaly_score: 0,
66
+ threat_indicators: '[]',
67
+ blocked_patterns: '[]',
68
+ reason: `SOURCE_MISSING: tool=${options.toolName}, ` +
69
+ `inferred=${source.type}:${source.identifier} ` +
70
+ `via ${detection.method} (confidence: ${detection.confidence})`,
71
+ fragmentation_score: null,
72
+ pipeline_duration_ms: null,
73
+ });
74
+ }
75
+ catch {
76
+ // Audit logging must never break tool execution.
77
+ }
78
+ }
79
+ return source;
80
+ }
@@ -10,6 +10,7 @@
10
10
  import { getDatabase, withTransaction } from '../database/init.js';
11
11
  import { DEFAULT_CONFIG, } from './types.js';
12
12
  import { getMemoriesByType, getRecentMemories, promoteMemory, deleteMemory, searchMemories, getMemoryStats, updateDecayScores, addMemory, rowToMemory, } from './store.js';
13
+ import { runDefencePipeline } from '../defence/index.js';
13
14
  import { processDecay, } from './decay.js';
14
15
  import { detectContradictions, linkContradictions, } from './contradiction.js';
15
16
  import { jaccardSimilarity } from './similarity.js';
@@ -276,6 +277,18 @@ export function deduplicateMemories(options) {
276
277
  .filter(s => s.length > 0 && !keptSentences.has(s.toLowerCase()));
277
278
  if (uniqueSentences.length > 0) {
278
279
  const mergedContent = kept.content + '\n\nMerged from duplicate:\n' + uniqueSentences.join('. ') + '.';
280
+ // DEFENCE PIPELINE: re-scan the merged content. Two individually-clean
281
+ // memories can produce content that straddles a credential pattern
282
+ // across the join. Without this re-scan the "every byte in `memories`
283
+ // has been scanned" invariant is broken. If the merge is blocked, skip
284
+ // both the content update AND the delete so the source rows survive.
285
+ const dedupSource = { type: 'hook', identifier: 'hook:consolidation' };
286
+ const defenceResult = runDefencePipeline(mergedContent, kept.title, dedupSource, undefined, kept.project ?? discarded.project ?? undefined);
287
+ if (defenceResult.firewall.result !== 'ALLOW') {
288
+ // Surface in audit (already written by the pipeline) and skip this pair.
289
+ console.warn(`[shieldcortex] Dedup merge blocked for memory ${kept.id} + ${removedId}: ${defenceResult.firewall.reason}`);
290
+ continue;
291
+ }
279
292
  db.prepare('UPDATE memories SET content = ? WHERE id = ?').run(mergedContent, kept.id);
280
293
  }
281
294
  deleteMemory(removedId);
@@ -46,7 +46,7 @@ export declare function getMemoryById(id: number, source?: DefenceSource): Memor
46
46
  export declare function updateMemory(id: number, updates: Partial<MemoryInput>): Memory | null;
47
47
  export declare function mergeMemories(keptId: number, removedId: number, options?: {
48
48
  reviewedBy?: string | null;
49
- }): Memory | null;
49
+ }, source?: DefenceSource): Memory | null;
50
50
  /**
51
51
  * Delete a memory
52
52
  */
@@ -672,7 +672,7 @@ function uniqueSentencesFrom(source, existing) {
672
672
  .map((sentence) => sentence.trim())
673
673
  .filter((sentence) => sentence.length > 0 && !existingSentences.has(sentence.toLowerCase()));
674
674
  }
675
- export function mergeMemories(keptId, removedId, options) {
675
+ export function mergeMemories(keptId, removedId, options, source = { type: 'cli', identifier: 'merge' }) {
676
676
  if (keptId === removedId)
677
677
  return getMemoryById(keptId);
678
678
  return withTransaction(() => {
@@ -685,6 +685,18 @@ export function mergeMemories(keptId, removedId, options) {
685
685
  const mergedContent = mergedSnippets.length > 0
686
686
  ? `${kept.content}\n\nMerged from duplicate (${removed.title}):\n${mergedSnippets.join('. ')}.`
687
687
  : kept.content;
688
+ // DEFENCE PIPELINE: re-scan the *merged* content. Two individually-clean
689
+ // memories can produce content that straddles a credential or injection
690
+ // pattern across the join (kept.content + " " + removed sentences). This
691
+ // is the one path that mechanically constructs new content from existing
692
+ // rows — without this re-scan the "every byte in `memories` has been
693
+ // scanned" invariant is broken. Throwing here rolls back the transaction
694
+ // so neither the kept row nor the removed row changes.
695
+ const mergedTitle = kept.title;
696
+ const defenceResult = runDefencePipeline(mergedContent, mergedTitle, source, undefined, kept.project ?? removed.project ?? undefined);
697
+ if (defenceResult.firewall.result !== 'ALLOW') {
698
+ throw new MemoryBlockedError(defenceResult.firewall.reason);
699
+ }
688
700
  const mergedTags = Array.from(new Set([...(kept.tags ?? []), ...(removed.tags ?? [])]));
689
701
  const mergedFrom = Array.isArray(kept.metadata?.mergedFrom)
690
702
  ? [...kept.metadata.mergedFrom]
package/dist/server.js CHANGED
@@ -22,16 +22,22 @@ import { handleGraphQuery, handleGraphEntities, handleGraphExplain } from './too
22
22
  import { checkDatabaseSize } from './database/init.js';
23
23
  import { queryAuditLogs, getAuditStats, getLifetimeStats } from './defence/audit/index.js';
24
24
  import { scanExistingMemories } from './defence/scanner/index.js';
25
- import { resolveSource } from './defence/trust/env-detector.js';
26
- import { logAudit } from './defence/audit/logger.js';
25
+ import { resolveToolSource as resolveToolSourceImpl } from './defence/trust/resolve-tool-source.js';
27
26
  import { scanToolResponse, shouldScanToolResponse } from './defence/tool-response-scanner.js';
28
27
  import { getToolResponseScanConfig } from './cloud/config.js';
29
28
  import { isKillSwitchActive, getKillSwitchMeta, assertOperationAllowed, activateKillSwitch, deactivateKillSwitch, KillSwitchError, } from './api/control.js';
30
- // Shared source schema for access control on MCP tools
29
+ // Shared source schema for access control on MCP tools.
30
+ // NOTE: 'user' is intentionally NOT accepted from MCP callers. MCP tools are
31
+ // always invoked by an agent, hook, CLI or API — never by a literal human
32
+ // typing — so accepting type:'user' would let a prompt-injected agent
33
+ // self-attest as the human operator and earn trust=1.0, bypassing the
34
+ // quarantine band and RESTRICTED read gating. The 'user' type still exists
35
+ // internally for things like dashboard-originated writes, but it must never
36
+ // be honoured when it arrives over the MCP transport.
31
37
  const sourceParam = z.object({
32
- type: z.enum(['user', 'cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response']),
38
+ type: z.enum(['cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response']),
33
39
  identifier: z.string(),
34
- }).optional().describe('Caller identity for access control (agents should pass this)');
40
+ }).optional().describe('Caller identity for access control (agents should pass this). type:"user" is rejected — MCP is never a human channel.');
35
41
  /**
36
42
  * Wrap an MCP tool handler to scan its response for threats.
37
43
  * Advisory mode: appends a warning but never blocks.
@@ -67,35 +73,19 @@ function withResponseScan(toolName, handler) {
67
73
  };
68
74
  }
69
75
  /**
70
- * Resolve source for an MCP tool call, inferring from environment if not declared.
71
- * Logs an audit warning when source is missing (gives operators visibility).
76
+ * Resolve source for an MCP tool call.
77
+ *
78
+ * Delegates to the env-ceiling clamp helper, which:
79
+ * - Drops any caller-declared source that claims higher trust than the
80
+ * runtime environment justifies (writes SOURCE_ELEVATION_BLOCKED to audit).
81
+ * - Falls back to env-inferred source when none was declared (writes
82
+ * SOURCE_MISSING to audit for operator visibility).
72
83
  */
73
84
  function resolveToolSource(declaredSource, toolName) {
74
- const { source, inferred, detection } = resolveSource(declaredSource);
75
- if (inferred) {
76
- try {
77
- logAudit({
78
- memory_id: null,
79
- project: getActiveProject(),
80
- timestamp: new Date().toISOString(),
81
- source_type: source.type,
82
- source_identifier: source.identifier,
83
- trust_score: 0,
84
- sensitivity_level: 'PUBLIC',
85
- firewall_result: 'ALLOW',
86
- anomaly_score: 0,
87
- threat_indicators: '[]',
88
- blocked_patterns: '[]',
89
- reason: `SOURCE_MISSING: tool=${toolName}, inferred=${source.type}:${source.identifier} via ${detection?.method ?? 'default'} (confidence: ${detection?.confidence ?? 'low'})`,
90
- fragmentation_score: null,
91
- pipeline_duration_ms: null,
92
- });
93
- }
94
- catch {
95
- // Audit logging should never break tool execution
96
- }
97
- }
98
- return source;
85
+ return resolveToolSourceImpl(declaredSource, {
86
+ toolName,
87
+ project: getActiveProject(),
88
+ });
99
89
  }
100
90
  /**
101
91
  * Wrap an MCP tool handler to enforce kill switch lockdown.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shieldcortex",
3
- "version": "4.27.2",
3
+ "version": "4.28.0",
4
4
  "description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, Codex, OpenClaw, LangChain, and MCP agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -61,7 +61,8 @@
61
61
  "bench:smoke": "SHIELDCORTEX_SKIP_EMBEDDINGS=1 tsx benchmark/longmemeval/run.ts --quiet",
62
62
  "audit:security": "npm audit --audit-level=moderate",
63
63
  "prepack": "node scripts/ensure-bin-executable.mjs",
64
- "prepublishOnly": "npm run build"
64
+ "version": "node scripts/sync-plugin-version.mjs && git add plugins/openclaw/package.json plugins/openclaw/openclaw.plugin.json",
65
+ "prepublishOnly": "node scripts/sync-plugin-version.mjs --check && npm run build"
65
66
  },
66
67
  "keywords": [
67
68
  "ai-memory",
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Hook-side prompt capture sanitiser (Fix #10).
3
+ *
4
+ * UserPromptSubmit historically stored the raw prompt text verbatim into
5
+ * `session_events`. Pasting a `.env` file (or any other credential-laden
6
+ * snippet) into Claude Code persisted it forever and the dashboard's session
7
+ * replay UI surfaced it on demand.
8
+ *
9
+ * This module runs the defence pipeline's credential redaction + sensitivity
10
+ * classifier against the prompt BEFORE it lands in `session_events`, returning:
11
+ * - redactedText: prompt with credentials replaced by [REDACTED-…] markers
12
+ * - sensitivity: classifier level (PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED)
13
+ * - findings: credential scan findings (already-redacted match previews)
14
+ * - redactedCount: number of credentials that were rewritten
15
+ *
16
+ * Fail-closed: if the dist defence modules cannot be loaded (dev workspace
17
+ * without `npm run build`, missing dist/, broken import), the caller gets a
18
+ * placeholder payload tagged RESTRICTED and a stderr warning. That keeps the
19
+ * raw text out of the database under all failure modes.
20
+ *
21
+ * Mirrors the lazy-loader pattern used by scripts/lib/save-memory.mjs so both
22
+ * hooks share the same dist resolution rules.
23
+ */
24
+
25
+ import { dirname, resolve } from 'path';
26
+ import { fileURLToPath, pathToFileURL } from 'url';
27
+
28
+ const FAIL_CLOSED_PLACEHOLDER = '[defence_unavailable: prompt suppressed]';
29
+
30
+ let _defenceCache = null;
31
+ let _defenceCacheKey = null;
32
+
33
+ /**
34
+ * Sanitise a raw user prompt for safe storage in `session_events`.
35
+ *
36
+ * @param {string} rawText - The raw user prompt as received by the hook.
37
+ * @returns {Promise<{ redactedText: string, sensitivity: string, findings: Array, redactedCount: number }>}
38
+ */
39
+ export async function captureForSessionEvent(rawText) {
40
+ const text = typeof rawText === 'string' ? rawText : '';
41
+
42
+ const defence = await loadDefenceModules();
43
+ if (!defence) {
44
+ process.stderr.write(
45
+ '[shieldcortex capture-prompt] defence modules unavailable — prompt suppressed (fail-closed)\n',
46
+ );
47
+ return {
48
+ redactedText: FAIL_CLOSED_PLACEHOLDER,
49
+ sensitivity: 'RESTRICTED',
50
+ findings: [],
51
+ redactedCount: 0,
52
+ };
53
+ }
54
+
55
+ // ── Credential redaction ──
56
+ // scanForCredentials gives both the redacted body and the findings array.
57
+ // redactCredentials would do the same string transform but throw away the
58
+ // findings — we want both so the caller can count and (later) audit.
59
+ let scan;
60
+ try {
61
+ scan = defence.scanForCredentials(text);
62
+ } catch (err) {
63
+ const msg = err && err.message ? err.message : String(err);
64
+ process.stderr.write(
65
+ `[shieldcortex capture-prompt] credential scan failed (${msg}) — prompt suppressed (fail-closed)\n`,
66
+ );
67
+ return {
68
+ redactedText: FAIL_CLOSED_PLACEHOLDER,
69
+ sensitivity: 'RESTRICTED',
70
+ findings: [],
71
+ redactedCount: 0,
72
+ };
73
+ }
74
+
75
+ const findings = Array.isArray(scan?.findings) ? scan.findings : [];
76
+ const redactedText = scan?.redactedContent ?? text;
77
+ const redactedCount = findings.length;
78
+
79
+ // ── Sensitivity classification ──
80
+ // Classifier is sync and pattern-based — failures here shouldn't fail-close
81
+ // the whole capture (we still have a useful redaction). Degrade to INTERNAL.
82
+ let sensitivity = 'INTERNAL';
83
+ try {
84
+ const classification = defence.classifySensitivity(text, '');
85
+ if (classification && typeof classification.level === 'string') {
86
+ sensitivity = classification.level;
87
+ }
88
+ } catch {
89
+ // Best-effort — keep INTERNAL default.
90
+ }
91
+
92
+ // If credentials were found, force at least CONFIDENTIAL. The classifier
93
+ // catches "api_key=" style markers but raw secret strings without context
94
+ // can slip past it, and we never want a prompt full of secrets tagged
95
+ // PUBLIC or INTERNAL just because the surrounding text was unremarkable.
96
+ if (redactedCount > 0 && (sensitivity === 'PUBLIC' || sensitivity === 'INTERNAL')) {
97
+ sensitivity = 'CONFIDENTIAL';
98
+ }
99
+
100
+ return {
101
+ redactedText,
102
+ sensitivity,
103
+ findings,
104
+ redactedCount,
105
+ };
106
+ }
107
+
108
+ // ==================== Internal: lazy dist loader ====================
109
+
110
+ async function loadDefenceModules() {
111
+ // capture-prompt.mjs lives at scripts/lib/, so dist is two directories up.
112
+ const here = dirname(fileURLToPath(import.meta.url));
113
+ const distRoot = resolve(here, '..', '..', 'dist');
114
+
115
+ if (_defenceCache && _defenceCacheKey === distRoot) {
116
+ return _defenceCache;
117
+ }
118
+
119
+ try {
120
+ const credentialUrl = pathToFileURL(
121
+ resolve(distRoot, 'defence', 'credential-leak', 'index.js'),
122
+ ).href;
123
+ const sensitivityUrl = pathToFileURL(
124
+ resolve(distRoot, 'defence', 'sensitivity', 'index.js'),
125
+ ).href;
126
+
127
+ const [credentialMod, sensitivityMod] = await Promise.all([
128
+ import(credentialUrl),
129
+ import(sensitivityUrl),
130
+ ]);
131
+
132
+ if (
133
+ typeof credentialMod.scanForCredentials !== 'function'
134
+ || typeof credentialMod.redactCredentials !== 'function'
135
+ || typeof sensitivityMod.classifySensitivity !== 'function'
136
+ ) {
137
+ return null;
138
+ }
139
+
140
+ _defenceCache = {
141
+ scanForCredentials: credentialMod.scanForCredentials,
142
+ redactCredentials: credentialMod.redactCredentials,
143
+ classifySensitivity: sensitivityMod.classifySensitivity,
144
+ };
145
+ _defenceCacheKey = distRoot;
146
+ return _defenceCache;
147
+ } catch {
148
+ return null;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Test-only: reset the lazy-load cache so unit tests can simulate dist-missing
154
+ * failure modes without spinning up a second process. Not exported via the
155
+ * scripts barrel — only the tests reach for it.
156
+ */
157
+ export function __resetCacheForTests() {
158
+ _defenceCache = null;
159
+ _defenceCacheKey = null;
160
+ }
@@ -21,10 +21,14 @@ const VALID_KINDS = new Set([
21
21
  'hook_fire',
22
22
  ]);
23
23
 
24
+ // v4.28 (Fix #10): `sensitivity_level` carries the defence classifier verdict
25
+ // (PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED) so the dashboard replay UI
26
+ // can mask/strip rows that contain credentials or otherwise-sensitive prompts.
27
+ // Defaults to 'INTERNAL' for events written by callers that don't set it.
24
28
  const INSERT_SQL = `
25
29
  INSERT INTO session_events
26
- (session_id, project, ts, kind, actor, payload, duration_ms, audit_id)
27
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
30
+ (session_id, project, ts, kind, actor, payload, duration_ms, audit_id, sensitivity_level)
31
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
28
32
  `;
29
33
 
30
34
  /** Stringify payload — objects → JSON, strings pass through verbatim. */
@@ -60,6 +64,7 @@ export function recordSessionEvent(db, event) {
60
64
  serialisePayload(event.payload),
61
65
  event.duration_ms ?? null,
62
66
  event.audit_id ?? null,
67
+ event.sensitivity_level ?? 'INTERNAL',
63
68
  );
64
69
  return Number(result.lastInsertRowid);
65
70
  } catch (err) {
@@ -93,6 +98,7 @@ export function recordSessionEvents(db, events) {
93
98
  serialisePayload(event.payload),
94
99
  event.duration_ms ?? null,
95
100
  event.audit_id ?? null,
101
+ event.sensitivity_level ?? 'INTERNAL',
96
102
  );
97
103
  ids.push(Number(result.lastInsertRowid));
98
104
  }
@@ -17,6 +17,7 @@ import { homedir } from 'os';
17
17
  import { deriveProjectKey } from './lib/project-key.mjs';
18
18
  import { sanitisePromptForRecall } from './lib/prompt-sanitiser.mjs';
19
19
  import { recordSessionEvent } from './lib/session-capture.mjs';
20
+ import { captureForSessionEvent } from './lib/capture-prompt.mjs';
20
21
  import { truncatePreservingWords } from './lib/truncate.mjs';
21
22
  import { compareRecallResults } from './lib/recall-rank.mjs';
22
23
  import { computeEffectiveSalience } from './lib/salience.mjs';
@@ -291,7 +292,7 @@ process.stdin.on('readable', () => {
291
292
  while ((chunk = process.stdin.read()) !== null) input += chunk;
292
293
  });
293
294
 
294
- process.stdin.on('end', () => {
295
+ process.stdin.on('end', async () => {
295
296
  try {
296
297
  const config = loadConfig();
297
298
  const hookData = JSON.parse(input || '{}');
@@ -303,19 +304,27 @@ process.stdin.on('end', () => {
303
304
  // proactiveRecall config so the dashboard replay timeline gets a
304
305
  // complete event stream. Opt-out via captureEvents=false. Failures
305
306
  // are swallowed — capture must never block the user prompt.
307
+ //
308
+ // Fix #10 (v4.28): redact credentials + classify sensitivity BEFORE the
309
+ // INSERT. Pasting a `.env` into Claude Code used to land verbatim in
310
+ // session_events; now it's routed through the defence pipeline first
311
+ // and the resulting sensitivity_level lets the dashboard mask/strip
312
+ // RESTRICTED rows from replay timelines.
306
313
  if (config.captureEvents !== false && sessionId && rawPrompt) {
307
314
  try {
308
315
  const project = deriveProjectKey(cwd);
309
316
  const dbPath = getDbPath();
310
317
  if (existsSync(dbPath)) {
318
+ const { redactedText, sensitivity } = await captureForSessionEvent(rawPrompt);
311
319
  const captureDb = new Database(dbPath, { timeout: 1000 });
312
320
  recordSessionEvent(captureDb, {
313
321
  session_id: sessionId,
314
322
  ts: new Date().toISOString(),
315
323
  kind: 'prompt',
316
- payload: { text: rawPrompt },
324
+ payload: { text: redactedText },
317
325
  project: project || null,
318
326
  actor: 'user',
327
+ sensitivity_level: sensitivity,
319
328
  });
320
329
  captureDb.close();
321
330
  }