shieldcortex 4.35.0 → 4.37.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.
- package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dist/api/routes/memories.js +14 -1
- package/dist/cloud/cli.js +26 -1
- package/dist/defence/firewall/markdown-image-detector.d.ts +15 -0
- package/dist/defence/firewall/markdown-image-detector.js +30 -0
- package/dist/defence/quarantine/review.js +29 -7
- package/dist/defence/tool-response-enforce.d.ts +57 -0
- package/dist/defence/tool-response-enforce.js +107 -0
- package/dist/defence/tool-response-scanner.d.ts +6 -3
- package/dist/defence/tool-response-scanner.js +56 -6
- package/dist/defence/trust/recall-filter.js +6 -2
- package/dist/defence/trust/source-scorer.js +5 -0
- package/dist/defence/types.d.ts +9 -0
- package/dist/memory/consolidate.js +50 -18
- package/dist/memory/lifecycle.js +13 -0
- package/dist/memory/store.d.ts +1 -0
- package/dist/memory/store.js +73 -54
- package/dist/server.d.ts +6 -0
- package/dist/server.js +52 -2
- package/package.json +1 -1
- package/scripts/lib/recall-defence.mjs +254 -0
- package/scripts/lib/save-memory.mjs +12 -3
- package/scripts/prompt-recall-hook.mjs +33 -0
- package/scripts/session-start-hook.mjs +36 -4
- /package/dashboard/.next/standalone/dashboard/.next/static/{h2qG7AvaXDfMKQrI-bK4V → Xdk3QuQEKommHIbMSem56}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{h2qG7AvaXDfMKQrI-bK4V → Xdk3QuQEKommHIbMSem56}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{h2qG7AvaXDfMKQrI-bK4V → Xdk3QuQEKommHIbMSem56}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recall-boundary defence shim (Feature #1).
|
|
3
|
+
*
|
|
4
|
+
* The read hooks (prompt-recall, session-start) used to inject recalled memory
|
|
5
|
+
* VERBATIM into the model prompt with no defence. This module sits between the
|
|
6
|
+
* SQL SELECT and the formatter: it filters rows by trust/sensitivity (via the
|
|
7
|
+
* dead-no-more filterByTrust) and re-scans surviving content for injection /
|
|
8
|
+
* credentials / encoded payloads, withholding (not deleting) anything bad so a
|
|
9
|
+
* poisoned or RESTRICTED row never reaches the model.
|
|
10
|
+
*
|
|
11
|
+
* `defendRecallRows` is PURE + dependency-injected so it unit-tests with no dist
|
|
12
|
+
* build and no DB. `loadRecallDefence` / `emitRecallAudit` (below) wire the real
|
|
13
|
+
* dist modules for the hooks and are exercised by the integration test.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { dirname, resolve } from 'node:path';
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
18
|
+
|
|
19
|
+
const RESTRICTED_MARKER = '[REDACTED - RESTRICTED]';
|
|
20
|
+
|
|
21
|
+
let _recallDefenceCache = null;
|
|
22
|
+
let _recallDefenceCacheKey = null;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Lazy-load the built dist defence modules the read hooks need. Returns null if
|
|
26
|
+
* the dist build is missing/incomplete → the caller MUST fail OPEN (leave recall
|
|
27
|
+
* unchanged), because blanking recall in an un-built dev workspace would break
|
|
28
|
+
* the product. Imports only LEAF detector modules (never dist/defence/pipeline.js)
|
|
29
|
+
* to stay inside the hook's <500ms budget; caches across invocations.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} [distRootOverride] test seam — point at an empty dir to assert fail-open.
|
|
32
|
+
*/
|
|
33
|
+
export async function loadRecallDefence(distRootOverride) {
|
|
34
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
35
|
+
const distRoot = distRootOverride ?? resolve(here, '..', '..', 'dist');
|
|
36
|
+
if (_recallDefenceCache && _recallDefenceCacheKey === distRoot) return _recallDefenceCache;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const [trustMod, firewallMod, credMod, auditMod, initMod, sanitiseMod] = await Promise.all([
|
|
40
|
+
import(pathToFileURL(resolve(distRoot, 'defence', 'trust', 'recall-filter.js')).href),
|
|
41
|
+
import(pathToFileURL(resolve(distRoot, 'defence', 'firewall', 'index.js')).href),
|
|
42
|
+
import(pathToFileURL(resolve(distRoot, 'defence', 'credential-leak', 'index.js')).href),
|
|
43
|
+
import(pathToFileURL(resolve(distRoot, 'defence', 'audit', 'logger.js')).href),
|
|
44
|
+
import(pathToFileURL(resolve(distRoot, 'database', 'init.js')).href),
|
|
45
|
+
import(pathToFileURL(resolve(distRoot, 'defence', 'input-sanitisation', 'index.js')).href).catch(() => ({})),
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
typeof trustMod.filterByTrust !== 'function' ||
|
|
50
|
+
typeof firewallMod.detectInstructions !== 'function' ||
|
|
51
|
+
typeof firewallMod.detectEncoding !== 'function' ||
|
|
52
|
+
typeof credMod.scanForCredentials !== 'function' ||
|
|
53
|
+
typeof auditMod.logAudit !== 'function' ||
|
|
54
|
+
typeof initMod.initDatabase !== 'function'
|
|
55
|
+
) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_recallDefenceCache = {
|
|
60
|
+
filterByTrust: trustMod.filterByTrust,
|
|
61
|
+
// Optional — strips zero-width/RTL/control bytes before scanning so a
|
|
62
|
+
// hidden injection can't dodge the regex detectors; defendRecallRows guards.
|
|
63
|
+
sanitiseInput: sanitiseMod.sanitiseInput,
|
|
64
|
+
detectInstructions: firewallMod.detectInstructions,
|
|
65
|
+
detectEncoding: firewallMod.detectEncoding,
|
|
66
|
+
// Optional — older dist builds may not export it; defendRecallRows guards.
|
|
67
|
+
detectMarkdownImageExfil: firewallMod.detectMarkdownImageExfil,
|
|
68
|
+
scanForCredentials: credMod.scanForCredentials,
|
|
69
|
+
logAudit: auditMod.logAudit,
|
|
70
|
+
initDatabase: initMod.initDatabase,
|
|
71
|
+
isDatabaseInitialized: initMod.isDatabaseInitialized,
|
|
72
|
+
getDatabase: initMod.getDatabase,
|
|
73
|
+
closeDatabase: initMod.closeDatabase,
|
|
74
|
+
};
|
|
75
|
+
_recallDefenceCacheKey = distRoot;
|
|
76
|
+
return _recallDefenceCache;
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Point the dist DB singleton (used by logAudit) at the hook's DB so withhold
|
|
84
|
+
* audit rows are visible across connections. Only needed when ≥1 row is withheld
|
|
85
|
+
* — keep it out of the common all-clear path. Best-effort.
|
|
86
|
+
*/
|
|
87
|
+
export function ensureRecallAuditDb(defence, dbPath) {
|
|
88
|
+
if (!defence || !dbPath || dbPath === ':memory:') return;
|
|
89
|
+
try {
|
|
90
|
+
if (defence.isDatabaseInitialized && defence.isDatabaseInitialized()) {
|
|
91
|
+
const current = defence.getDatabase();
|
|
92
|
+
if (current && current.name === dbPath) return;
|
|
93
|
+
if (defence.closeDatabase) defence.closeDatabase();
|
|
94
|
+
}
|
|
95
|
+
defence.initDatabase(dbPath);
|
|
96
|
+
} catch {
|
|
97
|
+
// logAudit no-ops gracefully if the singleton isn't initialised.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Write a defence_audit row recording a withheld/redacted recall. Best-effort —
|
|
103
|
+
* never throws into the hook (a recall must not fail because audit failed).
|
|
104
|
+
*/
|
|
105
|
+
export function emitRecallAudit(logAudit, { memoryId, action, layer, reason, project } = {}) {
|
|
106
|
+
try {
|
|
107
|
+
logAudit({
|
|
108
|
+
memory_id: typeof memoryId === 'number' ? memoryId : null,
|
|
109
|
+
project: project ?? null,
|
|
110
|
+
timestamp: new Date().toISOString(),
|
|
111
|
+
source_type: 'hook',
|
|
112
|
+
source_identifier: 'recall-defence',
|
|
113
|
+
trust_score: 0,
|
|
114
|
+
sensitivity_level: 'INTERNAL',
|
|
115
|
+
// No 'READ' firewall result exists; encode the withhold as BLOCK (dropped)
|
|
116
|
+
// / QUARANTINE (redacted) with the detail in `reason`.
|
|
117
|
+
firewall_result: action === 'redacted' ? 'QUARANTINE' : 'BLOCK',
|
|
118
|
+
anomaly_score: 0,
|
|
119
|
+
threat_indicators: JSON.stringify([`recall:${layer ?? 'unknown'}`]),
|
|
120
|
+
blocked_patterns: '[]',
|
|
121
|
+
reason: `recall-withheld: ${reason ?? layer ?? 'policy'}`,
|
|
122
|
+
fragmentation_score: null,
|
|
123
|
+
pipeline_duration_ms: 0,
|
|
124
|
+
});
|
|
125
|
+
} catch {
|
|
126
|
+
// best-effort
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function parseMetadata(meta) {
|
|
131
|
+
if (meta == null) return {};
|
|
132
|
+
if (typeof meta === 'object') return meta;
|
|
133
|
+
if (typeof meta === 'string') {
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(meta);
|
|
136
|
+
} catch {
|
|
137
|
+
return {};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Filter recalled rows through the trust/sensitivity + content defence layers.
|
|
145
|
+
*
|
|
146
|
+
* @param {Array<object>} rows raw recalled rows (better-sqlite3 rows — NOT mutated)
|
|
147
|
+
* @param {{ minTrust?: number, project?: string, reviewedPinnedBypass?: boolean }} opts
|
|
148
|
+
* @param {{ filterByTrust, detectInstructions, scanForCredentials, detectEncoding }} deps
|
|
149
|
+
* @returns {{ kept: object[], actions: Array<{id:any, action:'allowed'|'dropped'|'redacted', layer:string|null, reason:string|null}> }}
|
|
150
|
+
*/
|
|
151
|
+
export function defendRecallRows(rows, opts = {}, deps) {
|
|
152
|
+
const minTrust = typeof opts.minTrust === 'number' ? opts.minTrust : 0;
|
|
153
|
+
const reviewedPinnedBypass = opts.reviewedPinnedBypass !== false; // default ON
|
|
154
|
+
const actions = [];
|
|
155
|
+
|
|
156
|
+
// Shallow copies — never mutate the better-sqlite3 rows (reused by the dedupe
|
|
157
|
+
// ring + telemetry). Coalesce undefined trust → 1.0 (column DEFAULT 1.0) so a
|
|
158
|
+
// legacy un-migrated row isn't dropped as trust 0 by filterByTrust.
|
|
159
|
+
const copies = rows.map((r) => ({
|
|
160
|
+
...r,
|
|
161
|
+
trust_score: r.trust_score ?? 1.0,
|
|
162
|
+
metadata: parseMetadata(r.metadata),
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
// Trust + sensitivity: drops quarantined/below-minTrust, redacts RESTRICTED.
|
|
166
|
+
const trusted = deps.filterByTrust(copies, minTrust, opts.project);
|
|
167
|
+
const trustedIds = new Set(trusted.map((r) => r.id));
|
|
168
|
+
for (const c of copies) {
|
|
169
|
+
if (!trustedIds.has(c.id)) {
|
|
170
|
+
actions.push({ id: c.id, action: 'dropped', layer: 'trust', reason: `trust<${minTrust} or quarantined` });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const kept = [];
|
|
175
|
+
for (const row of trusted) {
|
|
176
|
+
// Already redacted by the trust layer — keep the masked row, don't re-scan
|
|
177
|
+
// the marker.
|
|
178
|
+
if (row.content === RESTRICTED_MARKER) {
|
|
179
|
+
actions.push({ id: row.id, action: 'redacted', layer: 'restricted', reason: 'RESTRICTED content redacted on recall' });
|
|
180
|
+
kept.push(row);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Reviewed/pinned bypass: a human-reviewed or pinned memory skips the
|
|
185
|
+
// content detectors (trust/RESTRICTED above still applied) so a legitimately
|
|
186
|
+
// reviewed security note isn't re-suppressed at read time.
|
|
187
|
+
if (reviewedPinnedBypass && (row.reviewed_at != null || row.pinned)) {
|
|
188
|
+
actions.push({ id: row.id, action: 'allowed', layer: 'bypass', reason: 'reviewed/pinned — content scan skipped' });
|
|
189
|
+
kept.push(row);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const content = typeof row.content === 'string' ? row.content : '';
|
|
194
|
+
// Sanitise (strip zero-width / RTL / control bytes) BEFORE scanning — the
|
|
195
|
+
// write path does this, so an injection hidden behind zero-width chars
|
|
196
|
+
// otherwise dodges the read-path regex detectors. Scan the sanitised form;
|
|
197
|
+
// the original (benign zero-width is harmless) is what gets injected.
|
|
198
|
+
const scanContent = deps.sanitiseInput ? (deps.sanitiseInput(content)?.sanitised ?? content) : content;
|
|
199
|
+
|
|
200
|
+
const instr = deps.detectInstructions(scanContent);
|
|
201
|
+
if (instr && instr.detected) {
|
|
202
|
+
actions.push({ id: row.id, action: 'dropped', layer: 'instruction', reason: `instruction:${(instr.patterns ?? []).join(',')}` });
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Mirror the WRITE path: drop only on a BLOCKING credential finding, not a
|
|
207
|
+
// warned/logged one. A benign high-entropy hash / cache key is stored
|
|
208
|
+
// (write blocks only on action==='blocked'), so recall must not be stricter
|
|
209
|
+
// or it silently withholds legitimate notes.
|
|
210
|
+
const cred = deps.scanForCredentials(scanContent);
|
|
211
|
+
const credBlocked = !!cred && Array.isArray(cred.findings) && cred.findings.some((f) => f && f.action === 'blocked');
|
|
212
|
+
if (credBlocked) {
|
|
213
|
+
const blocked = cred.findings.filter((f) => f && f.action === 'blocked');
|
|
214
|
+
actions.push({ id: row.id, action: 'dropped', layer: 'credential', reason: `credential:${blocked.length}` });
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Decode-and-rescan: a bare encoding flag is NOT a drop (base64 hashes are
|
|
219
|
+
// common) — only drop if a DECODED snippet itself trips a detector.
|
|
220
|
+
const enc = deps.detectEncoding(scanContent);
|
|
221
|
+
if (enc && enc.detected) {
|
|
222
|
+
let malicious = false;
|
|
223
|
+
for (const snippet of enc.decodedSnippets ?? []) {
|
|
224
|
+
const di = deps.detectInstructions(snippet);
|
|
225
|
+
const dc = deps.scanForCredentials(snippet);
|
|
226
|
+
const dcBlocked = !!dc && Array.isArray(dc.findings) && dc.findings.some((f) => f && f.action === 'blocked');
|
|
227
|
+
if ((di && di.detected) || dcBlocked) {
|
|
228
|
+
malicious = true;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (malicious) {
|
|
233
|
+
actions.push({ id: row.id, action: 'dropped', layer: 'encoding', reason: `encoding-payload:${(enc.encodingTypes ?? []).join(',')}` });
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Markdown-image exfil: a stored  is a click-free
|
|
239
|
+
// data-leak shape the write firewall catches but the read path didn't.
|
|
240
|
+
// detectMarkdownImageExfil only flags data-bearing image URLs (low FP).
|
|
241
|
+
if (deps.detectMarkdownImageExfil) {
|
|
242
|
+
const mdImg = deps.detectMarkdownImageExfil(scanContent);
|
|
243
|
+
if (mdImg && mdImg.detected) {
|
|
244
|
+
actions.push({ id: row.id, action: 'dropped', layer: 'markdown-image-exfil', reason: `markdown-image-exfil:${(mdImg.urls ?? []).length}` });
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
actions.push({ id: row.id, action: 'allowed', layer: null, reason: null });
|
|
250
|
+
kept.push(row);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return { kept, actions };
|
|
254
|
+
}
|
|
@@ -76,7 +76,11 @@ export async function saveAutoExtractedMemory(db, memory, project, opts = {}) {
|
|
|
76
76
|
const decision = result.firewall.result;
|
|
77
77
|
|
|
78
78
|
if (decision === 'ALLOW') {
|
|
79
|
-
|
|
79
|
+
// Persist the COMPUTED trust + sensitivity from the scan — not the schema
|
|
80
|
+
// DEFAULT (trust 1.0 / INTERNAL). The INSERT used to omit these columns, so
|
|
81
|
+
// every hook-captured memory was over-trusted at 1.0, undercutting the
|
|
82
|
+
// recall shim's trust filter.
|
|
83
|
+
insertMemoryRow(db, memory, project, sourceIdentifier, result.trust?.score, result.sensitivity?.level);
|
|
80
84
|
return;
|
|
81
85
|
}
|
|
82
86
|
|
|
@@ -99,7 +103,7 @@ export async function saveAutoExtractedMemory(db, memory, project, opts = {}) {
|
|
|
99
103
|
|
|
100
104
|
// ==================== Internal: writes ====================
|
|
101
105
|
|
|
102
|
-
function insertMemoryRow(db, memory, project, sourceIdentifier) {
|
|
106
|
+
function insertMemoryRow(db, memory, project, sourceIdentifier, trustScore, sensitivityLevel) {
|
|
103
107
|
const timestamp = new Date().toISOString();
|
|
104
108
|
|
|
105
109
|
// Cross-call, CROSS-PATH exact-title dedup: the hook fires repeatedly (per
|
|
@@ -153,9 +157,10 @@ function insertMemoryRow(db, memory, project, sourceIdentifier) {
|
|
|
153
157
|
INSERT INTO memories (
|
|
154
158
|
uuid, title, content, type, category, salience, tags, project,
|
|
155
159
|
memory_purpose, source, source_kind, capture_method,
|
|
160
|
+
trust_score, sensitivity_level,
|
|
156
161
|
created_at, last_accessed
|
|
157
162
|
)
|
|
158
|
-
VALUES (?, ?, ?, 'short_term', ?, ?, ?, ?, ?, ?, 'hook', 'auto', ?, ?)
|
|
163
|
+
VALUES (?, ?, ?, 'short_term', ?, ?, ?, ?, ?, ?, 'hook', 'auto', ?, ?, ?, ?)
|
|
159
164
|
`).run(
|
|
160
165
|
randomUUID(),
|
|
161
166
|
memory.title,
|
|
@@ -166,6 +171,10 @@ function insertMemoryRow(db, memory, project, sourceIdentifier) {
|
|
|
166
171
|
project || null,
|
|
167
172
|
memory.memoryPurpose ?? 'project',
|
|
168
173
|
`hook:${sourceIdentifier}`,
|
|
174
|
+
// Computed by the scan above (hook source → 0.8). Fall back to the schema
|
|
175
|
+
// defaults only if the pipeline somehow returned no trust/sensitivity.
|
|
176
|
+
typeof trustScore === 'number' ? trustScore : 1.0,
|
|
177
|
+
sensitivityLevel ?? 'INTERNAL',
|
|
169
178
|
timestamp,
|
|
170
179
|
timestamp,
|
|
171
180
|
);
|
|
@@ -24,6 +24,7 @@ import { computeEffectiveSalience } from './lib/salience.mjs';
|
|
|
24
24
|
import { writeRecallLog } from './lib/recall-log.mjs';
|
|
25
25
|
import { recordHookInvocation } from './lib/telemetry.mjs';
|
|
26
26
|
import { filterByRelevance, extractQueryTerms } from './lib/recall-relevance.mjs';
|
|
27
|
+
import { defendRecallRows, loadRecallDefence, ensureRecallAuditDb, emitRecallAudit } from './lib/recall-defence.mjs';
|
|
27
28
|
|
|
28
29
|
// ==================== CONFIG ====================
|
|
29
30
|
|
|
@@ -135,6 +136,7 @@ function recallRelevant(db, project, prompt) {
|
|
|
135
136
|
SELECT
|
|
136
137
|
m.id, m.title, m.content, m.category, m.salience, fts.rank,
|
|
137
138
|
m.pinned, m.access_count, m.last_accessed,
|
|
139
|
+
m.trust_score, m.sensitivity_level, m.metadata, m.reviewed_at,
|
|
138
140
|
COALESCE(m.downvote_count, 0) AS downvote_count
|
|
139
141
|
FROM memories m
|
|
140
142
|
JOIN memories_fts fts ON m.id = fts.rowid
|
|
@@ -184,6 +186,7 @@ function recallRelevant(db, project, prompt) {
|
|
|
184
186
|
SELECT
|
|
185
187
|
id, title, content, category, salience,
|
|
186
188
|
pinned, access_count, last_accessed,
|
|
189
|
+
trust_score, sensitivity_level, metadata, reviewed_at,
|
|
187
190
|
COALESCE(downvote_count, 0) AS downvote_count
|
|
188
191
|
FROM memories
|
|
189
192
|
WHERE category = ?
|
|
@@ -517,6 +520,36 @@ process.stdin.on('end', async () => {
|
|
|
517
520
|
}
|
|
518
521
|
}
|
|
519
522
|
|
|
523
|
+
// ── RECALL-BOUNDARY DEFENCE (Feature #1) ─────────────────────────────
|
|
524
|
+
// Filter poisoned / RESTRICTED / credential-bearing rows OUT of the recalled
|
|
525
|
+
// set before they're formatted into the prompt. Runs after dedupe (acts on
|
|
526
|
+
// the final injected set) and before format + ring + telemetry (so those see
|
|
527
|
+
// only safe rows). FAIL-OPEN: a missing dist build leaves recall unchanged.
|
|
528
|
+
if (config.recallDefence !== false && memories.length > 0) {
|
|
529
|
+
try {
|
|
530
|
+
const defence = await loadRecallDefence();
|
|
531
|
+
if (defence) {
|
|
532
|
+
const minTrust = typeof config.recallDefenceMinTrust === 'number' ? config.recallDefenceMinTrust : 0;
|
|
533
|
+
const { kept: safe, actions } = defendRecallRows(memories, { minTrust, project }, defence);
|
|
534
|
+
const withheld = actions.filter((a) => a.action !== 'allowed');
|
|
535
|
+
if (withheld.length > 0) {
|
|
536
|
+
console.error(
|
|
537
|
+
`[shieldcortex] recall-defence withheld ${withheld.length} memory row(s): ` +
|
|
538
|
+
withheld.map((w) => `#${w.id}:${w.layer}`).join(', '),
|
|
539
|
+
);
|
|
540
|
+
// Only touch a writable audit connection when something was withheld.
|
|
541
|
+
ensureRecallAuditDb(defence, dbPath);
|
|
542
|
+
for (const a of withheld) {
|
|
543
|
+
emitRecallAudit(defence.logAudit, { memoryId: a.id, action: a.action, layer: a.layer, reason: a.reason, project });
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
memories = safe;
|
|
547
|
+
}
|
|
548
|
+
} catch (e) {
|
|
549
|
+
console.error('[shieldcortex] recall-defence skipped:', e?.message ?? e);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
520
553
|
const context = formatRecallContext(memories);
|
|
521
554
|
|
|
522
555
|
// Update the session ring with the hashes of what we just injected.
|
|
@@ -25,6 +25,7 @@ import { homedir } from 'os';
|
|
|
25
25
|
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
26
26
|
import { truncatePreservingWords } from './lib/truncate.mjs';
|
|
27
27
|
import { orderByEffectiveSalience } from './lib/session-context.mjs';
|
|
28
|
+
import { defendRecallRows, loadRecallDefence, ensureRecallAuditDb, emitRecallAudit } from './lib/recall-defence.mjs';
|
|
28
29
|
|
|
29
30
|
const NEW_DB_DIR = join(homedir(), '.shieldcortex');
|
|
30
31
|
const LEGACY_DB_DIR = join(homedir(), '.claude-cortex');
|
|
@@ -94,7 +95,8 @@ function getProjectContext(db, project) {
|
|
|
94
95
|
// computeEffectiveSalience.
|
|
95
96
|
const candidates = db.prepare(`
|
|
96
97
|
SELECT id, title, content, category, type, salience, tags, created_at,
|
|
97
|
-
pinned, access_count, last_accessed,
|
|
98
|
+
pinned, access_count, last_accessed, trust_score, sensitivity_level, metadata, reviewed_at,
|
|
99
|
+
COALESCE(downvote_count, 0) AS downvote_count
|
|
98
100
|
FROM memories
|
|
99
101
|
WHERE (project = ? OR project IS NULL)
|
|
100
102
|
AND salience >= ?
|
|
@@ -111,7 +113,8 @@ function getProjectContext(db, project) {
|
|
|
111
113
|
const excludeIds = memories.map(m => m.id);
|
|
112
114
|
const placeholders = excludeIds.length > 0 ? excludeIds.map(() => '?').join(',') : '0';
|
|
113
115
|
const recent = db.prepare(`
|
|
114
|
-
SELECT id, title, content, category, type, salience, tags, created_at
|
|
116
|
+
SELECT id, title, content, category, type, salience, tags, created_at,
|
|
117
|
+
pinned, trust_score, sensitivity_level, metadata, reviewed_at
|
|
115
118
|
FROM memories
|
|
116
119
|
WHERE (project = ? OR project IS NULL)
|
|
117
120
|
AND id NOT IN (${placeholders})
|
|
@@ -208,7 +211,7 @@ process.stdin.on('readable', () => {
|
|
|
208
211
|
}
|
|
209
212
|
});
|
|
210
213
|
|
|
211
|
-
process.stdin.on('end', () => {
|
|
214
|
+
process.stdin.on('end', async () => {
|
|
212
215
|
try {
|
|
213
216
|
const hookData = JSON.parse(input || '{}');
|
|
214
217
|
const source = typeof hookData.source === 'string' ? hookData.source : 'startup';
|
|
@@ -239,8 +242,37 @@ process.stdin.on('end', () => {
|
|
|
239
242
|
} else {
|
|
240
243
|
const db = new Database(DB_PATH, { readonly: true, timeout: 5000 });
|
|
241
244
|
memories = getProjectContext(db, project);
|
|
242
|
-
context = formatContext(memories, project);
|
|
243
245
|
db.close();
|
|
246
|
+
|
|
247
|
+
// ── RECALL-BOUNDARY DEFENCE (Feature #1) ───────────────────────────
|
|
248
|
+
// Same shim as prompt-recall: drop poisoned / RESTRICTED / credential
|
|
249
|
+
// rows from the session preamble before they're formatted. FAIL-OPEN if
|
|
250
|
+
// the dist build is missing (recall preamble unchanged).
|
|
251
|
+
if (config.recallDefence !== false && memories.length > 0) {
|
|
252
|
+
try {
|
|
253
|
+
const defence = await loadRecallDefence();
|
|
254
|
+
if (defence) {
|
|
255
|
+
const minTrust = typeof config.recallDefenceMinTrust === 'number' ? config.recallDefenceMinTrust : 0;
|
|
256
|
+
const { kept: safe, actions } = defendRecallRows(memories, { minTrust, project }, defence);
|
|
257
|
+
const withheld = actions.filter((a) => a.action !== 'allowed');
|
|
258
|
+
if (withheld.length > 0) {
|
|
259
|
+
console.error(
|
|
260
|
+
`[shieldcortex] recall-defence (session-start) withheld ${withheld.length} memory row(s): ` +
|
|
261
|
+
withheld.map((w) => `#${w.id}:${w.layer}`).join(', '),
|
|
262
|
+
);
|
|
263
|
+
ensureRecallAuditDb(defence, DB_PATH);
|
|
264
|
+
for (const a of withheld) {
|
|
265
|
+
emitRecallAudit(defence.logAudit, { memoryId: a.id, action: a.action, layer: a.layer, reason: a.reason, project });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
memories = safe;
|
|
269
|
+
}
|
|
270
|
+
} catch (e) {
|
|
271
|
+
console.error('[shieldcortex] recall-defence skipped:', e?.message ?? e);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
context = formatContext(memories, project);
|
|
244
276
|
}
|
|
245
277
|
|
|
246
278
|
if (context) {
|
|
File without changes
|
|
File without changes
|