shieldcortex 4.38.0 → 4.39.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/admin.js +2 -0
- package/dist/api/routes/memories.js +5 -2
- package/dist/api/visualization-server.js +1 -0
- package/dist/database/inline-schema.js +6 -0
- package/dist/database/migrations.js +34 -0
- package/dist/database/schema.sql +6 -0
- package/dist/defence/audit/logger.js +4 -2
- package/dist/defence/audit/queries.js +4 -0
- package/dist/defence/audit/retention.js +22 -12
- package/dist/defence/iron-dome/audit.js +1 -0
- package/dist/defence/pipeline.js +4 -1
- package/dist/defence/tool-response-scanner.js +1 -0
- package/dist/defence/trust/resolve-tool-source.js +2 -0
- package/dist/defence/types.d.ts +10 -0
- package/dist/memory/lifecycle.js +5 -2
- package/dist/memory/store.d.ts +16 -2
- package/dist/memory/store.js +100 -6
- package/dist/tools/context.js +15 -1
- package/dist/tools/recall.js +9 -1
- package/package.json +1 -1
- /package/dashboard/.next/standalone/dashboard/.next/static/{PR51g0pS7Wp0zLzu2q6mQ → LfTY3B6uX3j7zNwqqgvPG}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{PR51g0pS7Wp0zLzu2q6mQ → LfTY3B6uX3j7zNwqqgvPG}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{PR51g0pS7Wp0zLzu2q6mQ → LfTY3B6uX3j7zNwqqgvPG}/_ssgManifest.js +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
2
|
-
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/d878b929b21636c4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57043,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n3:I[27657,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n4:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"ViewportBoundary\"]\n9:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"MetadataBoundary\"]\nb:I[30687,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"
|
|
1
|
+
<!DOCTYPE html><!--LfTY3B6uX3j7zNwqqgvPG--><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/d878b929b21636c4.js"/><script src="/_next/static/chunks/f70f563804550a9c.js" async=""></script><script src="/_next/static/chunks/43d761df92da7cb6.js" async=""></script><script src="/_next/static/chunks/e281719dbabcca1d.js" async=""></script><script src="/_next/static/chunks/9e56d1f8f4d7adcb.js" async=""></script><script src="/_next/static/chunks/turbopack-768a6a8b9db952e0.js" async=""></script><script src="/_next/static/chunks/102f894cc892994d.js" async=""></script><script src="/_next/static/chunks/417032eeb2cd875f.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
|
|
2
|
+
@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/d878b929b21636c4.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57043,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n3:I[27657,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n4:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n7:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"ViewportBoundary\"]\n9:I[56978,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"MetadataBoundary\"]\nb:I[30687,[\"/_next/static/chunks/102f894cc892994d.js\",\"/_next/static/chunks/417032eeb2cd875f.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"LfTY3B6uX3j7zNwqqgvPG\",\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"title\",null,{\"children\":\"500: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/102f894cc892994d.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/417032eeb2cd875f.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"6:null\na:[]\n"])</script></body></html>
|
package/dist/api/routes/admin.js
CHANGED
|
@@ -99,6 +99,8 @@ export function registerAdminRoutes(app, deps) {
|
|
|
99
99
|
options.source = req.query.source;
|
|
100
100
|
if (req.query.firewallResult)
|
|
101
101
|
options.firewallResult = req.query.firewallResult;
|
|
102
|
+
if (req.query.operation)
|
|
103
|
+
options.operation = req.query.operation;
|
|
102
104
|
if (req.query.limit)
|
|
103
105
|
options.limit = parseInt(req.query.limit, 10);
|
|
104
106
|
if (req.query.project)
|
|
@@ -587,7 +587,10 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
587
587
|
}), (req, res) => {
|
|
588
588
|
try {
|
|
589
589
|
const id = parseInt(req.params.id, 10);
|
|
590
|
-
|
|
590
|
+
// Attribute the dashboard delete so it lands on the provenance ledger
|
|
591
|
+
// (the primary human-initiated delete — the source-less exemption is only
|
|
592
|
+
// for internal consolidate/merge machinery).
|
|
593
|
+
const success = deleteMemory(id, { type: 'api', identifier: `dashboard:memory-delete:${id}` });
|
|
591
594
|
if (!success) {
|
|
592
595
|
return res.status(404).json({ error: 'Memory not found' });
|
|
593
596
|
}
|
|
@@ -1235,7 +1238,7 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
1235
1238
|
const db = getDatabase();
|
|
1236
1239
|
db.prepare(`INSERT INTO quarantine (original_title, original_content, source_type, source_identifier, reason, project, status, created_at)
|
|
1237
1240
|
VALUES (?, ?, ?, ?, ?, ?, 'pending', ?)`).run(memory.title, memory.content, 'dashboard', 'brain-control', req.body.reason || 'Manually quarantined from Brain dashboard', memory.project || null, new Date().toISOString());
|
|
1238
|
-
deleteMemory(id);
|
|
1241
|
+
deleteMemory(id, { type: 'api', identifier: `dashboard:quarantine-delete:${id}` });
|
|
1239
1242
|
res.json({ success: true, quarantined: id });
|
|
1240
1243
|
}
|
|
1241
1244
|
catch (error) {
|
|
@@ -36,6 +36,7 @@ export function getInlineSchema() {
|
|
|
36
36
|
trust_score REAL DEFAULT 1.0,
|
|
37
37
|
sensitivity_level TEXT DEFAULT 'INTERNAL',
|
|
38
38
|
source TEXT DEFAULT 'user:direct',
|
|
39
|
+
content_hash TEXT,
|
|
39
40
|
status TEXT DEFAULT 'active' CHECK(status IN ('active', 'archived', 'suppressed', 'canonical')),
|
|
40
41
|
pinned INTEGER DEFAULT 0,
|
|
41
42
|
reviewed_at TIMESTAMP,
|
|
@@ -84,6 +85,8 @@ export function getInlineSchema() {
|
|
|
84
85
|
CREATE INDEX IF NOT EXISTS idx_memories_decayed_score ON memories(decayed_score DESC);
|
|
85
86
|
CREATE INDEX IF NOT EXISTS idx_memories_last_accessed ON memories(last_accessed DESC);
|
|
86
87
|
CREATE INDEX IF NOT EXISTS idx_memories_updated ON memories(updated_at DESC);
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_memories_source ON memories(source);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash);
|
|
87
90
|
|
|
88
91
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
89
92
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -168,6 +171,8 @@ export function getInlineSchema() {
|
|
|
168
171
|
trust_score REAL NOT NULL,
|
|
169
172
|
sensitivity_level TEXT NOT NULL DEFAULT 'INTERNAL',
|
|
170
173
|
firewall_result TEXT NOT NULL CHECK(firewall_result IN ('ALLOW', 'BLOCK', 'QUARANTINE')),
|
|
174
|
+
operation TEXT,
|
|
175
|
+
content_hash TEXT,
|
|
171
176
|
anomaly_score REAL DEFAULT 0.0,
|
|
172
177
|
threat_indicators TEXT DEFAULT '[]',
|
|
173
178
|
blocked_patterns TEXT DEFAULT '[]',
|
|
@@ -182,6 +187,7 @@ export function getInlineSchema() {
|
|
|
182
187
|
CREATE INDEX IF NOT EXISTS idx_audit_result ON defence_audit(firewall_result);
|
|
183
188
|
CREATE INDEX IF NOT EXISTS idx_audit_source ON defence_audit(source_type);
|
|
184
189
|
CREATE INDEX IF NOT EXISTS idx_audit_project ON defence_audit(project);
|
|
190
|
+
CREATE INDEX IF NOT EXISTS idx_audit_operation ON defence_audit(operation);
|
|
185
191
|
|
|
186
192
|
-- Cumulative audit aggregate (single row, id=1) — retention rollup target.
|
|
187
193
|
-- See schema.sql for the rationale.
|
|
@@ -750,4 +750,38 @@ export function runMigrations(database) {
|
|
|
750
750
|
catch (err) {
|
|
751
751
|
logIfUnexpectedDdlError(err, 'mcp_tool_hashes');
|
|
752
752
|
}
|
|
753
|
+
// Migration: provenance ledger (v4.39.0) — add an `operation` discriminator
|
|
754
|
+
// (read/write/delete) and a `content_hash` (write-time tamper-evidence) to
|
|
755
|
+
// defence_audit, a `content_hash` to memories, and an index on memories.source
|
|
756
|
+
// for revoke-by-source. Existing rows keep operation/content_hash NULL (legacy,
|
|
757
|
+
// unclassifiable). Fresh installs get these from schema.sql / inline-schema.ts.
|
|
758
|
+
try {
|
|
759
|
+
const auditCols = database.prepare("PRAGMA table_info(defence_audit)").all();
|
|
760
|
+
if (auditCols.length > 0) {
|
|
761
|
+
const auditColNames = new Set(auditCols.map((c) => c.name));
|
|
762
|
+
if (!auditColNames.has('operation')) {
|
|
763
|
+
database.exec('ALTER TABLE defence_audit ADD COLUMN operation TEXT');
|
|
764
|
+
}
|
|
765
|
+
if (!auditColNames.has('content_hash')) {
|
|
766
|
+
database.exec('ALTER TABLE defence_audit ADD COLUMN content_hash TEXT');
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
catch (err) {
|
|
771
|
+
logIfUnexpectedDdlError(err, 'defence_audit provenance columns (operation, content_hash)');
|
|
772
|
+
}
|
|
773
|
+
if (!columnNames.has('content_hash')) {
|
|
774
|
+
database.exec('ALTER TABLE memories ADD COLUMN content_hash TEXT');
|
|
775
|
+
}
|
|
776
|
+
// Indexes in an unconditional, self-healing block: CREATE INDEX IF NOT EXISTS
|
|
777
|
+
// no-ops if the column already had its index, and back-fills it if the column
|
|
778
|
+
// exists without it (e.g. a column added by a prior partial run).
|
|
779
|
+
try {
|
|
780
|
+
database.exec('CREATE INDEX IF NOT EXISTS idx_audit_operation ON defence_audit(operation)');
|
|
781
|
+
database.exec('CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash)');
|
|
782
|
+
database.exec('CREATE INDEX IF NOT EXISTS idx_memories_source ON memories(source)');
|
|
783
|
+
}
|
|
784
|
+
catch (err) {
|
|
785
|
+
logIfUnexpectedDdlError(err, 'provenance ledger indexes (audit operation, memories content_hash/source)');
|
|
786
|
+
}
|
|
753
787
|
}
|
package/dist/database/schema.sql
CHANGED
|
@@ -24,6 +24,7 @@ CREATE TABLE IF NOT EXISTS memories (
|
|
|
24
24
|
trust_score REAL DEFAULT 1.0,
|
|
25
25
|
sensitivity_level TEXT DEFAULT 'INTERNAL',
|
|
26
26
|
source TEXT DEFAULT 'user:direct',
|
|
27
|
+
content_hash TEXT,
|
|
27
28
|
status TEXT DEFAULT 'active' CHECK(status IN ('active', 'archived', 'suppressed', 'canonical')),
|
|
28
29
|
pinned INTEGER DEFAULT 0,
|
|
29
30
|
reviewed_at TIMESTAMP,
|
|
@@ -85,6 +86,8 @@ CREATE INDEX IF NOT EXISTS idx_memories_updated ON memories(updated_at DESC);
|
|
|
85
86
|
CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
|
|
86
87
|
CREATE INDEX IF NOT EXISTS idx_memories_pinned ON memories(pinned DESC);
|
|
87
88
|
CREATE INDEX IF NOT EXISTS idx_memories_source_kind ON memories(source_kind);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS idx_memories_source ON memories(source);
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash);
|
|
88
91
|
|
|
89
92
|
-- Session tracking for consolidation
|
|
90
93
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
@@ -214,6 +217,8 @@ CREATE TABLE IF NOT EXISTS defence_audit (
|
|
|
214
217
|
trust_score REAL NOT NULL,
|
|
215
218
|
sensitivity_level TEXT NOT NULL DEFAULT 'INTERNAL',
|
|
216
219
|
firewall_result TEXT NOT NULL CHECK(firewall_result IN ('ALLOW', 'BLOCK', 'QUARANTINE')),
|
|
220
|
+
operation TEXT, -- provenance ledger: 'read' | 'write' | 'delete' (NULL on legacy rows)
|
|
221
|
+
content_hash TEXT, -- SHA-256 of content at write time (tamper-evidence)
|
|
217
222
|
anomaly_score REAL DEFAULT 0.0,
|
|
218
223
|
threat_indicators TEXT DEFAULT '[]', -- JSON array of ThreatIndicator strings
|
|
219
224
|
blocked_patterns TEXT DEFAULT '[]', -- JSON array of matched patterns
|
|
@@ -228,6 +233,7 @@ CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON defence_audit(timestamp DESC);
|
|
|
228
233
|
CREATE INDEX IF NOT EXISTS idx_audit_result ON defence_audit(firewall_result);
|
|
229
234
|
CREATE INDEX IF NOT EXISTS idx_audit_source ON defence_audit(source_type);
|
|
230
235
|
CREATE INDEX IF NOT EXISTS idx_audit_project ON defence_audit(project);
|
|
236
|
+
CREATE INDEX IF NOT EXISTS idx_audit_operation ON defence_audit(operation);
|
|
231
237
|
|
|
232
238
|
-- Defence: cumulative audit aggregate (single row, id=1). Retention purges roll
|
|
233
239
|
-- the to-be-deleted rows' lifetime-stat contributions into this row BEFORE
|
|
@@ -15,12 +15,12 @@ export function logAudit(entry) {
|
|
|
15
15
|
const stmt = db.prepare(`
|
|
16
16
|
INSERT INTO defence_audit (
|
|
17
17
|
memory_id, project, timestamp, source_type, source_identifier,
|
|
18
|
-
trust_score, sensitivity_level, firewall_result,
|
|
18
|
+
trust_score, sensitivity_level, firewall_result, operation, content_hash,
|
|
19
19
|
anomaly_score, threat_indicators, blocked_patterns,
|
|
20
20
|
reason, fragmentation_score, pipeline_duration_ms
|
|
21
21
|
) VALUES (
|
|
22
22
|
@memory_id, @project, @timestamp, @source_type, @source_identifier,
|
|
23
|
-
@trust_score, @sensitivity_level, @firewall_result,
|
|
23
|
+
@trust_score, @sensitivity_level, @firewall_result, @operation, @content_hash,
|
|
24
24
|
@anomaly_score, @threat_indicators, @blocked_patterns,
|
|
25
25
|
@reason, @fragmentation_score, @pipeline_duration_ms
|
|
26
26
|
)
|
|
@@ -34,6 +34,8 @@ export function logAudit(entry) {
|
|
|
34
34
|
trust_score: entry.trust_score,
|
|
35
35
|
sensitivity_level: entry.sensitivity_level,
|
|
36
36
|
firewall_result: entry.firewall_result,
|
|
37
|
+
operation: entry.operation ?? null,
|
|
38
|
+
content_hash: entry.content_hash ?? null,
|
|
37
39
|
anomaly_score: entry.anomaly_score ?? 0,
|
|
38
40
|
threat_indicators: entry.threat_indicators ?? '[]',
|
|
39
41
|
blocked_patterns: entry.blocked_patterns ?? '[]',
|
|
@@ -22,6 +22,10 @@ export function queryAuditLogs(options = {}) {
|
|
|
22
22
|
conditions.push('da.firewall_result = @firewallResult');
|
|
23
23
|
params.firewallResult = options.firewallResult;
|
|
24
24
|
}
|
|
25
|
+
if (options.operation) {
|
|
26
|
+
conditions.push('da.operation = @operation');
|
|
27
|
+
params.operation = options.operation;
|
|
28
|
+
}
|
|
25
29
|
if (options.source) {
|
|
26
30
|
conditions.push('da.source_type = @source');
|
|
27
31
|
params.source = options.source;
|
|
@@ -140,22 +140,32 @@ export function purgeAuditUnderSizePressure(options = {}) {
|
|
|
140
140
|
const total = db.prepare('SELECT COUNT(*) AS c FROM defence_audit').get().c;
|
|
141
141
|
if (total <= maxRows)
|
|
142
142
|
return 0;
|
|
143
|
-
|
|
144
|
-
// the
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
const over = total - maxRows;
|
|
144
|
+
// Forensic-aware eviction: trim the `over` oldest rows, but evict
|
|
145
|
+
// LOW-VALUE provenance rows first (ALLOW reads/deletes — the high-volume,
|
|
146
|
+
// low-forensic-value entries) and only fall back to threat rows
|
|
147
|
+
// (BLOCK/QUARANTINE, or anything with threat_indicators) once the low-value
|
|
148
|
+
// rows are exhausted. Otherwise a flood of routine reads would push the
|
|
149
|
+
// oldest injection/credential-leak records out from under the row cap.
|
|
150
|
+
const ids = db.prepare(`
|
|
151
|
+
SELECT id FROM defence_audit
|
|
152
|
+
ORDER BY
|
|
153
|
+
CASE WHEN firewall_result = 'ALLOW'
|
|
154
|
+
AND operation IN ('read', 'delete')
|
|
155
|
+
AND (threat_indicators IS NULL OR threat_indicators IN ('', '[]'))
|
|
156
|
+
THEN 0 ELSE 1 END ASC,
|
|
157
|
+
timestamp ASC
|
|
158
|
+
LIMIT ?
|
|
159
|
+
`).all(over).map((r) => r.id);
|
|
160
|
+
if (ids.length === 0)
|
|
151
161
|
return 0;
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
const delta = computeDelta(where,
|
|
162
|
+
const placeholders = ids.map(() => '?').join(',');
|
|
163
|
+
const where = `id IN (${placeholders})`;
|
|
164
|
+
const delta = computeDelta(where, ids);
|
|
155
165
|
if (delta.total_scans === 0)
|
|
156
166
|
return 0;
|
|
157
167
|
rollIntoAggregate(delta);
|
|
158
|
-
const res = db.prepare(`DELETE FROM defence_audit WHERE ${where}`).run(...
|
|
168
|
+
const res = db.prepare(`DELETE FROM defence_audit WHERE ${where}`).run(...ids);
|
|
159
169
|
return Number(res.changes ?? 0);
|
|
160
170
|
})();
|
|
161
171
|
}
|
|
@@ -19,6 +19,7 @@ export function logIronDomeAudit(event) {
|
|
|
19
19
|
trust_score: 0,
|
|
20
20
|
sensitivity_level: 'PUBLIC',
|
|
21
21
|
firewall_result: event.allowed ? 'ALLOW' : 'BLOCK',
|
|
22
|
+
operation: null, // iron-dome kill-switch / defence event, not a memory read/write/delete
|
|
22
23
|
anomaly_score: 0,
|
|
23
24
|
threat_indicators: '[]',
|
|
24
25
|
blocked_patterns: '[]',
|
package/dist/defence/pipeline.js
CHANGED
|
@@ -11,7 +11,7 @@ import { analyzeFirewall } from './firewall/index.js';
|
|
|
11
11
|
import { classifySensitivity } from './sensitivity/index.js';
|
|
12
12
|
import { analyzeFragmentation } from './fragmentation/index.js';
|
|
13
13
|
import { scanForCredentials } from './credential-leak/index.js';
|
|
14
|
-
import { logAudit } from './audit/index.js';
|
|
14
|
+
import { logAudit, createContentHash } from './audit/index.js';
|
|
15
15
|
import { persistEvent } from '../api/events.js';
|
|
16
16
|
import { syncToCloud } from '../cloud/sync.js';
|
|
17
17
|
import { syncQuarantineToCloud } from '../cloud/quarantine-sync.js';
|
|
@@ -202,6 +202,8 @@ export function runDefencePipeline(content, title, source, config, project) {
|
|
|
202
202
|
trust_score: trust.score,
|
|
203
203
|
sensitivity_level: sensitivity.level,
|
|
204
204
|
firewall_result: firewall.result,
|
|
205
|
+
operation: 'write',
|
|
206
|
+
content_hash: createContentHash(content),
|
|
205
207
|
anomaly_score: firewall.anomalyScore,
|
|
206
208
|
threat_indicators: JSON.stringify(firewall.threatIndicators),
|
|
207
209
|
blocked_patterns: JSON.stringify(firewall.blockedPatterns),
|
|
@@ -283,6 +285,7 @@ export function runDefencePipeline(content, title, source, config, project) {
|
|
|
283
285
|
trust_score: 0,
|
|
284
286
|
sensitivity_level: 'RESTRICTED',
|
|
285
287
|
firewall_result: 'BLOCK',
|
|
288
|
+
operation: 'write',
|
|
286
289
|
anomaly_score: 1.0,
|
|
287
290
|
threat_indicators: '["pipeline_error"]',
|
|
288
291
|
blocked_patterns: '[]',
|
|
@@ -250,6 +250,7 @@ export function scanToolResponse(toolName, content, mode) {
|
|
|
250
250
|
trust_score: 0.5,
|
|
251
251
|
sensitivity_level: (credentials.leaked || decodedCredentialLeak) ? 'CONFIDENTIAL' : 'PUBLIC',
|
|
252
252
|
firewall_result: firewallResult,
|
|
253
|
+
operation: 'read',
|
|
253
254
|
anomaly_score: anomalyScore,
|
|
254
255
|
threat_indicators: JSON.stringify(threatIndicators),
|
|
255
256
|
blocked_patterns: JSON.stringify(blockedPatterns),
|
|
@@ -33,6 +33,7 @@ export function resolveToolSource(declaredSource, options) {
|
|
|
33
33
|
trust_score: ceilingScore,
|
|
34
34
|
sensitivity_level: 'PUBLIC',
|
|
35
35
|
firewall_result: 'BLOCK',
|
|
36
|
+
operation: null, // source-resolution meta-event, not a memory read/write/delete
|
|
36
37
|
anomaly_score: 0,
|
|
37
38
|
threat_indicators: JSON.stringify(['privilege_escalation']),
|
|
38
39
|
blocked_patterns: '[]',
|
|
@@ -62,6 +63,7 @@ export function resolveToolSource(declaredSource, options) {
|
|
|
62
63
|
trust_score: 0,
|
|
63
64
|
sensitivity_level: 'PUBLIC',
|
|
64
65
|
firewall_result: 'ALLOW',
|
|
66
|
+
operation: null, // source-resolution meta-event, not a memory read/write/delete
|
|
65
67
|
anomaly_score: 0,
|
|
66
68
|
threat_indicators: '[]',
|
|
67
69
|
blocked_patterns: '[]',
|
package/dist/defence/types.d.ts
CHANGED
|
@@ -129,6 +129,8 @@ export interface QuarantineEntry {
|
|
|
129
129
|
expires_at: string | null;
|
|
130
130
|
audit_id: number | null;
|
|
131
131
|
}
|
|
132
|
+
/** Operation that produced an audit row (provenance ledger discriminator). */
|
|
133
|
+
export type AuditOperation = 'write' | 'read' | 'delete' | 'update';
|
|
132
134
|
export interface AuditEntry {
|
|
133
135
|
id: number;
|
|
134
136
|
memory_id: number | null;
|
|
@@ -139,6 +141,14 @@ export interface AuditEntry {
|
|
|
139
141
|
trust_score: number;
|
|
140
142
|
sensitivity_level: string;
|
|
141
143
|
firewall_result: FirewallResult;
|
|
144
|
+
/**
|
|
145
|
+
* The operation that produced this row. Required on every new emission so the
|
|
146
|
+
* ledger is queryable by read/write/delete; `null` only on legacy rows written
|
|
147
|
+
* before the provenance-ledger column existed.
|
|
148
|
+
*/
|
|
149
|
+
operation: AuditOperation | null;
|
|
150
|
+
/** SHA-256 of the content at write time (tamper-evidence); null for read/delete rows. */
|
|
151
|
+
content_hash?: string | null;
|
|
142
152
|
anomaly_score: number;
|
|
143
153
|
threat_indicators: string;
|
|
144
154
|
blocked_patterns: string;
|
package/dist/memory/lifecycle.js
CHANGED
|
@@ -27,6 +27,7 @@ import { jaccardSimilarity } from './similarity.js';
|
|
|
27
27
|
import { emitMemoryAccessed, emitMemoryUpdated, persistEvent, } from '../api/events.js';
|
|
28
28
|
import { createMemoryLink } from './links.js';
|
|
29
29
|
import { runDefencePipeline } from '../defence/index.js';
|
|
30
|
+
import { createContentHash } from '../defence/audit/logger.js';
|
|
30
31
|
// Enrichment text is recall-query / caller-derived (attacker-influenced); scan
|
|
31
32
|
// it before persisting. Trust doesn't matter here (the row keeps its own) — we
|
|
32
33
|
// only act on the firewall verdict, so a low-trust web source is fine.
|
|
@@ -207,13 +208,15 @@ export function enrichMemory(memoryId, newContext, contextType = 'access') {
|
|
|
207
208
|
if (defenceResult.firewall.result !== 'ALLOW') {
|
|
208
209
|
return { enriched: false, reason: `Enrichment blocked by defence: ${defenceResult.firewall.reason}` };
|
|
209
210
|
}
|
|
210
|
-
// Update memory
|
|
211
|
+
// Update memory (recompute content_hash — the integrity snapshot must track
|
|
212
|
+
// the enriched content, not the pre-enrichment original).
|
|
211
213
|
db.prepare(`
|
|
212
214
|
UPDATE memories
|
|
213
215
|
SET content = ?,
|
|
216
|
+
content_hash = ?,
|
|
214
217
|
last_accessed = CURRENT_TIMESTAMP
|
|
215
218
|
WHERE id = ?
|
|
216
|
-
`).run(newContent, memoryId);
|
|
219
|
+
`).run(newContent, createContentHash(newContent), memoryId);
|
|
217
220
|
// Update cooldown timestamp
|
|
218
221
|
enrichmentTimestamps.set(memoryId, now);
|
|
219
222
|
// Emit update event for dashboard
|
package/dist/memory/store.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Handles storage, retrieval, and management of memories.
|
|
6
6
|
*/
|
|
7
7
|
import { Memory, MemoryInput, MemoryType, MemoryConfig } from './types.js';
|
|
8
|
-
import type { DefenceSource } from '../defence/types.js';
|
|
8
|
+
import type { DefenceSource, AuditOperation } from '../defence/types.js';
|
|
9
9
|
export declare const MAX_CONTENT_SIZE: number;
|
|
10
10
|
export declare const UNATTRIBUTED_SOURCE: DefenceSource;
|
|
11
11
|
/**
|
|
@@ -20,7 +20,21 @@ export declare function getLastTruncationInfo(): {
|
|
|
20
20
|
* Convert database row to Memory object
|
|
21
21
|
*/
|
|
22
22
|
export declare function rowToMemory(row: Record<string, unknown>): Memory;
|
|
23
|
-
export declare function logAccessDenial(memoryId: number, source: DefenceSource, reason: string): void;
|
|
23
|
+
export declare function logAccessDenial(memoryId: number, source: DefenceSource, reason: string, operation?: AuditOperation): void;
|
|
24
|
+
/**
|
|
25
|
+
* Provenance ledger: record an ALLOWED read. Emitted ONCE per tool call (not per
|
|
26
|
+
* row) to keep the audit table bounded — recall returns up to 50 rows, so a
|
|
27
|
+
* per-row emit would flood it. memory_id carries the single id for single-target
|
|
28
|
+
* reads; the full id list (capped) goes in blocked_patterns for forensics.
|
|
29
|
+
*/
|
|
30
|
+
export declare function logAllowedRead(source: DefenceSource, tool: string, memoryIds: number[], project?: string | null): void;
|
|
31
|
+
/**
|
|
32
|
+
* Provenance ledger: record an ALLOWED delete (one row per deleted memory).
|
|
33
|
+
* memory_id is NULL by design — the row is emitted after the DELETE, and the
|
|
34
|
+
* audit.memory_id FK is ON DELETE SET NULL, so a live reference can't survive.
|
|
35
|
+
* The deleted id is preserved in `reason` + `blocked_patterns` for forensics.
|
|
36
|
+
*/
|
|
37
|
+
export declare function logAllowedDelete(memoryId: number, source: DefenceSource, project?: string | null): void;
|
|
24
38
|
/**
|
|
25
39
|
* Error thrown when memory creation is paused
|
|
26
40
|
*/
|
package/dist/memory/store.js
CHANGED
|
@@ -21,7 +21,7 @@ import { syncMemoryDeleteToCloud, syncMemoryUpsertToCloud } from '../cloud/memor
|
|
|
21
21
|
import { isFeatureEnabled } from '../license/gate.js';
|
|
22
22
|
import { checkAccess } from '../defence/trust/access-control.js';
|
|
23
23
|
import { scoreSource } from '../defence/trust/source-scorer.js';
|
|
24
|
-
import { logAudit } from '../defence/audit/logger.js';
|
|
24
|
+
import { logAudit, createContentHash } from '../defence/audit/logger.js';
|
|
25
25
|
import { dispatchWebhook } from '../events/webhooks.js';
|
|
26
26
|
import { safeJsonParse } from './fts.js';
|
|
27
27
|
// Internal use of the link API. links.ts also imports from store.ts (getMemoryById,
|
|
@@ -230,7 +230,7 @@ function checkRateLimit(source) {
|
|
|
230
230
|
// ── Read-Time Access Control ──
|
|
231
231
|
// Exported because search-recall.ts also calls logAccessDenial inside its
|
|
232
232
|
// post-search ACL filter (cycle artifact, not intended public API).
|
|
233
|
-
export function logAccessDenial(memoryId, source, reason) {
|
|
233
|
+
export function logAccessDenial(memoryId, source, reason, operation = 'read') {
|
|
234
234
|
const trust = scoreSource(source).score;
|
|
235
235
|
logAudit({
|
|
236
236
|
memory_id: memoryId,
|
|
@@ -241,6 +241,7 @@ export function logAccessDenial(memoryId, source, reason) {
|
|
|
241
241
|
trust_score: trust,
|
|
242
242
|
sensitivity_level: 'INTERNAL',
|
|
243
243
|
firewall_result: 'BLOCK',
|
|
244
|
+
operation,
|
|
244
245
|
anomaly_score: 0,
|
|
245
246
|
threat_indicators: '[]',
|
|
246
247
|
blocked_patterns: '[]',
|
|
@@ -249,6 +250,58 @@ export function logAccessDenial(memoryId, source, reason) {
|
|
|
249
250
|
pipeline_duration_ms: 0,
|
|
250
251
|
});
|
|
251
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Provenance ledger: record an ALLOWED read. Emitted ONCE per tool call (not per
|
|
255
|
+
* row) to keep the audit table bounded — recall returns up to 50 rows, so a
|
|
256
|
+
* per-row emit would flood it. memory_id carries the single id for single-target
|
|
257
|
+
* reads; the full id list (capped) goes in blocked_patterns for forensics.
|
|
258
|
+
*/
|
|
259
|
+
export function logAllowedRead(source, tool, memoryIds, project) {
|
|
260
|
+
if (memoryIds.length === 0)
|
|
261
|
+
return;
|
|
262
|
+
logAudit({
|
|
263
|
+
memory_id: memoryIds.length === 1 ? memoryIds[0] : null,
|
|
264
|
+
project: project ?? null,
|
|
265
|
+
timestamp: new Date().toISOString(),
|
|
266
|
+
source_type: source.type,
|
|
267
|
+
source_identifier: source.identifier,
|
|
268
|
+
trust_score: scoreSource(source).score,
|
|
269
|
+
sensitivity_level: 'INTERNAL',
|
|
270
|
+
firewall_result: 'ALLOW',
|
|
271
|
+
operation: 'read',
|
|
272
|
+
anomaly_score: 0,
|
|
273
|
+
threat_indicators: '[]',
|
|
274
|
+
blocked_patterns: JSON.stringify(memoryIds.slice(0, 50)),
|
|
275
|
+
reason: `read ${memoryIds.length} memor${memoryIds.length === 1 ? 'y' : 'ies'} via ${tool}`,
|
|
276
|
+
fragmentation_score: null,
|
|
277
|
+
pipeline_duration_ms: null,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Provenance ledger: record an ALLOWED delete (one row per deleted memory).
|
|
282
|
+
* memory_id is NULL by design — the row is emitted after the DELETE, and the
|
|
283
|
+
* audit.memory_id FK is ON DELETE SET NULL, so a live reference can't survive.
|
|
284
|
+
* The deleted id is preserved in `reason` + `blocked_patterns` for forensics.
|
|
285
|
+
*/
|
|
286
|
+
export function logAllowedDelete(memoryId, source, project) {
|
|
287
|
+
logAudit({
|
|
288
|
+
memory_id: null,
|
|
289
|
+
project: project ?? null,
|
|
290
|
+
timestamp: new Date().toISOString(),
|
|
291
|
+
source_type: source.type,
|
|
292
|
+
source_identifier: source.identifier,
|
|
293
|
+
trust_score: scoreSource(source).score,
|
|
294
|
+
sensitivity_level: 'INTERNAL',
|
|
295
|
+
firewall_result: 'ALLOW',
|
|
296
|
+
operation: 'delete',
|
|
297
|
+
anomaly_score: 0,
|
|
298
|
+
threat_indicators: '[]',
|
|
299
|
+
blocked_patterns: JSON.stringify([memoryId]),
|
|
300
|
+
reason: `deleted memory #${memoryId}`,
|
|
301
|
+
fragmentation_score: null,
|
|
302
|
+
pipeline_duration_ms: null,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
252
305
|
/**
|
|
253
306
|
* Filter raw DB rows by access control before converting to Memory objects.
|
|
254
307
|
* Returns only rows the source is allowed to read.
|
|
@@ -324,6 +377,7 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
|
|
|
324
377
|
trust_score: scoreSource(source).score,
|
|
325
378
|
sensitivity_level: 'INTERNAL',
|
|
326
379
|
firewall_result: 'BLOCK',
|
|
380
|
+
operation: 'write',
|
|
327
381
|
anomaly_score: 1.0,
|
|
328
382
|
threat_indicators: JSON.stringify(['rate_limit_exceeded']),
|
|
329
383
|
blocked_patterns: '[]',
|
|
@@ -413,8 +467,11 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
|
|
|
413
467
|
// defenceResult is always set now (every write is scanned), so always stamp
|
|
414
468
|
// the pipeline's real trust + sensitivity alongside the resolved source —
|
|
415
469
|
// no source-less branch can default to trust 1.0 / unscanned INTERNAL.
|
|
416
|
-
db.prepare(`UPDATE memories SET trust_score = ?, sensitivity_level = ?, source = ? WHERE id = ?`)
|
|
417
|
-
|
|
470
|
+
db.prepare(`UPDATE memories SET trust_score = ?, sensitivity_level = ?, source = ?, content_hash = ? WHERE id = ?`)
|
|
471
|
+
// content_hash = SHA-256 of the SUBMITTED content (a write-time provenance
|
|
472
|
+
// snapshot), matching the write-audit row in pipeline.ts. Consistent for
|
|
473
|
+
// >10KB memories too (where the STORED content is truncated).
|
|
474
|
+
.run(defenceResult.trust.score, defenceResult.sensitivity.level, sourceDetails.sourceValue, createContentHash(input.content), result.lastInsertRowid);
|
|
418
475
|
return result.lastInsertRowid;
|
|
419
476
|
})();
|
|
420
477
|
const memory = getMemoryById(insertedId);
|
|
@@ -701,6 +758,14 @@ export function updateMemory(id, updates) {
|
|
|
701
758
|
if (embeddedTextChanged) {
|
|
702
759
|
fields.push('embedding = NULL');
|
|
703
760
|
}
|
|
761
|
+
// STALENESS: content_hash is a write-time integrity snapshot. When content
|
|
762
|
+
// changes it must be recomputed in the SAME UPDATE — otherwise the stored hash
|
|
763
|
+
// refers to the old content and any tamper check false-positives on a
|
|
764
|
+
// legitimately-edited memory.
|
|
765
|
+
if (updates.content !== undefined) {
|
|
766
|
+
fields.push('content_hash = ?');
|
|
767
|
+
values.push(createContentHash(updates.content));
|
|
768
|
+
}
|
|
704
769
|
if (fields.length === 0)
|
|
705
770
|
return existing;
|
|
706
771
|
values.push(id);
|
|
@@ -721,6 +786,28 @@ export function updateMemory(id, updates) {
|
|
|
721
786
|
console.error('[shieldcortex] Entity extraction refresh failed:', e);
|
|
722
787
|
}
|
|
723
788
|
}
|
|
789
|
+
// Provenance ledger: a content/title change is an update-class mutation.
|
|
790
|
+
if (updates.content !== undefined || updates.title !== undefined) {
|
|
791
|
+
const changed = [updates.title !== undefined ? 'title' : null, updates.content !== undefined ? 'content' : null].filter(Boolean).join('+');
|
|
792
|
+
logAudit({
|
|
793
|
+
memory_id: id,
|
|
794
|
+
project: updatedMemory.project ?? null,
|
|
795
|
+
timestamp: new Date().toISOString(),
|
|
796
|
+
source_type: 'cli',
|
|
797
|
+
source_identifier: 'memory-update',
|
|
798
|
+
trust_score: updatedMemory.trustScore ?? 1,
|
|
799
|
+
sensitivity_level: updatedMemory.sensitivityLevel ?? 'INTERNAL',
|
|
800
|
+
firewall_result: 'ALLOW',
|
|
801
|
+
operation: 'update',
|
|
802
|
+
content_hash: updates.content !== undefined ? createContentHash(updates.content) : null,
|
|
803
|
+
anomaly_score: 0,
|
|
804
|
+
threat_indicators: '[]',
|
|
805
|
+
blocked_patterns: '[]',
|
|
806
|
+
reason: `updated memory #${id} (${changed})`,
|
|
807
|
+
fragmentation_score: null,
|
|
808
|
+
pipeline_duration_ms: null,
|
|
809
|
+
});
|
|
810
|
+
}
|
|
724
811
|
// Emit event for real-time dashboard (in-process)
|
|
725
812
|
emitMemoryUpdated(updatedMemory);
|
|
726
813
|
// Persist event for cross-process IPC (MCP → Dashboard)
|
|
@@ -804,6 +891,7 @@ export function mergeMemories(keptId, removedId, options, source = { type: 'cli'
|
|
|
804
891
|
db.prepare(`
|
|
805
892
|
UPDATE memories
|
|
806
893
|
SET content = ?,
|
|
894
|
+
content_hash = ?,
|
|
807
895
|
tags = ?,
|
|
808
896
|
salience = ?,
|
|
809
897
|
project = ?,
|
|
@@ -822,7 +910,7 @@ export function mergeMemories(keptId, removedId, options, source = { type: 'cli'
|
|
|
822
910
|
embedding = NULL,
|
|
823
911
|
updated_at = CURRENT_TIMESTAMP
|
|
824
912
|
WHERE id = ?
|
|
825
|
-
`).run(mergedContent, JSON.stringify(mergedTags), mergedSalience, mergedProject, JSON.stringify(mergedMetadata), mergedScope, mergedTransferable ? 1 : 0, mergedStatus, mergedPinned ? 1 : 0, mergedReviewedBy, new Date().toISOString(), mergedTrustScore, mergedSensitivity, mergedCloudExcluded ? 1 : 0, mergedAccessCount, mergedLastAccessed, kept.id);
|
|
913
|
+
`).run(mergedContent, createContentHash(mergedContent), JSON.stringify(mergedTags), mergedSalience, mergedProject, JSON.stringify(mergedMetadata), mergedScope, mergedTransferable ? 1 : 0, mergedStatus, mergedPinned ? 1 : 0, mergedReviewedBy, new Date().toISOString(), mergedTrustScore, mergedSensitivity, mergedCloudExcluded ? 1 : 0, mergedAccessCount, mergedLastAccessed, kept.id);
|
|
826
914
|
const updatedMemory = getMemoryById(kept.id);
|
|
827
915
|
try {
|
|
828
916
|
const extraction = extractFromMemory(updatedMemory.title, updatedMemory.content, updatedMemory.category);
|
|
@@ -856,7 +944,7 @@ export function deleteMemory(id, source) {
|
|
|
856
944
|
if (row) {
|
|
857
945
|
const policy = checkAccess({ id: row.id, source: row.source, sensitivity_level: row.sensitivity_level }, source, 'delete');
|
|
858
946
|
if (!policy.canDelete) {
|
|
859
|
-
logAccessDenial(id, source, policy.reason);
|
|
947
|
+
logAccessDenial(id, source, policy.reason, 'delete');
|
|
860
948
|
return false;
|
|
861
949
|
}
|
|
862
950
|
}
|
|
@@ -874,6 +962,12 @@ export function deleteMemory(id, source) {
|
|
|
874
962
|
const result = db.prepare('DELETE FROM memories WHERE id = ?').run(id);
|
|
875
963
|
// Emit event for real-time dashboard (in-process)
|
|
876
964
|
if (result.changes > 0 && memory) {
|
|
965
|
+
// Provenance ledger: record the allowed delete (one row per memory) when the
|
|
966
|
+
// caller is attributed. Internal source-less deletes (merge/consolidation)
|
|
967
|
+
// are machinery, not user actions, so they're not audited here.
|
|
968
|
+
if (source) {
|
|
969
|
+
logAllowedDelete(id, source, memory.project ?? null);
|
|
970
|
+
}
|
|
877
971
|
if (isFeatureEnabled('cloud_sync')) {
|
|
878
972
|
syncMemoryDeleteToCloud(memory);
|
|
879
973
|
syncGraphDeleteForMemoryToCloud(memory);
|