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
@@ -40,7 +40,44 @@ import { registerDigestRoutes } from './routes/digest.js';
40
40
  import { registerSessionRoutes } from './routes/sessions.js';
41
41
  import { createIronDomeRouteGuard } from './iron-dome-route-guard.js';
42
42
  import { readAndClearDetectionEvents } from '../xray/activity.js';
43
+ import { classifySqlQuery } from './sql-classifier.js';
43
44
  const PORT = process.env.PORT || 3001;
45
+ // ── Defence source whitelist (Fix #13) ──────────────────────────────────────
46
+ // The DefenceSource.type field is part of the threat-model surface — caller-
47
+ // controlled `source.type` values pollute Iron Dome dashboards and audit
48
+ // queries. Normalise unknown values to 'api' silently (defence in depth) and
49
+ // cap identifier length to avoid log-explosion attacks.
50
+ const ALLOWED_DEFENCE_SOURCE_TYPES = [
51
+ 'user', 'cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response',
52
+ ];
53
+ const MAX_SOURCE_IDENTIFIER_LENGTH = 200;
54
+ /**
55
+ * Normalise an incoming `source` object from a REST request body into a
56
+ * trusted `DefenceSource`.
57
+ *
58
+ * - Unknown `type` values fall back to `'api'` (no rejection — defence in depth)
59
+ * - `identifier` longer than {@link MAX_SOURCE_IDENTIFIER_LENGTH} is truncated
60
+ * with an ellipsis ("…") so the truncation is visible in audit logs
61
+ * - Non-string identifiers fall back to `'rest-api'`
62
+ *
63
+ * Exported for unit tests.
64
+ */
65
+ export function normaliseDefenceSource(raw) {
66
+ const candidate = (raw ?? {});
67
+ const rawType = typeof candidate.type === 'string' ? candidate.type : undefined;
68
+ const type = rawType && ALLOWED_DEFENCE_SOURCE_TYPES.includes(rawType)
69
+ ? rawType
70
+ : 'api';
71
+ const rawIdentifier = typeof candidate.identifier === 'string' ? candidate.identifier : 'rest-api';
72
+ const identifier = rawIdentifier.length > MAX_SOURCE_IDENTIFIER_LENGTH
73
+ ? rawIdentifier.slice(0, MAX_SOURCE_IDENTIFIER_LENGTH - 1) + '…'
74
+ : rawIdentifier;
75
+ return { type, identifier };
76
+ }
77
+ export const __test__ = {
78
+ ALLOWED_DEFENCE_SOURCE_TYPES,
79
+ MAX_SOURCE_IDENTIFIER_LENGTH,
80
+ };
44
81
  /**
45
82
  * In-memory counters for FEATURE_GATED (403) responses per feature.
46
83
  * Lightweight telemetry to detect noisy free-tier clients hammering gated endpoints.
@@ -75,6 +112,95 @@ function requireProFeature(feature) {
75
112
  }
76
113
  // Track connected WebSocket clients
77
114
  const clients = new Set();
115
+ /**
116
+ * Handler for `POST /api/v1/scan`.
117
+ *
118
+ * Scans content through the defence pipeline. The `config` field on the
119
+ * request body is intentionally ignored — runtime always uses the persisted
120
+ * defence mode. Any attempt to override config is logged as a BLOCK with
121
+ * RESTRICTED sensitivity so incident-triage queries surface it (Fix #13).
122
+ *
123
+ * Exported for unit tests.
124
+ */
125
+ export function handleV1Scan(req, res) {
126
+ try {
127
+ const { content, title, source } = req.body;
128
+ if (!content || typeof content !== 'string') {
129
+ res.status(400).json({ error: 'content (string) is required' });
130
+ return;
131
+ }
132
+ // Log if caller tried to override config (potential tampering).
133
+ // Fix #13: record as BLOCK / RESTRICTED so incident-triage queries
134
+ // filtering on firewall_result IN ('BLOCK','QUARANTINE') surface
135
+ // config-tampering attempts.
136
+ if (req.body.config) {
137
+ try {
138
+ logAudit({
139
+ memory_id: null,
140
+ project: null,
141
+ timestamp: new Date().toISOString(),
142
+ source_type: 'api',
143
+ source_identifier: 'rest-api',
144
+ trust_score: 0,
145
+ sensitivity_level: 'RESTRICTED',
146
+ firewall_result: 'BLOCK',
147
+ anomaly_score: 0.5,
148
+ threat_indicators: '["config_tampering"]',
149
+ blocked_patterns: '[]',
150
+ reason: 'config_override_attempt: scan endpoint config parameter ignored',
151
+ fragmentation_score: null,
152
+ pipeline_duration_ms: 0,
153
+ });
154
+ }
155
+ catch { /* audit is best-effort */ }
156
+ }
157
+ // Fix #13: whitelist source.type and cap identifier length
158
+ const defenceSource = normaliseDefenceSource(source);
159
+ // Always use persisted config — no per-request overrides via HTTP
160
+ const defenceConfig = { ...DEFAULT_DEFENCE_CONFIG, mode: getDefenceMode() };
161
+ const result = runDefencePipeline(content, title ?? 'Untitled', defenceSource, defenceConfig);
162
+ res.json(result);
163
+ }
164
+ catch (error) {
165
+ res.status(500).json({ error: error.message });
166
+ }
167
+ }
168
+ /**
169
+ * Handler for `POST /api/v1/scan/batch`.
170
+ *
171
+ * Scans up to 100 items in one request. Like {@link handleV1Scan}, the
172
+ * `config` field is intentionally ignored; source is normalised through
173
+ * {@link normaliseDefenceSource} (Fix #13).
174
+ *
175
+ * Exported for unit tests.
176
+ */
177
+ export function handleV1ScanBatch(req, res) {
178
+ try {
179
+ const { items, source } = req.body;
180
+ if (!Array.isArray(items) || items.length === 0) {
181
+ res.status(400).json({ error: 'items (array) is required' });
182
+ return;
183
+ }
184
+ if (items.length > 100) {
185
+ res.status(400).json({ error: 'Maximum 100 items per batch' });
186
+ return;
187
+ }
188
+ // Fix #13: whitelist source.type and cap identifier length
189
+ const defenceSource = normaliseDefenceSource(source);
190
+ // Always use persisted config — no per-request overrides via HTTP
191
+ const defenceConfig = { ...DEFAULT_DEFENCE_CONFIG, mode: getDefenceMode() };
192
+ const results = items.map((item) => {
193
+ if (!item.content || typeof item.content !== 'string') {
194
+ return { error: 'content (string) is required', allowed: false };
195
+ }
196
+ return runDefencePipeline(item.content, item.title ?? 'Untitled', defenceSource, defenceConfig);
197
+ });
198
+ res.json({ results, total: results.length });
199
+ }
200
+ catch (error) {
201
+ res.status(500).json({ error: error.message });
202
+ }
203
+ }
78
204
  /**
79
205
  * Start the visualization API server
80
206
  */
@@ -157,15 +283,19 @@ export function startVisualizationServer(dbPath) {
157
283
  });
158
284
  }
159
285
  function classifySqlAction(req) {
160
- const query = typeof req.body?.query === 'string' ? req.body.query.trim().toUpperCase() : '';
161
- if (!query)
286
+ const query = typeof req.body?.query === 'string' ? req.body.query : '';
287
+ if (!query.trim())
162
288
  return 'database_migrate';
163
- if (query.startsWith('SELECT') || query.startsWith('PRAGMA'))
289
+ // PURGE is application-level (not a real SQL keyword) keep the regex check.
290
+ if (/\bPURGE\b/i.test(query))
291
+ return 'destroy';
292
+ const classification = classifySqlQuery(query);
293
+ if (classification.kind === 'read')
164
294
  return 'run_report';
165
- if (/\bDELETE\b/.test(query))
166
- return 'delete';
167
- if (/\bDROP\b|\bTRUNCATE\b|\bPURGE\b/.test(query))
295
+ if (classification.kind === 'destroy')
168
296
  return 'destroy';
297
+ if (classification.kind === 'write' && classification.operation === 'DELETE')
298
+ return 'delete';
169
299
  return 'database_migrate';
170
300
  }
171
301
  // ============================================
@@ -213,29 +343,30 @@ export function startVisualizationServer(dbPath) {
213
343
  if (!query || typeof query !== 'string') {
214
344
  return res.status(400).json({ error: 'Query string required' });
215
345
  }
216
- const upperQuery = query.toUpperCase().trim();
217
- // Always block DROP and TRUNCATE
218
- if (/\bDROP\b/.test(upperQuery) || /\bTRUNCATE\b/.test(upperQuery)) {
346
+ // Classify the query — robust against CTE prefixes that would bypass
347
+ // a naive `startsWith('INSERT'|'UPDATE'|...)` check, e.g.
348
+ // WITH t AS (SELECT 1) INSERT INTO memories VALUES (...)
349
+ const classification = classifySqlQuery(query);
350
+ // Always block DROP and TRUNCATE (and reject anything we can't classify)
351
+ if (classification.kind === 'destroy') {
219
352
  return res.status(403).json({
220
353
  error: 'DROP and TRUNCATE operations are blocked for safety',
221
354
  });
222
355
  }
356
+ if (classification.kind === 'reject') {
357
+ return res.status(400).json({
358
+ error: `Query rejected: ${classification.reason}`,
359
+ });
360
+ }
223
361
  // Block writes unless explicitly allowed
224
- const isWriteOperation = upperQuery.startsWith('INSERT') ||
225
- upperQuery.startsWith('UPDATE') ||
226
- upperQuery.startsWith('DELETE') ||
227
- upperQuery.startsWith('ALTER') ||
228
- upperQuery.startsWith('CREATE');
229
- if (isWriteOperation && !allowWrite) {
362
+ if (classification.kind === 'write' && !allowWrite) {
230
363
  return res.status(403).json({
231
364
  error: 'Write operations are disabled. Enable allowWrite to execute.',
232
365
  });
233
366
  }
234
367
  const db = getDatabase();
235
368
  const startTime = Date.now();
236
- // Execute query
237
- const isSelect = upperQuery.startsWith('SELECT') || upperQuery.startsWith('PRAGMA');
238
- if (isSelect) {
369
+ if (classification.kind === 'read') {
239
370
  const rows = db.prepare(query).all();
240
371
  const executionTime = Date.now() - startTime;
241
372
  // Get column names from first row or empty
@@ -248,7 +379,7 @@ export function startVisualizationServer(dbPath) {
248
379
  });
249
380
  }
250
381
  else {
251
- // Write operation
382
+ // Write operation (allowWrite === true at this point)
252
383
  const result = db.prepare(query).run();
253
384
  const executionTime = Date.now() - startTime;
254
385
  res.json({
@@ -563,78 +694,8 @@ export function startVisualizationServer(dbPath) {
563
694
  // BRAIN WORKER (Phase 4)
564
695
  // ============================================
565
696
  // ── Defence API v1 ──────────────────────────────────────────
566
- // Scan content through the defence pipeline
567
- // NOTE: config parameter is intentionally ignored — always uses persisted mode (security hardening)
568
- app.post('/api/v1/scan', (req, res) => {
569
- try {
570
- const { content, title, source } = req.body;
571
- if (!content || typeof content !== 'string') {
572
- return res.status(400).json({ error: 'content (string) is required' });
573
- }
574
- // Log if caller tried to override config (potential tampering)
575
- if (req.body.config) {
576
- try {
577
- logAudit({
578
- memory_id: null,
579
- project: null,
580
- timestamp: new Date().toISOString(),
581
- source_type: 'api',
582
- source_identifier: 'rest-api',
583
- trust_score: 0,
584
- sensitivity_level: 'INTERNAL',
585
- firewall_result: 'ALLOW',
586
- anomaly_score: 0.5,
587
- threat_indicators: '["config_tampering"]',
588
- blocked_patterns: '[]',
589
- reason: 'config_override_attempt: scan endpoint config parameter ignored',
590
- fragmentation_score: null,
591
- pipeline_duration_ms: 0,
592
- });
593
- }
594
- catch { /* audit is best-effort */ }
595
- }
596
- const defenceSource = {
597
- type: source?.type ?? 'api',
598
- identifier: source?.identifier ?? 'rest-api',
599
- };
600
- // Always use persisted config — no per-request overrides via HTTP
601
- const defenceConfig = { ...DEFAULT_DEFENCE_CONFIG, mode: getDefenceMode() };
602
- const result = runDefencePipeline(content, title ?? 'Untitled', defenceSource, defenceConfig);
603
- res.json(result);
604
- }
605
- catch (error) {
606
- res.status(500).json({ error: error.message });
607
- }
608
- });
609
- // Batch scan multiple items
610
- // NOTE: config parameter is intentionally ignored — always uses persisted mode (security hardening)
611
- app.post('/api/v1/scan/batch', (req, res) => {
612
- try {
613
- const { items, source } = req.body;
614
- if (!Array.isArray(items) || items.length === 0) {
615
- return res.status(400).json({ error: 'items (array) is required' });
616
- }
617
- if (items.length > 100) {
618
- return res.status(400).json({ error: 'Maximum 100 items per batch' });
619
- }
620
- const defenceSource = {
621
- type: source?.type ?? 'api',
622
- identifier: source?.identifier ?? 'rest-api',
623
- };
624
- // Always use persisted config — no per-request overrides via HTTP
625
- const defenceConfig = { ...DEFAULT_DEFENCE_CONFIG, mode: getDefenceMode() };
626
- const results = items.map((item) => {
627
- if (!item.content || typeof item.content !== 'string') {
628
- return { error: 'content (string) is required', allowed: false };
629
- }
630
- return runDefencePipeline(item.content, item.title ?? 'Untitled', defenceSource, defenceConfig);
631
- });
632
- res.json({ results, total: results.length });
633
- }
634
- catch (error) {
635
- res.status(500).json({ error: error.message });
636
- }
637
- });
697
+ app.post('/api/v1/scan', handleV1Scan);
698
+ app.post('/api/v1/scan/batch', handleV1ScanBatch);
638
699
  const brainWorker = new BrainWorker();
639
700
  registerIncidentRoutes(app);
640
701
  registerAdminRoutes(app, {
package/dist/cloud/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getCloudConfig, setCloudConfig, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, } from './config.js';
1
+ import { getCloudConfig, setCloudConfig, getCloudSyncControls, setCloudSyncControls, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, } from './config.js';
2
2
  const VALID_RANKER_ENGINES = ['rrf', 'legacy'];
3
3
  import { syncAllGraphToCloud } from './graph-sync.js';
4
4
  import { syncAllMemoriesToCloud } from './memory-sync.js';
@@ -16,12 +16,14 @@ export function handleCloudConfig(args) {
16
16
  const reviewCopilot = getReviewCopilotConfig();
17
17
  const openclawAutoMemory = getOpenClawAutoMemory();
18
18
  const ranker = getRankerConfig();
19
+ const syncControls = getCloudSyncControls();
19
20
  const rankerOverridden = !!process.env.SHIELDCORTEX_RANKER;
20
21
  console.log('\nShieldCortex Configuration:');
21
22
  console.log(` Defence Mode: ${mode}`);
22
23
  console.log(` Cloud Enabled: ${config.cloudEnabled ? 'Yes' : 'No'}`);
23
24
  console.log(` API Key: ${config.cloudApiKey ? config.cloudApiKey.substring(0, 12) + '...' : 'Not set'}`);
24
25
  console.log(` Base URL: ${config.cloudBaseUrl}`);
26
+ console.log(` Sensitive Memories: ${syncControls.excludeSensitive ? 'Excluded from sync (safe default)' : 'Included in sync'}`);
25
27
  console.log(` LLM Verify: ${verify.verifyEnabled ? 'Enabled' : 'Disabled'} (${verify.verifyMode}, ${verify.verifyTimeoutMs}ms timeout)`);
26
28
  console.log(` Verify Triggers: ${verify.verifyTriggers.join(', ')}`);
27
29
  console.log(` Local AI Explainer: ${reviewCopilot.enabled ? 'Enabled' : 'Disabled'} (${reviewCopilot.modelId})`);
@@ -65,6 +67,21 @@ export function handleCloudConfig(args) {
65
67
  console.log('Cloud sync disabled.');
66
68
  changed = true;
67
69
  }
70
+ // ── Sensitive-content opt-in/opt-out ──
71
+ // Default since v4.27: CONFIDENTIAL+ memories are NOT shipped to the cloud.
72
+ // Users who genuinely want to mirror sensitive content (e.g. self-hosted
73
+ // backend on their own network) can opt back in here.
74
+ if (args.includes('--cloud-include-sensitive')) {
75
+ setCloudSyncControls({ excludeSensitive: false });
76
+ console.log('Cloud sync will now include CONFIDENTIAL+ memories.');
77
+ console.log('Note: content is sent to your configured cloudBaseUrl in full.');
78
+ changed = true;
79
+ }
80
+ if (args.includes('--cloud-exclude-sensitive')) {
81
+ setCloudSyncControls({ excludeSensitive: true });
82
+ console.log('Cloud sync will skip CONFIDENTIAL+ memories (default).');
83
+ changed = true;
84
+ }
68
85
  // ── Verify flags ──
69
86
  if (args.includes('--verify-enable')) {
70
87
  const config = getCloudConfig();
@@ -190,6 +207,8 @@ export function handleCloudConfig(args) {
190
207
  console.log(' --cloud-url <url> Set cloud base URL');
191
208
  console.log(' --cloud-enable Enable cloud sync');
192
209
  console.log(' --cloud-disable Disable cloud sync');
210
+ console.log(' --cloud-include-sensitive Sync CONFIDENTIAL+ memories (off by default since v4.27)');
211
+ console.log(' --cloud-exclude-sensitive Stop syncing CONFIDENTIAL+ memories (default)');
193
212
  console.log(' --cloud-status Show current configuration');
194
213
  console.log(' --openclaw-auto-memory <true|false> Extract memories from OpenClaw LLM output (default: off)');
195
214
  console.log(' --proactive-recall <true|false> Inject SC memory into prompts (default: off — adds latency)');
@@ -18,11 +18,18 @@ function getIntegrityKeyFile() {
18
18
  return join(getConfigDir(), '.integrity-key');
19
19
  }
20
20
  const DEFAULT_BASE_URL = 'https://api.shieldcortex.ai';
21
+ // Safety-first defaults: CONFIDENTIAL+ memories are NOT shipped to the cloud
22
+ // unless the user explicitly opts in via `--cloud-include-sensitive` or the
23
+ // dashboard. Prior to the v4.27 flip, `excludeSensitive` defaulted to false,
24
+ // which meant enabling cloud sync silently shipped credential-bearing /
25
+ // classified content without per-record consent. `contentMode` stays 'full'
26
+ // so the opt-in sync stream remains useful for PUBLIC/INTERNAL records that
27
+ // the user did consent to share.
21
28
  const DEFAULT_SYNC_CONTROLS = {
22
29
  projectMode: 'all',
23
30
  projects: [],
24
31
  contentMode: 'full',
25
- excludeSensitive: false,
32
+ excludeSensitive: true,
26
33
  };
27
34
  const DEFAULT_REVIEW_COPILOT_CONFIG = {
28
35
  enabled: false,
@@ -164,6 +171,19 @@ function normalizeProjectList(value) {
164
171
  }
165
172
  export function getCloudSyncControls() {
166
173
  const raw = readRawConfig();
174
+ // One-shot v4.27 migration: pre-upgrade configs with cloud sync enabled
175
+ // were silently shipping CONFIDENTIAL+ content because `excludeSensitive`
176
+ // defaulted to false. Detect those configs (cloud on, no explicit setting,
177
+ // no prior migration stamp) and rewrite them to the new safe default. If
178
+ // the user later opts back in via `--cloud-include-sensitive`, that writes
179
+ // `cloudSyncExcludeSensitive: false` explicitly and this branch is skipped.
180
+ if (raw.cloudEnabled === true &&
181
+ typeof raw.cloudSyncExcludeSensitive !== 'boolean' &&
182
+ typeof raw.cloudSyncDefaultsMigratedAt !== 'string') {
183
+ raw.cloudSyncExcludeSensitive = true;
184
+ raw.cloudSyncDefaultsMigratedAt = new Date().toISOString();
185
+ writeRawConfig(raw);
186
+ }
167
187
  const projectMode = raw.cloudSyncProjectMode;
168
188
  const contentMode = raw.cloudSyncContentMode;
169
189
  return {
@@ -28,6 +28,11 @@ export interface MemorySyncEnvelope {
28
28
  platform: string;
29
29
  };
30
30
  }
31
+ /**
32
+ * Per-record sync gate. Exported for unit testing the safety contract:
33
+ * a CONFIDENTIAL record on fresh-default controls MUST return false.
34
+ */
35
+ export declare function shouldSyncRecord(record: Pick<SyncedMemoryRecord, 'project' | 'sensitivity_level' | 'cloud_excluded'>): boolean;
31
36
  export declare function syncMemoryUpsertToCloud(memory: Memory): void;
32
37
  export declare function syncMemoryDeleteToCloud(memory: Memory): void;
33
38
  export declare function syncAllMemoriesToCloud(): Promise<{
@@ -44,7 +44,11 @@ function buildEnvelope(records) {
44
44
  },
45
45
  };
46
46
  }
47
- function shouldSyncRecord(record) {
47
+ /**
48
+ * Per-record sync gate. Exported for unit testing the safety contract:
49
+ * a CONFIDENTIAL record on fresh-default controls MUST return false.
50
+ */
51
+ export function shouldSyncRecord(record) {
48
52
  if (record.cloud_excluded)
49
53
  return false;
50
54
  const controls = getCloudSyncControls();
@@ -27,9 +27,10 @@ export async function submitVerification(content, title, pipelineResult, source)
27
27
  }
28
28
  // Redact credentials before sending to cloud
29
29
  const cleanContent = redactCredentials(content);
30
+ const cleanTitle = redactCredentials(title);
30
31
  const payload = {
31
32
  content: cleanContent,
32
- title,
33
+ title: cleanTitle,
33
34
  source_type: source.type,
34
35
  source_identifier: source.identifier,
35
36
  anomaly_score: pipelineResult.firewall.anomalyScore,
@@ -295,6 +295,7 @@ export function getInlineSchema() {
295
295
  );
296
296
 
297
297
  -- v4.17 Session capture (mirrors schema.sql; bundled fallback only).
298
+ -- v4.28 (Fix #10): + sensitivity_level for prompt-redaction tagging.
298
299
  CREATE TABLE IF NOT EXISTS session_events (
299
300
  id INTEGER PRIMARY KEY AUTOINCREMENT,
300
301
  session_id TEXT NOT NULL,
@@ -308,11 +309,13 @@ export function getInlineSchema() {
308
309
  duration_ms INTEGER,
309
310
  audit_id INTEGER,
310
311
  content_hash TEXT,
312
+ sensitivity_level TEXT DEFAULT 'INTERNAL',
311
313
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
312
314
  FOREIGN KEY (audit_id) REFERENCES defence_audit(id) ON DELETE SET NULL
313
315
  );
314
316
  CREATE INDEX IF NOT EXISTS idx_session_events_session ON session_events(session_id, ts);
315
317
  CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(project, ts DESC);
318
+ CREATE INDEX IF NOT EXISTS idx_session_events_sensitivity ON session_events(sensitivity_level);
316
319
  CREATE UNIQUE INDEX IF NOT EXISTS idx_session_events_dedupe
317
320
  ON session_events(session_id, ts, kind, content_hash);
318
321
  `;
@@ -503,4 +503,29 @@ export function runMigrations(database) {
503
503
  logIfUnexpectedDdlError(err, 'session_events.content_hash column + dedupe index');
504
504
  // (importer-side INSERT OR IGNORE handles missing index gracefully)
505
505
  }
506
+ // Migration: session_events.sensitivity_level (v4.28 — Fix #10).
507
+ //
508
+ // Without this, the UserPromptSubmit hook captured the raw prompt verbatim
509
+ // (no pipeline, no credential scan, no sensitivity tag). The column lets
510
+ // the hook record the defence classifier's verdict alongside the redacted
511
+ // text so the dashboard's replay UI can mask/strip RESTRICTED rows.
512
+ // Defaults to 'INTERNAL' for backfilled rows + future callers that omit it.
513
+ try {
514
+ const sessionEventsTable = database
515
+ .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='session_events'")
516
+ .get();
517
+ if (sessionEventsTable) {
518
+ const sessionCols = database
519
+ .prepare("PRAGMA table_info(session_events)")
520
+ .all();
521
+ const sessionColNames = new Set(sessionCols.map((c) => c.name));
522
+ if (!sessionColNames.has('sensitivity_level')) {
523
+ database.exec("ALTER TABLE session_events ADD COLUMN sensitivity_level TEXT DEFAULT 'INTERNAL'");
524
+ }
525
+ database.exec('CREATE INDEX IF NOT EXISTS idx_session_events_sensitivity ON session_events(sensitivity_level)');
526
+ }
527
+ }
528
+ catch (err) {
529
+ logIfUnexpectedDdlError(err, 'session_events.sensitivity_level column + index');
530
+ }
506
531
  }
@@ -120,11 +120,16 @@ CREATE TABLE IF NOT EXISTS session_events (
120
120
  duration_ms INTEGER,
121
121
  audit_id INTEGER,
122
122
  content_hash TEXT,
123
+ -- v4.28 (Fix #10): defence classifier verdict for this event.
124
+ -- PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED. Lets the dashboard
125
+ -- replay UI mask or strip sensitive prompts/responses.
126
+ sensitivity_level TEXT DEFAULT 'INTERNAL',
123
127
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
124
128
  FOREIGN KEY (audit_id) REFERENCES defence_audit(id) ON DELETE SET NULL
125
129
  );
126
130
  CREATE INDEX IF NOT EXISTS idx_session_events_session ON session_events(session_id, ts);
127
131
  CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(project, ts DESC);
132
+ CREATE INDEX IF NOT EXISTS idx_session_events_sensitivity ON session_events(sensitivity_level);
128
133
  CREATE UNIQUE INDEX IF NOT EXISTS idx_session_events_dedupe
129
134
  ON session_events(session_id, ts, kind, content_hash);
130
135
 
@@ -41,3 +41,34 @@ export declare function resolveSource(declaredSource?: DefenceSource, strictMode
41
41
  inferred: boolean;
42
42
  detection?: EnvDetectionResult;
43
43
  };
44
+ export interface CeilingClampResult {
45
+ /** The effective source after clamping (declared if safe, env-inferred otherwise). */
46
+ source: DefenceSource;
47
+ /** True when the declared source claimed higher trust than the runtime environment justifies. */
48
+ clamped: boolean;
49
+ /** Trust score of the declared source (only meaningful when a declared source was passed). */
50
+ declaredScore: number | null;
51
+ /** Trust score the runtime environment actually permits. */
52
+ ceilingScore: number;
53
+ /** The environment-inferred source used as the trust ceiling. */
54
+ ceiling: DefenceSource;
55
+ /** Detection metadata for the environment inference. */
56
+ detection: EnvDetectionResult;
57
+ }
58
+ /**
59
+ * Clamp a caller-declared source against the environment-inferred trust ceiling.
60
+ *
61
+ * MCP callers are arbitrary processes — a prompt-injected agent could claim
62
+ * `{type:'user', identifier:'direct'}` to get trust=1.0 and bypass quarantine.
63
+ * To prevent that, we compute the highest trust the actual runtime allows
64
+ * (from env vars like CLAUDE_CODE_ENTRYPOINT) and refuse any declared source
65
+ * that would score higher.
66
+ *
67
+ * Semantics:
68
+ * - If no declared source: return env-inferred (no clamping).
69
+ * - If declaredScore <= ceilingScore: trust the declared source (allows
70
+ * legitimate downgrades, e.g. an agent labelling input as `email`).
71
+ * - If declaredScore > ceilingScore: drop the declared source and use the
72
+ * env-inferred one, with `clamped: true` so the caller can audit it.
73
+ */
74
+ export declare function clampSourceToCeiling(declaredSource: DefenceSource | undefined): CeilingClampResult;
@@ -8,6 +8,7 @@
8
8
  * This addresses Phase 1 limitation: "security is opt-in" — with env detection,
9
9
  * Claude Code agents get correct trust automatically with zero configuration.
10
10
  */
11
+ import { scoreSource } from './source-scorer.js';
11
12
  /**
12
13
  * Infer caller source from process environment variables.
13
14
  *
@@ -114,3 +115,52 @@ export function resolveSource(declaredSource, strictMode = false) {
114
115
  detection,
115
116
  };
116
117
  }
118
+ /**
119
+ * Clamp a caller-declared source against the environment-inferred trust ceiling.
120
+ *
121
+ * MCP callers are arbitrary processes — a prompt-injected agent could claim
122
+ * `{type:'user', identifier:'direct'}` to get trust=1.0 and bypass quarantine.
123
+ * To prevent that, we compute the highest trust the actual runtime allows
124
+ * (from env vars like CLAUDE_CODE_ENTRYPOINT) and refuse any declared source
125
+ * that would score higher.
126
+ *
127
+ * Semantics:
128
+ * - If no declared source: return env-inferred (no clamping).
129
+ * - If declaredScore <= ceilingScore: trust the declared source (allows
130
+ * legitimate downgrades, e.g. an agent labelling input as `email`).
131
+ * - If declaredScore > ceilingScore: drop the declared source and use the
132
+ * env-inferred one, with `clamped: true` so the caller can audit it.
133
+ */
134
+ export function clampSourceToCeiling(declaredSource) {
135
+ const detection = inferSourceFromEnvironment();
136
+ const ceilingScore = scoreSource(detection.source).score;
137
+ if (!declaredSource) {
138
+ return {
139
+ source: detection.source,
140
+ clamped: false,
141
+ declaredScore: null,
142
+ ceilingScore,
143
+ ceiling: detection.source,
144
+ detection,
145
+ };
146
+ }
147
+ const declaredScore = scoreSource(declaredSource).score;
148
+ if (declaredScore > ceilingScore) {
149
+ return {
150
+ source: detection.source,
151
+ clamped: true,
152
+ declaredScore,
153
+ ceilingScore,
154
+ ceiling: detection.source,
155
+ detection,
156
+ };
157
+ }
158
+ return {
159
+ source: declaredSource,
160
+ clamped: false,
161
+ declaredScore,
162
+ ceilingScore,
163
+ ceiling: detection.source,
164
+ detection,
165
+ };
166
+ }
@@ -2,7 +2,10 @@ export { scoreSource } from './source-scorer.js';
2
2
  export { filterByTrust } from './recall-filter.js';
3
3
  export { scoreAgent, getAgentDepth, buildAgentHierarchy } from './agent-scorer.js';
4
4
  export { checkAccess } from './access-control.js';
5
- export { inferSourceFromEnvironment, resolveSource } from './env-detector.js';
5
+ export { inferSourceFromEnvironment, resolveSource, clampSourceToCeiling } from './env-detector.js';
6
+ export type { CeilingClampResult } from './env-detector.js';
7
+ export { resolveToolSource } from './resolve-tool-source.js';
8
+ export type { ResolveToolSourceOptions } from './resolve-tool-source.js';
6
9
  export type { AccessPolicy, AccessCheckMemory } from './access-control.js';
7
10
  export type { AgentTrustConfig } from './agent-scorer.js';
8
11
  export type { EnvDetectionResult } from './env-detector.js';
@@ -2,4 +2,5 @@ export { scoreSource } from './source-scorer.js';
2
2
  export { filterByTrust } from './recall-filter.js';
3
3
  export { scoreAgent, getAgentDepth, buildAgentHierarchy } from './agent-scorer.js';
4
4
  export { checkAccess } from './access-control.js';
5
- export { inferSourceFromEnvironment, resolveSource } from './env-detector.js';
5
+ export { inferSourceFromEnvironment, resolveSource, clampSourceToCeiling } from './env-detector.js';
6
+ export { resolveToolSource } from './resolve-tool-source.js';
@@ -0,0 +1,27 @@
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 type { DefenceSource } from '../types.js';
14
+ export interface ResolveToolSourceOptions {
15
+ /** Tool name (e.g. 'remember', 'recall') — recorded in the audit reason. */
16
+ toolName: string;
17
+ /** Active project scope, recorded on the audit row. */
18
+ project: string | null;
19
+ }
20
+ /**
21
+ * Resolve the effective source for an MCP tool call.
22
+ *
23
+ * Returns the source the rest of the pipeline should use. When a caller
24
+ * over-claims trust the declared source is dropped, an audit row is written,
25
+ * and the env-inferred source is returned instead.
26
+ */
27
+ export declare function resolveToolSource(declaredSource: DefenceSource | undefined, options: ResolveToolSourceOptions): DefenceSource;