shieldcortex 4.31.2 → 4.32.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/README.md +78 -2
- 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/prerender-manifest.json +3 -3
- 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/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
- package/dist/api/control.d.ts +2 -0
- package/dist/api/control.js +119 -2
- package/dist/api/routes/memories.js +19 -14
- package/dist/api/routes/system.js +2 -3
- package/dist/api/visualization-server.d.ts +13 -1
- package/dist/api/visualization-server.js +57 -1
- package/dist/audit/env-scanner.js +5 -2
- package/dist/audit/index.d.ts +4 -1
- package/dist/audit/index.js +2 -1
- package/dist/audit/mcp-config-scanner.d.ts +23 -0
- package/dist/audit/mcp-config-scanner.js +110 -0
- package/dist/audit/mcp-tools-scanner.d.ts +112 -0
- package/dist/audit/mcp-tools-scanner.js +299 -0
- package/dist/cli/audit.d.ts +1 -0
- package/dist/cli/audit.js +12 -1
- package/dist/cli/mcp.d.ts +13 -0
- package/dist/cli/mcp.js +0 -0
- package/dist/cli/remember.d.ts +75 -0
- package/dist/cli/remember.js +195 -0
- package/dist/cloud/config.d.ts +23 -1
- package/dist/cloud/config.js +453 -193
- package/dist/cloud/quarantine-sync.d.ts +12 -2
- package/dist/cloud/quarantine-sync.js +28 -6
- package/dist/cloud/sync-queue.d.ts +21 -2
- package/dist/cloud/sync-queue.js +124 -29
- package/dist/database/better-sqlite3-guard.d.ts +21 -2
- package/dist/database/better-sqlite3-guard.js +29 -5
- package/dist/database/init.js +68 -16
- package/dist/database/inline-schema.js +35 -1
- package/dist/database/migrations.js +104 -8
- package/dist/database/schema.sql +39 -1
- package/dist/defence/audit/queries.d.ts +10 -2
- package/dist/defence/audit/queries.js +30 -4
- package/dist/defence/audit/retention.d.ts +50 -0
- package/dist/defence/audit/retention.js +161 -0
- package/dist/defence/credential-leak/entropy.d.ts +11 -0
- package/dist/defence/credential-leak/entropy.js +27 -0
- package/dist/defence/credential-leak/index.js +27 -1
- package/dist/defence/credential-leak/patterns.d.ts +9 -0
- package/dist/defence/credential-leak/patterns.js +21 -0
- package/dist/defence/custom-patterns/store.js +8 -1
- package/dist/defence/custom-rules/store.d.ts +18 -0
- package/dist/defence/custom-rules/store.js +63 -0
- package/dist/defence/firewall/confusables.d.ts +30 -0
- package/dist/defence/firewall/confusables.js +87 -0
- package/dist/defence/firewall/encoding-detector.js +23 -9
- package/dist/defence/firewall/index.d.ts +11 -1
- package/dist/defence/firewall/index.js +34 -1
- package/dist/defence/firewall/instruction-detector.js +18 -7
- package/dist/defence/firewall/markdown-image-detector.d.ts +34 -0
- package/dist/defence/firewall/markdown-image-detector.js +83 -0
- package/dist/defence/fragmentation/entity-extractor.js +17 -6
- package/dist/defence/index.d.ts +5 -0
- package/dist/defence/index.js +8 -0
- package/dist/defence/iron-dome/index.js +7 -1
- package/dist/defence/pipeline.js +62 -10
- package/dist/defence/scan-windows.d.ts +41 -0
- package/dist/defence/scan-windows.js +61 -0
- package/dist/defence/semantic/attack-corpus.d.ts +22 -0
- package/dist/defence/semantic/attack-corpus.js +75 -0
- package/dist/defence/semantic/index.d.ts +67 -0
- package/dist/defence/semantic/index.js +138 -0
- package/dist/defence/skill-scanner/deep-scan.js +35 -15
- package/dist/defence/skill-scanner/patterns.d.ts +1 -1
- package/dist/defence/skill-scanner/patterns.js +8 -7
- package/dist/defence/tool-response-scanner.d.ts +21 -5
- package/dist/defence/tool-response-scanner.js +111 -22
- package/dist/defence/types.d.ts +11 -1
- package/dist/index.d.ts +29 -0
- package/dist/index.js +104 -20
- package/dist/memory/consolidate.js +1 -1
- package/dist/memory/decay.js +3 -1
- package/dist/memory/embedding.d.ts +18 -2
- package/dist/memory/embedding.js +32 -11
- package/dist/memory/expiry.js +1 -1
- package/dist/memory/search-recall.js +107 -49
- package/dist/memory/search.d.ts +19 -3
- package/dist/memory/search.js +25 -10
- package/dist/memory/store.d.ts +13 -2
- package/dist/memory/store.js +115 -11
- package/dist/scan-only.d.ts +64 -0
- package/dist/scan-only.js +173 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +6 -4
- package/dist/setup/claude-md.js +39 -34
- package/dist/setup/codex.js +9 -2
- package/dist/setup/copilot.js +160 -47
- package/dist/setup/json-config.d.ts +99 -0
- package/dist/setup/json-config.js +167 -0
- package/dist/setup/migrate.js +1 -1
- package/dist/setup/settings-hooks.js +8 -13
- package/dist/setup/uninstall.js +1 -21
- package/dist/tools/context.d.ts +8 -8
- package/dist/tools/forget.d.ts +9 -8
- package/dist/tools/forget.js +17 -4
- package/dist/tools/recall.d.ts +13 -13
- package/dist/tools/remember.d.ts +16 -16
- package/dist/tools/remember.js +19 -8
- package/dist/worker/brain-worker.d.ts +1 -0
- package/dist/worker/brain-worker.js +79 -16
- package/dist/worker/types.d.ts +8 -0
- package/dist/worker/types.js +8 -0
- package/dist/xray/dir-scanner.d.ts +18 -0
- package/dist/xray/dir-scanner.js +23 -1
- package/dist/xray/file-scanner.js +16 -1
- package/dist/xray/findings-store.js +9 -1
- package/dist/xray/index.d.ts +2 -0
- package/dist/xray/index.js +10 -1
- package/dist/xray/npm-inspector.d.ts +31 -0
- package/dist/xray/npm-inspector.js +135 -29
- package/dist/xray/patterns.d.ts +1 -1
- package/dist/xray/patterns.js +20 -23
- package/dist/xray/sarif.d.ts +78 -0
- package/dist/xray/sarif.js +166 -0
- package/dist/xray/watch.d.ts +1 -0
- package/dist/xray/watch.js +10 -1
- package/hooks/openclaw/cortex-memory/handler.ts +122 -18
- package/hooks/openclaw/cortex-memory/runtime.mjs +10 -4
- package/package.json +10 -3
- package/dist/memory/embedding-cache.d.ts +0 -20
- package/dist/memory/embedding-cache.js +0 -91
- /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{_j4TeMpss-w79QtNNWqZw → Ox9scglBehbbCk7DD8-Vn}/_ssgManifest.js +0 -0
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* Fire-and-forget: sends quarantined content to ShieldCortex cloud.
|
|
3
3
|
* Never blocks, never throws. Failed requests are logged and queued for retry.
|
|
4
4
|
*
|
|
5
|
-
* IMPORTANT:
|
|
6
|
-
*
|
|
5
|
+
* IMPORTANT: Quarantine holds the most sensitive payloads, so it applies the
|
|
6
|
+
* SAME CloudSyncControls gating as memory-sync (see shouldSyncRecord /
|
|
7
|
+
* applyContentMode in memory-sync.ts) BEFORE any content leaves the device:
|
|
8
|
+
* - project filter (`shouldSyncProject`) — excluded projects never sync
|
|
9
|
+
* - `excludeSensitive` — CONFIDENTIAL+ items are dropped entirely
|
|
10
|
+
* - `contentMode: 'metadata'` — content/title are redacted to a placeholder
|
|
11
|
+
* On top of that, credentials/secrets are always redacted with
|
|
12
|
+
* [REDACTED-{type}] placeholders to prevent secret leakage.
|
|
7
13
|
*/
|
|
8
14
|
export declare function syncQuarantineToCloud(entry: {
|
|
9
15
|
original_content: string;
|
|
@@ -14,4 +20,8 @@ export declare function syncQuarantineToCloud(entry: {
|
|
|
14
20
|
threat_indicators: string[];
|
|
15
21
|
anomaly_score: number;
|
|
16
22
|
firewall_result: string;
|
|
23
|
+
/** Project the quarantined write belongs to (for the project filter). */
|
|
24
|
+
project?: string | null;
|
|
25
|
+
/** Sensitivity classification of the content (for `excludeSensitive`). */
|
|
26
|
+
sensitivity_level?: string | null;
|
|
17
27
|
}): void;
|
|
@@ -1,22 +1,44 @@
|
|
|
1
|
-
import { getCloudConfig, getDeviceId, getDeviceName } from './config.js';
|
|
1
|
+
import { getCloudConfig, getCloudSyncControls, getDeviceId, getDeviceName, isSensitiveLevel, shouldSyncProject, } from './config.js';
|
|
2
2
|
import { enqueueFailedQuarantineSync } from './sync-queue.js';
|
|
3
3
|
import { redactCredentials } from '../defence/credential-leak/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Fire-and-forget: sends quarantined content to ShieldCortex cloud.
|
|
6
6
|
* Never blocks, never throws. Failed requests are logged and queued for retry.
|
|
7
7
|
*
|
|
8
|
-
* IMPORTANT:
|
|
9
|
-
*
|
|
8
|
+
* IMPORTANT: Quarantine holds the most sensitive payloads, so it applies the
|
|
9
|
+
* SAME CloudSyncControls gating as memory-sync (see shouldSyncRecord /
|
|
10
|
+
* applyContentMode in memory-sync.ts) BEFORE any content leaves the device:
|
|
11
|
+
* - project filter (`shouldSyncProject`) — excluded projects never sync
|
|
12
|
+
* - `excludeSensitive` — CONFIDENTIAL+ items are dropped entirely
|
|
13
|
+
* - `contentMode: 'metadata'` — content/title are redacted to a placeholder
|
|
14
|
+
* On top of that, credentials/secrets are always redacted with
|
|
15
|
+
* [REDACTED-{type}] placeholders to prevent secret leakage.
|
|
10
16
|
*/
|
|
11
17
|
export function syncQuarantineToCloud(entry) {
|
|
12
18
|
const config = getCloudConfig();
|
|
13
19
|
if (!config.cloudEnabled || !config.cloudApiKey)
|
|
14
20
|
return;
|
|
21
|
+
// Apply the user's CloudSyncControls (parity with memory-sync).
|
|
22
|
+
const controls = getCloudSyncControls();
|
|
23
|
+
if (!shouldSyncProject(entry.project ?? null, controls))
|
|
24
|
+
return;
|
|
25
|
+
if (controls.excludeSensitive && isSensitiveLevel(entry.sensitivity_level ?? null))
|
|
26
|
+
return;
|
|
27
|
+
const metadataOnly = controls.contentMode === 'metadata';
|
|
28
|
+
// Always redact credentials; metadata-only mode replaces content entirely.
|
|
29
|
+
const safeContent = metadataOnly
|
|
30
|
+
? '[ShieldCortex] Quarantine content redacted by local sync policy.'
|
|
31
|
+
: redactCredentials(entry.original_content);
|
|
32
|
+
const safeTitle = metadataOnly
|
|
33
|
+
? '[Metadata only]'
|
|
34
|
+
: entry.original_title
|
|
35
|
+
? redactCredentials(entry.original_title)
|
|
36
|
+
: entry.original_title;
|
|
15
37
|
const payload = {
|
|
16
38
|
...entry,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
39
|
+
original_content: safeContent,
|
|
40
|
+
original_title: safeTitle,
|
|
41
|
+
content_redacted: metadataOnly,
|
|
20
42
|
device_id: getDeviceId(),
|
|
21
43
|
device_name: getDeviceName(),
|
|
22
44
|
timestamp: new Date().toISOString(),
|
|
@@ -31,6 +31,9 @@ export interface QuarantineSyncEntry {
|
|
|
31
31
|
threat_indicators: string[];
|
|
32
32
|
anomaly_score: number;
|
|
33
33
|
firewall_result: string;
|
|
34
|
+
project?: string | null;
|
|
35
|
+
sensitivity_level?: string | null;
|
|
36
|
+
content_redacted?: boolean;
|
|
34
37
|
device_id: string;
|
|
35
38
|
device_name: string;
|
|
36
39
|
timestamp: string;
|
|
@@ -79,12 +82,28 @@ export declare function enqueueFailedGraphSync(entry: GraphSyncEnvelope): void;
|
|
|
79
82
|
* number of rows dropped. Best-effort and never throws.
|
|
80
83
|
*/
|
|
81
84
|
export declare function enforceQueueCap(maxRows?: number): number;
|
|
85
|
+
export interface ProcessRetryOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Maximum number of pending rows to attempt in one call. Bounds the network
|
|
88
|
+
* work an MCP-profile worker does per light tick (it passes a small budget,
|
|
89
|
+
* e.g. 25); the full dashboard profile uses the default. Resurrection is
|
|
90
|
+
* unaffected — only the pending-row SELECT is limited.
|
|
91
|
+
*/
|
|
92
|
+
maxRows?: number;
|
|
93
|
+
}
|
|
82
94
|
/**
|
|
83
95
|
* Process pending items in the retry queue.
|
|
84
|
-
*
|
|
96
|
+
*
|
|
97
|
+
* Runs a resurrection pass first (revive transiently-failed rows within TTL),
|
|
98
|
+
* then SELECTs pending rows due for retry (up to `maxRows`) and attempts each.
|
|
85
99
|
* Awaits each fetch so results are accurate and no double-processing occurs.
|
|
100
|
+
*
|
|
101
|
+
* Failure handling:
|
|
102
|
+
* - HTTP 4xx (≠429) → permanent: mark failed, no further retries.
|
|
103
|
+
* - network/timeout/5xx/429 → transient: keep pending with capped (≤1h)
|
|
104
|
+
* backoff, retrying until the 7-day TTL purge — survives long outages.
|
|
86
105
|
*/
|
|
87
|
-
export declare function processRetryQueue(): Promise<SyncQueueResult>;
|
|
106
|
+
export declare function processRetryQueue(options?: ProcessRetryOptions): Promise<SyncQueueResult>;
|
|
88
107
|
/**
|
|
89
108
|
* Get queue statistics by status.
|
|
90
109
|
*/
|
package/dist/cloud/sync-queue.js
CHANGED
|
@@ -159,26 +159,102 @@ function buildRetryRequest(payloadText) {
|
|
|
159
159
|
}
|
|
160
160
|
throw new Error('Unsupported sync queue payload');
|
|
161
161
|
}
|
|
162
|
+
/** Cap on transient backoff. A single offline laptop shouldn't wait more than
|
|
163
|
+
* an hour between retry attempts, but we don't want 2^attempts*30s to grow
|
|
164
|
+
* unbounded after a long outage (it hits days within ~14 attempts). */
|
|
165
|
+
const MAX_BACKOFF_MS = 60 * 60 * 1000; // 1h
|
|
166
|
+
const BASE_BACKOFF_MS = 30_000;
|
|
162
167
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
168
|
+
* Classify a sync failure to decide retry policy.
|
|
169
|
+
*
|
|
170
|
+
* - 'permanent': HTTP 4xx. The request is malformed, unauthorised, or points
|
|
171
|
+
* at something that doesn't exist — retrying is pointless, so fail fast.
|
|
172
|
+
* - 'transient': network errors, timeouts/AbortError, HTTP 5xx, HTTP 429.
|
|
173
|
+
* The server or link is temporarily unavailable; retrying always makes
|
|
174
|
+
* sense, so we keep the row pending (capped backoff) until the 7-day TTL
|
|
175
|
+
* purge removes it.
|
|
176
|
+
*
|
|
177
|
+
* 429 (rate limited) is deliberately transient — backing off and retrying is
|
|
178
|
+
* exactly the right response to a rate limit.
|
|
179
|
+
*/
|
|
180
|
+
function classifyHttpStatus(status) {
|
|
181
|
+
// 4xx (except 429) is a client error → permanent. 429 + 5xx → transient.
|
|
182
|
+
if (status === 429)
|
|
183
|
+
return 'transient';
|
|
184
|
+
if (status >= 400 && status < 500)
|
|
185
|
+
return 'permanent';
|
|
186
|
+
return 'transient';
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Heuristic for whether a stored `last_error` describes a transient failure,
|
|
190
|
+
* used by the resurrection pass to revive rows that the OLD 3-attempt logic
|
|
191
|
+
* wrongly marked terminal. We can't store the classification (no schema
|
|
192
|
+
* change), so we infer from the message:
|
|
193
|
+
* - `HTTP 4xx` (but not `HTTP 429`) → permanent → leave failed.
|
|
194
|
+
* - everything else (timeouts, network messages, `HTTP 5xx`, `HTTP 429`)
|
|
195
|
+
* → transient → resurrect.
|
|
196
|
+
* Conservative by design: an unrecognised message is treated as transient so
|
|
197
|
+
* we err on the side of retrying rather than silently dropping a sync.
|
|
165
198
|
*/
|
|
166
|
-
function
|
|
199
|
+
function isTransientErrorMessage(lastError) {
|
|
200
|
+
if (!lastError)
|
|
201
|
+
return true;
|
|
202
|
+
const m = /^HTTP (\d{3})/.exec(lastError);
|
|
203
|
+
if (m)
|
|
204
|
+
return classifyHttpStatus(Number(m[1])) === 'transient';
|
|
205
|
+
return true; // network/timeout/unknown → transient
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Schedule a transient-failure retry. Keeps the row `pending` with a future
|
|
209
|
+
* `next_retry_at` using capped exponential backoff (min(2^attempts*30s, 1h)).
|
|
210
|
+
* Crucially this does NOT honour max_attempts — transient errors retry until
|
|
211
|
+
* the 7-day TTL purge, so an overnight outage recovers instead of being
|
|
212
|
+
* permanently lost after 3 strikes. `attempts` still increments for observability.
|
|
213
|
+
*/
|
|
214
|
+
function scheduleRetry(rowId, currentAttempts, newAttempts, errorMsg) {
|
|
167
215
|
const db = getDatabase();
|
|
168
|
-
|
|
169
|
-
db.prepare(`
|
|
170
|
-
UPDATE sync_queue SET status = 'failed', attempts = ?, last_error = ?
|
|
171
|
-
WHERE id = ?
|
|
172
|
-
`).run(newAttempts, errorMsg, rowId);
|
|
173
|
-
return true; // permanently failed
|
|
174
|
-
}
|
|
175
|
-
const backoffMs = Math.pow(2, currentAttempts) * 30_000;
|
|
216
|
+
const backoffMs = Math.min(Math.pow(2, currentAttempts) * BASE_BACKOFF_MS, MAX_BACKOFF_MS);
|
|
176
217
|
const nextRetry = new Date(Date.now() + backoffMs).toISOString();
|
|
177
218
|
db.prepare(`
|
|
178
|
-
UPDATE sync_queue SET attempts = ?, next_retry_at = ?, last_error = ?
|
|
219
|
+
UPDATE sync_queue SET status = 'pending', attempts = ?, next_retry_at = ?, last_error = ?
|
|
179
220
|
WHERE id = ?
|
|
180
221
|
`).run(newAttempts, nextRetry, errorMsg, rowId);
|
|
181
|
-
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Mark a queue row permanently failed (HTTP 4xx). No further retries.
|
|
225
|
+
*/
|
|
226
|
+
function markPermanentlyFailed(rowId, newAttempts, errorMsg) {
|
|
227
|
+
const db = getDatabase();
|
|
228
|
+
db.prepare(`
|
|
229
|
+
UPDATE sync_queue SET status = 'failed', attempts = ?, last_error = ?
|
|
230
|
+
WHERE id = ?
|
|
231
|
+
`).run(newAttempts, errorMsg, rowId);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Revive `failed` rows that were really transient failures (old 3-attempt
|
|
235
|
+
* logic, or pre-upgrade rows). Only rows still within the 7-day TTL window
|
|
236
|
+
* and whose `last_error` looks transient are reset to `pending` + due now.
|
|
237
|
+
* Genuine 4xx failures stay failed. Returns the number of rows resurrected.
|
|
238
|
+
*/
|
|
239
|
+
function resurrectTransientFailures() {
|
|
240
|
+
const db = getDatabase();
|
|
241
|
+
const now = new Date().toISOString();
|
|
242
|
+
const cutoff = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
243
|
+
// Resurrect failed rows within TTL whose last_error is NOT a 4xx (4xx except
|
|
244
|
+
// 429 are permanent). `HTTP 429` and `HTTP 5xx` and network/timeout messages
|
|
245
|
+
// all fall through to transient. NULL last_error → transient (be generous).
|
|
246
|
+
const result = db.prepare(`
|
|
247
|
+
UPDATE sync_queue
|
|
248
|
+
SET status = 'pending', next_retry_at = ?
|
|
249
|
+
WHERE status = 'failed'
|
|
250
|
+
AND created_at > ?
|
|
251
|
+
AND (
|
|
252
|
+
last_error IS NULL
|
|
253
|
+
OR last_error NOT GLOB 'HTTP 4[0-9][0-9]*'
|
|
254
|
+
OR last_error GLOB 'HTTP 429*'
|
|
255
|
+
)
|
|
256
|
+
`).run(now, cutoff);
|
|
257
|
+
return Number(result.changes ?? 0);
|
|
182
258
|
}
|
|
183
259
|
function formatQueueError(err) {
|
|
184
260
|
const name = err instanceof Error ? err.name : '';
|
|
@@ -191,14 +267,25 @@ function formatQueueError(err) {
|
|
|
191
267
|
}
|
|
192
268
|
return message;
|
|
193
269
|
}
|
|
270
|
+
// Default per-tick budget for the full profile. Kept at the historical value
|
|
271
|
+
// so dashboard behaviour is unchanged; mcp callers pass a smaller budget.
|
|
272
|
+
const DEFAULT_RETRY_BUDGET = 10;
|
|
194
273
|
/**
|
|
195
274
|
* Process pending items in the retry queue.
|
|
196
|
-
*
|
|
275
|
+
*
|
|
276
|
+
* Runs a resurrection pass first (revive transiently-failed rows within TTL),
|
|
277
|
+
* then SELECTs pending rows due for retry (up to `maxRows`) and attempts each.
|
|
197
278
|
* Awaits each fetch so results are accurate and no double-processing occurs.
|
|
279
|
+
*
|
|
280
|
+
* Failure handling:
|
|
281
|
+
* - HTTP 4xx (≠429) → permanent: mark failed, no further retries.
|
|
282
|
+
* - network/timeout/5xx/429 → transient: keep pending with capped (≤1h)
|
|
283
|
+
* backoff, retrying until the 7-day TTL purge — survives long outages.
|
|
198
284
|
*/
|
|
199
|
-
export async function processRetryQueue() {
|
|
285
|
+
export async function processRetryQueue(options = {}) {
|
|
200
286
|
const db = getDatabase();
|
|
201
287
|
const config = getCloudConfig();
|
|
288
|
+
const limit = options.maxRows && options.maxRows > 0 ? options.maxRows : DEFAULT_RETRY_BUDGET;
|
|
202
289
|
const result = {
|
|
203
290
|
processed: 0,
|
|
204
291
|
succeeded: 0,
|
|
@@ -209,15 +296,23 @@ export async function processRetryQueue() {
|
|
|
209
296
|
if (!config.cloudEnabled || !config.cloudApiKey) {
|
|
210
297
|
return result;
|
|
211
298
|
}
|
|
299
|
+
// Revive any transiently-failed rows (old 3-attempt logic / pre-upgrade)
|
|
300
|
+
// before selecting the pending batch, so they get a chance this tick.
|
|
301
|
+
try {
|
|
302
|
+
resurrectTransientFailures();
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
/* best-effort — resurrection failure must not block live retries */
|
|
306
|
+
}
|
|
212
307
|
const now = new Date().toISOString();
|
|
213
|
-
// Fetch
|
|
308
|
+
// Fetch pending items ready for retry, bounded by the budget.
|
|
214
309
|
const rows = db.prepare(`
|
|
215
|
-
SELECT id, payload, attempts
|
|
310
|
+
SELECT id, payload, attempts
|
|
216
311
|
FROM sync_queue
|
|
217
312
|
WHERE status = 'pending' AND next_retry_at <= ?
|
|
218
313
|
ORDER BY next_retry_at ASC
|
|
219
|
-
LIMIT
|
|
220
|
-
`).all(now);
|
|
314
|
+
LIMIT ?
|
|
315
|
+
`).all(now, limit);
|
|
221
316
|
if (rows.length === 0) {
|
|
222
317
|
return result;
|
|
223
318
|
}
|
|
@@ -250,21 +345,21 @@ export async function processRetryQueue() {
|
|
|
250
345
|
}
|
|
251
346
|
catch { /* non-critical */ }
|
|
252
347
|
}
|
|
348
|
+
else if (classifyHttpStatus(res.status) === 'permanent') {
|
|
349
|
+
markPermanentlyFailed(row.id, newAttempts, `HTTP ${res.status}`);
|
|
350
|
+
result.permanentlyFailed++;
|
|
351
|
+
}
|
|
253
352
|
else {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
else
|
|
258
|
-
result.failed++;
|
|
353
|
+
// 5xx / 429 — transient, keep retrying with capped backoff.
|
|
354
|
+
scheduleRetry(row.id, row.attempts, newAttempts, `HTTP ${res.status}`);
|
|
355
|
+
result.failed++;
|
|
259
356
|
}
|
|
260
357
|
}
|
|
261
358
|
catch (err) {
|
|
359
|
+
// Network errors, timeouts (AbortError) — all transient.
|
|
262
360
|
const errorMsg = formatQueueError(err);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
result.permanentlyFailed++;
|
|
266
|
-
else
|
|
267
|
-
result.failed++;
|
|
361
|
+
scheduleRetry(row.id, row.attempts, newAttempts, errorMsg);
|
|
362
|
+
result.failed++;
|
|
268
363
|
}
|
|
269
364
|
}
|
|
270
365
|
return result;
|
|
@@ -6,10 +6,29 @@
|
|
|
6
6
|
* toolchain to compile from source), the native load fails — historically
|
|
7
7
|
* with a bare `libc++abi: terminating ... Napi::Error` crash-loop and zero
|
|
8
8
|
* guidance. This module is the single place better-sqlite3 is loaded at
|
|
9
|
-
* runtime: it turns that failure into one actionable
|
|
10
|
-
*
|
|
9
|
+
* runtime: it turns that failure into one actionable, catchable error
|
|
10
|
+
* instead of an opaque abort.
|
|
11
|
+
*
|
|
12
|
+
* It must NEVER call `process.exit()`: this module is reachable from the
|
|
13
|
+
* library entry (`shieldcortex` → `initDatabase`), so a host app that merely
|
|
14
|
+
* imports the package must not be terminated. The load failure is thrown as a
|
|
15
|
+
* typed `NativeModuleLoadError`; a CLI/server entry point can catch it and
|
|
16
|
+
* decide to exit, but the module itself stays a well-behaved library.
|
|
11
17
|
*/
|
|
12
18
|
import type DatabaseConstructor from 'better-sqlite3';
|
|
19
|
+
/**
|
|
20
|
+
* Thrown when the better-sqlite3 native binding cannot be loaded (missing /
|
|
21
|
+
* ABI-mismatched / wrong-arch prebuild, or the module is not installed).
|
|
22
|
+
*
|
|
23
|
+
* Carries the actionable, formatted guidance in `.message` so a caller can
|
|
24
|
+
* print it verbatim. Typed so entry points can distinguish an environmental
|
|
25
|
+
* install problem from a genuine runtime error and exit cleanly if they choose.
|
|
26
|
+
*/
|
|
27
|
+
export declare class NativeModuleLoadError extends Error {
|
|
28
|
+
/** The original error raised by `require('better-sqlite3')`. */
|
|
29
|
+
readonly cause: unknown;
|
|
30
|
+
constructor(message: string, cause: unknown);
|
|
31
|
+
}
|
|
13
32
|
/**
|
|
14
33
|
* Build the user-facing message for a native-load failure. Pure and
|
|
15
34
|
* side-effect free so it can be unit-tested without breaking the binding.
|
|
@@ -6,11 +6,34 @@
|
|
|
6
6
|
* toolchain to compile from source), the native load fails — historically
|
|
7
7
|
* with a bare `libc++abi: terminating ... Napi::Error` crash-loop and zero
|
|
8
8
|
* guidance. This module is the single place better-sqlite3 is loaded at
|
|
9
|
-
* runtime: it turns that failure into one actionable
|
|
10
|
-
*
|
|
9
|
+
* runtime: it turns that failure into one actionable, catchable error
|
|
10
|
+
* instead of an opaque abort.
|
|
11
|
+
*
|
|
12
|
+
* It must NEVER call `process.exit()`: this module is reachable from the
|
|
13
|
+
* library entry (`shieldcortex` → `initDatabase`), so a host app that merely
|
|
14
|
+
* imports the package must not be terminated. The load failure is thrown as a
|
|
15
|
+
* typed `NativeModuleLoadError`; a CLI/server entry point can catch it and
|
|
16
|
+
* decide to exit, but the module itself stays a well-behaved library.
|
|
11
17
|
*/
|
|
12
18
|
import { createRequire } from 'module';
|
|
13
19
|
const require = createRequire(import.meta.url);
|
|
20
|
+
/**
|
|
21
|
+
* Thrown when the better-sqlite3 native binding cannot be loaded (missing /
|
|
22
|
+
* ABI-mismatched / wrong-arch prebuild, or the module is not installed).
|
|
23
|
+
*
|
|
24
|
+
* Carries the actionable, formatted guidance in `.message` so a caller can
|
|
25
|
+
* print it verbatim. Typed so entry points can distinguish an environmental
|
|
26
|
+
* install problem from a genuine runtime error and exit cleanly if they choose.
|
|
27
|
+
*/
|
|
28
|
+
export class NativeModuleLoadError extends Error {
|
|
29
|
+
/** The original error raised by `require('better-sqlite3')`. */
|
|
30
|
+
cause;
|
|
31
|
+
constructor(message, cause) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'NativeModuleLoadError';
|
|
34
|
+
this.cause = cause;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
14
37
|
/**
|
|
15
38
|
* Build the user-facing message for a native-load failure. Pure and
|
|
16
39
|
* side-effect free so it can be unit-tested without breaking the binding.
|
|
@@ -67,9 +90,10 @@ function loadBetterSqlite3() {
|
|
|
67
90
|
}
|
|
68
91
|
catch (err) {
|
|
69
92
|
const message = formatNativeLoadError(err, process.version, String(process.versions.modules));
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
// THROW, never exit: this module is imported by the library entry, so it
|
|
94
|
+
// must not kill a host app. The message carries the rebuild guidance; an
|
|
95
|
+
// entry point (CLI/server) may catch this and exit if it wants to.
|
|
96
|
+
throw new NativeModuleLoadError(message, err);
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
99
|
const BetterSqlite3 = loadBetterSqlite3();
|
package/dist/database/init.js
CHANGED
|
@@ -9,6 +9,7 @@ import { fileURLToPath } from 'url';
|
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
10
|
import { runMigrations } from './migrations.js';
|
|
11
11
|
import { getInlineSchema } from './inline-schema.js';
|
|
12
|
+
import { seedDefaultFirewallRules } from './seed-firewall-rules.js';
|
|
12
13
|
const _currentFile = fileURLToPath(import.meta.url);
|
|
13
14
|
const _currentDir = dirname(_currentFile);
|
|
14
15
|
let db = null;
|
|
@@ -427,7 +428,20 @@ export function initDatabase(dbPath) {
|
|
|
427
428
|
currentDbPath = expandedPath;
|
|
428
429
|
acquireStartupLock(expandedPath);
|
|
429
430
|
console.error(`[database] Startup runtime=${resolveRuntimeInfo().kind} db=${expandedPath} wal=${existsSync(expandedPath + '-wal')} shm=${existsSync(expandedPath + '-shm')}`);
|
|
430
|
-
|
|
431
|
+
// Lazily inspect `.corrupt.*` backups (Phase 17 B4). Each backup inspection
|
|
432
|
+
// opens the file read-only and runs a FULL integrity check, so doing it
|
|
433
|
+
// unconditionally on every startup paid a per-backup scan even when the live
|
|
434
|
+
// DB opened cleanly. Defer it: the only consumers are the corruption /
|
|
435
|
+
// empty-live recovery branches below, so the scan now happens ONLY when
|
|
436
|
+
// recovery is actually invoked. Memoised so a branch that consults it twice
|
|
437
|
+
// still inspects each backup once.
|
|
438
|
+
let _healthyBackups = null;
|
|
439
|
+
const getHealthyBackups = () => {
|
|
440
|
+
if (_healthyBackups === null) {
|
|
441
|
+
_healthyBackups = listHealthyBackups(expandedPath);
|
|
442
|
+
}
|
|
443
|
+
return _healthyBackups;
|
|
444
|
+
};
|
|
431
445
|
// Wrap the initial open in try/catch to handle corrupt files gracefully
|
|
432
446
|
let database;
|
|
433
447
|
try {
|
|
@@ -452,7 +466,7 @@ export function initDatabase(dbPath) {
|
|
|
452
466
|
}
|
|
453
467
|
// Database file is corrupt or not a valid SQLite database
|
|
454
468
|
console.error(`❌ Database open failed for ${expandedPath}: ${openError}`);
|
|
455
|
-
const latestHealthyBackup =
|
|
469
|
+
const latestHealthyBackup = getHealthyBackups()[0];
|
|
456
470
|
if (latestHealthyBackup) {
|
|
457
471
|
console.error(`[database] Restoring latest healthy backup with ${latestHealthyBackup.count} memories: ${latestHealthyBackup.path}`);
|
|
458
472
|
restoreBackupAsLive(expandedPath, latestHealthyBackup.path, 'failed-open');
|
|
@@ -465,13 +479,21 @@ export function initDatabase(dbPath) {
|
|
|
465
479
|
database = new BetterSqlite3(expandedPath);
|
|
466
480
|
}
|
|
467
481
|
}
|
|
468
|
-
// Integrity check on existing databases (skip for newly created files)
|
|
482
|
+
// Integrity check on existing databases (skip for newly created files).
|
|
483
|
+
// This is the SINGLE live-DB integrity scan on the startup path (Phase 17
|
|
484
|
+
// B4). `liveIntegrityOk` records its outcome so the empty-live heuristic
|
|
485
|
+
// below can reuse it instead of re-opening the file and scanning a second
|
|
486
|
+
// time. It stays true for freshly-created files (size 0, check skipped) and
|
|
487
|
+
// for connections rebuilt by a recovery branch — both are known-good.
|
|
488
|
+
let liveIntegrityOk = true;
|
|
469
489
|
if (existsSync(expandedPath) && statSync(expandedPath).size > 0) {
|
|
470
490
|
const integrityResult = runIntegrityCheck(database);
|
|
491
|
+
liveIntegrityOk = integrityResult === 'ok';
|
|
471
492
|
if (integrityResult !== 'ok') {
|
|
472
493
|
console.warn(`[database] WARNING: Database integrity check failed: ${integrityResult}`);
|
|
473
494
|
if (isLikelyFtsIntegrityIssue(integrityResult) && attemptFtsRecovery(database)) {
|
|
474
495
|
console.warn('[database] Preserved memory rows by repairing the FTS index in place.');
|
|
496
|
+
liveIntegrityOk = true; // FTS rebuild re-verified integrity == 'ok'.
|
|
475
497
|
}
|
|
476
498
|
else {
|
|
477
499
|
const freshIntegrityResult = verifyOnDiskIntegrity(expandedPath);
|
|
@@ -479,6 +501,7 @@ export function initDatabase(dbPath) {
|
|
|
479
501
|
console.warn('[database] Integrity failure was transient. Reopening the on-disk database without destructive recovery.');
|
|
480
502
|
database.close();
|
|
481
503
|
database = new BetterSqlite3(expandedPath);
|
|
504
|
+
liveIntegrityOk = true; // On-disk re-check was clean.
|
|
482
505
|
}
|
|
483
506
|
else {
|
|
484
507
|
console.warn(`[database] Fresh integrity check also failed: ${freshIntegrityResult}`);
|
|
@@ -490,7 +513,7 @@ export function initDatabase(dbPath) {
|
|
|
490
513
|
database = recovered;
|
|
491
514
|
}
|
|
492
515
|
else {
|
|
493
|
-
const latestHealthyBackup =
|
|
516
|
+
const latestHealthyBackup = getHealthyBackups()[0];
|
|
494
517
|
if (latestHealthyBackup) {
|
|
495
518
|
console.error(`[database] Recovery failed. Restoring latest healthy backup with ${latestHealthyBackup.count} memories: ${latestHealthyBackup.path}`);
|
|
496
519
|
restoreBackupAsLive(expandedPath, latestHealthyBackup.path, 'recovery-failed');
|
|
@@ -506,23 +529,40 @@ export function initDatabase(dbPath) {
|
|
|
506
529
|
database = new BetterSqlite3(expandedPath);
|
|
507
530
|
}
|
|
508
531
|
}
|
|
532
|
+
// Dump-recovery, backup-restore and fresh-create all yield a
|
|
533
|
+
// known-good DB — the empty-live heuristic can trust it.
|
|
534
|
+
liveIntegrityOk = true;
|
|
509
535
|
}
|
|
510
536
|
}
|
|
511
537
|
}
|
|
512
538
|
}
|
|
513
|
-
|
|
514
|
-
|
|
539
|
+
// Empty-live recovery heuristic (Phase 17 B4): this used to call
|
|
540
|
+
// `inspectDatabaseFile(expandedPath)`, which RE-OPENED the live file
|
|
541
|
+
// read-only and ran a SECOND full integrity check purely to obtain the row
|
|
542
|
+
// count — duplicating the scan already performed above. Now the count comes
|
|
543
|
+
// from the open connection and integrity is reused from `liveIntegrityOk`.
|
|
544
|
+
// `getHealthyBackups()` (the eager per-backup scan) is consulted ONLY when
|
|
545
|
+
// the live DB is actually healthy-but-empty, so a normal startup never
|
|
546
|
+
// inspects a backup at all.
|
|
547
|
+
let liveCount = null;
|
|
548
|
+
try {
|
|
549
|
+
liveCount = database.prepare('SELECT COUNT(*) AS count FROM memories').get().count;
|
|
550
|
+
}
|
|
551
|
+
catch {
|
|
552
|
+
liveCount = null;
|
|
553
|
+
}
|
|
515
554
|
const liveStats = existsSync(expandedPath) ? statSync(expandedPath) : null;
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
555
|
+
if (liveIntegrityOk && liveCount === 0) {
|
|
556
|
+
const latestHealthyBackup = getHealthyBackups()[0];
|
|
557
|
+
if (latestHealthyBackup
|
|
558
|
+
&& latestHealthyBackup.count >= 100
|
|
559
|
+
&& liveStats
|
|
560
|
+
&& (liveStats.mtimeMs - latestHealthyBackup.mtimeMs) < (24 * 60 * 60 * 1000)) {
|
|
561
|
+
console.error(`[database] Empty live database detected alongside a recent healthy backup (${latestHealthyBackup.count} memories). Restoring ${latestHealthyBackup.path}`);
|
|
562
|
+
database.close();
|
|
563
|
+
restoreBackupAsLive(expandedPath, latestHealthyBackup.path, 'empty-live');
|
|
564
|
+
database = new BetterSqlite3(expandedPath);
|
|
565
|
+
}
|
|
526
566
|
}
|
|
527
567
|
db = database;
|
|
528
568
|
// Record file identity so getDatabase() can detect if the file was replaced
|
|
@@ -577,6 +617,18 @@ export function initDatabase(dbPath) {
|
|
|
577
617
|
// Inline schema if file not found (for bundled deployment)
|
|
578
618
|
db.exec(getInlineSchema());
|
|
579
619
|
}
|
|
620
|
+
// Seed built-in firewall rules. This runs AFTER the schema so the
|
|
621
|
+
// firewall_rules table is guaranteed to exist — `runMigrations()` returns
|
|
622
|
+
// early on a fresh DB (no `memories` table), so seeding cannot live there or
|
|
623
|
+
// it never fires for new installs (the case the README's "seeded on first
|
|
624
|
+
// run" promise covers). Idempotent: the seeder no-ops when built_in rows are
|
|
625
|
+
// already present, so re-running on every startup is safe and cheap.
|
|
626
|
+
try {
|
|
627
|
+
seedDefaultFirewallRules(db);
|
|
628
|
+
}
|
|
629
|
+
catch {
|
|
630
|
+
// Seeder is best-effort; a failure here must never block startup.
|
|
631
|
+
}
|
|
580
632
|
return db;
|
|
581
633
|
}
|
|
582
634
|
/**
|
|
@@ -69,7 +69,7 @@ export function getInlineSchema() {
|
|
|
69
69
|
VALUES('delete', old.id, old.title, old.content, old.tags);
|
|
70
70
|
END;
|
|
71
71
|
|
|
72
|
-
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
72
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE OF title, content, tags ON memories BEGIN
|
|
73
73
|
INSERT INTO memories_fts(memories_fts, rowid, title, content, tags)
|
|
74
74
|
VALUES('delete', old.id, old.title, old.content, old.tags);
|
|
75
75
|
INSERT INTO memories_fts(rowid, title, content, tags)
|
|
@@ -183,6 +183,18 @@ export function getInlineSchema() {
|
|
|
183
183
|
CREATE INDEX IF NOT EXISTS idx_audit_source ON defence_audit(source_type);
|
|
184
184
|
CREATE INDEX IF NOT EXISTS idx_audit_project ON defence_audit(project);
|
|
185
185
|
|
|
186
|
+
-- Cumulative audit aggregate (single row, id=1) — retention rollup target.
|
|
187
|
+
-- See schema.sql for the rationale.
|
|
188
|
+
CREATE TABLE IF NOT EXISTS audit_aggregates (
|
|
189
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
190
|
+
total_scans INTEGER NOT NULL DEFAULT 0,
|
|
191
|
+
threats_blocked INTEGER NOT NULL DEFAULT 0,
|
|
192
|
+
quarantined INTEGER NOT NULL DEFAULT 0,
|
|
193
|
+
memories_protected INTEGER NOT NULL DEFAULT 0,
|
|
194
|
+
credential_leaks INTEGER NOT NULL DEFAULT 0,
|
|
195
|
+
updated_at TEXT
|
|
196
|
+
);
|
|
197
|
+
|
|
186
198
|
CREATE TABLE IF NOT EXISTS quarantine (
|
|
187
199
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
188
200
|
original_content TEXT NOT NULL,
|
|
@@ -283,10 +295,12 @@ export function getInlineSchema() {
|
|
|
283
295
|
condition_value TEXT NOT NULL,
|
|
284
296
|
action TEXT NOT NULL CHECK(action IN ('block', 'allow', 'quarantine')),
|
|
285
297
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
298
|
+
built_in INTEGER NOT NULL DEFAULT 0,
|
|
286
299
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
287
300
|
);
|
|
288
301
|
CREATE INDEX IF NOT EXISTS idx_firewall_rules_priority ON firewall_rules(priority);
|
|
289
302
|
CREATE INDEX IF NOT EXISTS idx_firewall_rules_enabled ON firewall_rules(enabled);
|
|
303
|
+
CREATE INDEX IF NOT EXISTS idx_firewall_rules_built_in ON firewall_rules(built_in);
|
|
290
304
|
|
|
291
305
|
CREATE TABLE IF NOT EXISTS rate_limits (
|
|
292
306
|
source_key TEXT PRIMARY KEY,
|
|
@@ -294,6 +308,14 @@ export function getInlineSchema() {
|
|
|
294
308
|
window_start_ms INTEGER NOT NULL
|
|
295
309
|
);
|
|
296
310
|
|
|
311
|
+
-- Control state (single row, cross-process kill-switch / pause)
|
|
312
|
+
CREATE TABLE IF NOT EXISTS control_state (
|
|
313
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
314
|
+
mode TEXT NOT NULL DEFAULT 'active' CHECK (mode IN ('active','paused','kill_switch')),
|
|
315
|
+
meta_json TEXT,
|
|
316
|
+
updated_at TEXT NOT NULL
|
|
317
|
+
);
|
|
318
|
+
|
|
297
319
|
-- v4.17 Session capture (mirrors schema.sql; bundled fallback only).
|
|
298
320
|
-- v4.28 (Fix #10): + sensitivity_level for prompt-redaction tagging.
|
|
299
321
|
CREATE TABLE IF NOT EXISTS session_events (
|
|
@@ -318,5 +340,17 @@ export function getInlineSchema() {
|
|
|
318
340
|
CREATE INDEX IF NOT EXISTS idx_session_events_sensitivity ON session_events(sensitivity_level);
|
|
319
341
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_session_events_dedupe
|
|
320
342
|
ON session_events(session_id, ts, kind, content_hash);
|
|
343
|
+
|
|
344
|
+
-- Phase 14: MCP tool-description hashes (drift / rug-pull detection).
|
|
345
|
+
-- Mirrors schema.sql.
|
|
346
|
+
CREATE TABLE IF NOT EXISTS mcp_tool_hashes (
|
|
347
|
+
server_name TEXT NOT NULL,
|
|
348
|
+
tool_name TEXT NOT NULL,
|
|
349
|
+
content_hash TEXT NOT NULL,
|
|
350
|
+
first_seen TEXT,
|
|
351
|
+
last_seen TEXT,
|
|
352
|
+
last_changed TEXT,
|
|
353
|
+
PRIMARY KEY (server_name, tool_name)
|
|
354
|
+
);
|
|
321
355
|
`;
|
|
322
356
|
}
|