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