shieldcortex 4.39.0 → 4.41.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/(dashboard)/admin/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/cloud/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/capture/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/graph/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/page/react-loadable-manifest.json +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/recall/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/replay/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/review/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/memory/timeline/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/overview/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/audit/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/intercepts/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/iron-dome/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/policies/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/protection/quarantine/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/supply-chain/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/supply-chain/xray/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/(dashboard)/xray/page_client-reference-manifest.js +1 -1
- 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/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +2 -2
- 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 +3 -3
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/page_client-reference-manifest.js +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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +2 -2
- 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 +3 -3
- 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 +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_c219bf07._.js +4 -4
- package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_src_components_xray_XRayOverview_tsx_ceba698e._.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/6dddc4bf46b08fb2.css +1 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/90baaf667600b429.js +1 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/{e8884e7f3b85fd0b.js → 9305fb02787779da.js} +1 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/9b02aba35b7ce4b7.js +15 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/e18095d552836b96.js +1 -0
- package/dist/api/events.js +2 -0
- package/dist/api/redact-response.d.ts +15 -0
- package/dist/api/redact-response.js +19 -0
- package/dist/api/routes/memories.js +86 -21
- package/dist/api/visualization-server.js +15 -4
- package/dist/cloud/cli.js +13 -1
- package/dist/cloud/config.d.ts +10 -0
- package/dist/cloud/config.js +15 -0
- package/dist/defence/audit/queries.d.ts +1 -1
- package/dist/defence/trust/access-control.d.ts +1 -4
- package/dist/defence/trust/access-control.js +32 -0
- package/dist/defence/trust/read-guard.d.ts +42 -0
- package/dist/defence/trust/read-guard.js +120 -0
- package/dist/defence/types.d.ts +1 -1
- package/dist/memory/store.d.ts +4 -2
- package/dist/memory/store.js +9 -7
- package/dist/server.js +9 -1
- package/dist/tools/forget.d.ts +3 -0
- package/dist/tools/forget.js +53 -1
- package/package.json +1 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/1600063be806f47c.js +0 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/61aaa0c660c32b96.js +0 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/98ae91e0a6f5d317.css +0 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/cfbc41857d998b74.js +0 -15
- /package/dashboard/.next/standalone/dashboard/.next/static/{LfTY3B6uX3j7zNwqqgvPG → QyU8uJKG3JL56w9hEtgrx}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{LfTY3B6uX3j7zNwqqgvPG → QyU8uJKG3JL56w9hEtgrx}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{LfTY3B6uX3j7zNwqqgvPG → QyU8uJKG3JL56w9hEtgrx}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,27918,e=>{"use strict";var t=e.i(27493),a=e.i(4),s=e.i(45434),r=e.i(36062),i=e.i(71259),n=e.i(24929);let c=(0,n.default)("file-search",[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["circle",{cx:"11.5",cy:"14.5",r:"2.5",key:"1bq0ko"}],["path",{d:"M13.3 16.3 15 18",key:"2quom7"}]]),l=(0,n.default)("folder-search",[["path",{d:"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1",key:"1bw5m7"}],["path",{d:"m21 21-1.9-1.9",key:"1g2n9r"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}]]);var d=e.i(66949);let o=(0,n.default)("radar",[["path",{d:"M19.07 4.93A10 10 0 0 0 6.99 3.34",key:"z3du51"}],["path",{d:"M4 6h.01",key:"oypzma"}],["path",{d:"M2.29 9.62A10 10 0 1 0 21.31 8.35",key:"qzzz0"}],["path",{d:"M16.24 7.76A6 6 0 1 0 8.23 16.67",key:"1yjesh"}],["path",{d:"M12 18h.01",key:"mhygvu"}],["path",{d:"M17.99 11.66A6 6 0 0 1 15.77 16.67",key:"1u2y91"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}],["path",{d:"m13.41 10.59 5.66-5.66",key:"mhq4k0"}]]);var x=e.i(76344),m=e.i(48615),v=e.i(88969),u=e.i(35372),h=e.i(16467),p=e.i(95659),g=e.i(81523),y=e.i(40950),f=e.i(46194);function j({score:e,size:a=160,label:s}){let r=2*Math.PI*42,i=e/100*r,n=e<=50?"var(--sc-coral)":e<=75?"var(--sc-amber)":"var(--sc-cyan)",c=e<=50?"var(--sc-glow-coral)":e<=75?"rgba(245, 158, 11, 0.15)":"var(--sc-glow-cyan)";return(0,t.jsxs)("div",{className:"flex flex-col items-center gap-2",children:[(0,t.jsxs)("div",{className:"relative",style:{width:a,height:a},children:[(0,t.jsxs)("svg",{viewBox:"0 0 100 100",className:"h-full w-full -rotate-90",style:{filter:`drop-shadow(0 0 12px ${c})`},children:[(0,t.jsx)("circle",{cx:"50",cy:"50",r:42,fill:"none",stroke:"var(--sc-bg-elevated)",strokeWidth:"7"}),(0,t.jsx)("circle",{cx:"50",cy:"50",r:42,fill:"none",stroke:n,strokeWidth:"7",strokeDasharray:`${i} ${r}`,strokeLinecap:"round",className:"transition-all duration-1000 ease-out"})]}),(0,t.jsxs)("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[(0,t.jsx)("span",{className:"text-3xl font-bold",style:{color:n},children:e}),(0,t.jsx)("span",{className:"text-[11px] text-[var(--sc-text-muted)]",children:"trust"})]})]}),s&&(0,t.jsx)("span",{className:"text-xs font-medium text-[var(--sc-text-secondary)]",children:s})]})}var b=e.i(16511);let N=(0,n.default)("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);var k=e.i(27528),w=e.i(77744),S=e.i(22534),C=e.i(45688),B=e.i(71921),E=e.i(1235);let F=S.default.env.NEXT_PUBLIC_API_URL||"http://localhost:3001";function $(e){return(0,C.useQuery)({queryKey:["xray-findings",e],queryFn:async()=>{let t=new URLSearchParams;e?.status&&t.set("status",e.status),e?.severity&&t.set("severity",e.severity),e?.target&&t.set("target",e.target),e?.limit&&t.set("limit",String(e.limit));let a=t.toString()?`?${t}`:"",s=await (0,v.gatedFetch)(`${F}/api/xray/findings${a}`);if(!s.ok)throw Error(await (0,v.readApiError)(s,"Failed to fetch findings"));return s.json()},refetchInterval:15e3})}function z(){let e=(0,E.useQueryClient)();return(0,B.useMutation)({mutationFn:async({id:e,status:t,note:a})=>{let s=await (0,v.gatedFetch)(`${F}/api/xray/findings/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:t,note:a})});if(!s.ok)throw Error(await (0,v.readApiError)(s,"Failed to update finding"));return s.json()},onSuccess:()=>{e.invalidateQueries({queryKey:["xray-findings"]}),e.invalidateQueries({queryKey:["xray-findings-stats"]})}})}function A(){let e=(0,E.useQueryClient)();return(0,B.useMutation)({mutationFn:async({id:e,note:t})=>{let a=await (0,v.gatedFetch)(`${F}/api/xray/findings/${e}/quarantine`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({note:t})});if(!a.ok)throw Error(await (0,v.readApiError)(a,"Failed to quarantine file"));return a.json()},onSuccess:()=>{e.invalidateQueries({queryKey:["xray-findings"]}),e.invalidateQueries({queryKey:["xray-findings-stats"]})}})}function R({findingId:e,status:s,hasFile:r,compact:n=!1}){let c,[l,d]=(0,a.useState)(!1),[o,x]=(0,a.useState)(""),[u,h]=(0,a.useState)(!1),p=z(),y=A(),f=(c=(0,E.useQueryClient)(),(0,B.useMutation)({mutationFn:async e=>{let t=await (0,v.gatedFetch)(`${F}/api/xray/findings/${e}`,{method:"DELETE"});if(!t.ok)throw Error(await (0,v.readApiError)(t,"Failed to delete finding"));return t.json()},onSuccess:()=>{c.invalidateQueries({queryKey:["xray-findings"]}),c.invalidateQueries({queryKey:["xray-findings-stats"]})}})),j=t=>{switch(t){case"reviewed":p.mutate({id:e,status:"reviewed"},{onSuccess:()=>m.toast.success("Marked as reviewed"),onError:e=>m.toast.error(`Failed to update: ${e.message}`)});break;case"ignored":p.mutate({id:e,status:"ignored",note:o},{onSuccess:()=>{m.toast.info("Finding ignored — removed from active list"),d(!1),x(""),h(!0)},onError:e=>m.toast.error(`Failed to ignore: ${e.message}`)});break;case"resolved":p.mutate({id:e,status:"resolved",note:o},{onSuccess:()=>{m.toast.success("Finding resolved — removed from active list"),d(!1),x(""),h(!0)},onError:e=>m.toast.error(`Failed to resolve: ${e.message}`)});break;case"quarantine":y.mutate({id:e,note:o},{onSuccess:e=>{m.toast.warning(e.moved?"File quarantined and moved":"Marked quarantined (file not found)"),h(!0)},onError:e=>m.toast.error(`Quarantine failed: ${e.message}`)});break;case"delete":f.mutate(e,{onSuccess:()=>{m.toast.success("Finding deleted"),h(!0)},onError:e=>m.toast.error(`Failed to delete: ${e.message}`)})}};if(u)return(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--sc-cyan)] italic animate-pulse",children:[(0,t.jsx)(b.Check,{size:12})," Done — removing from list..."]});if("resolved"===s)return(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--sc-cyan)]",children:[(0,t.jsx)(b.Check,{size:12})," Resolved"]});if("quarantined"===s)return(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--sc-amber)]",children:[(0,t.jsx)(k.Shield,{size:12})," Quarantined"]});if("ignored"===s)return(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-xs text-[var(--sc-text-muted)]",children:[(0,t.jsx)(N,{size:12})," Ignored"]});let S=n?"sm":"md",C=p.isPending||y.isPending||f.isPending;return(0,t.jsxs)("div",{className:"space-y-2",children:[(0,t.jsxs)("div",{className:"flex flex-wrap gap-1.5",children:["new"===s&&(0,t.jsxs)(g.Button,{variant:"ghost",size:S,onClick:()=>j("reviewed"),disabled:C,children:[(0,t.jsx)(i.Eye,{size:12})," Mark reviewed"]}),(0,t.jsxs)(g.Button,{variant:"cyan",size:S,onClick:()=>d(!l),disabled:C,children:[(0,t.jsx)(b.Check,{size:12})," Resolve"]}),(0,t.jsxs)(g.Button,{variant:"ghost",size:S,onClick:()=>j("ignored"),disabled:C,children:[(0,t.jsx)(N,{size:12})," Safe to ignore"]}),r&&(0,t.jsxs)(g.Button,{variant:"coral",size:S,onClick:()=>j("quarantine"),disabled:C,children:[(0,t.jsx)(k.Shield,{size:12})," Quarantine file"]}),(0,t.jsx)(g.Button,{variant:"ghost",size:S,onClick:()=>j("delete"),disabled:C,children:(0,t.jsx)(w.Trash2,{size:12})})]}),l&&(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsx)("input",{value:o,onChange:e=>x(e.target.value),placeholder:"What did you do about it? (optional)",className:"flex-1 rounded-lg border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-3 py-1.5 text-xs text-[var(--sc-text-primary)] placeholder:text-[var(--sc-text-muted)] focus-ring-cyan","aria-label":"Resolution note",onKeyDown:e=>{"Enter"===e.key&&j("resolved")}}),(0,t.jsx)(g.Button,{variant:"cyan",size:"sm",onClick:()=>j("resolved"),disabled:C,children:"Done"})]})]})}var P=e.i(45256),L=e.i(51069),M=e.i(44758);let q=(0,n.default)("shield-x",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m14.5 9.5-5 5",key:"17q4r4"}],["path",{d:"m9.5 9.5 5 5",key:"18nt4w"}]]);var D=e.i(13808),T=e.i(76624),W=e.i(23457),I=e.i(44250);function G(e,t,a,s){return`${e}|${t}|${a??""}|${s??""}`}function Q({finding:e,target:s}){let r=(0,W.useLocalAiExplain)(),i=z(),n=A(),[c,l]=(0,a.useState)(new Set),d=e=>l(t=>{let a=new Set(t);return a.add(e),a}),o=!e.id&&!!s&&!!r.data,x=$(o?{target:s,limit:200}:void 0),v=(()=>{if(e.id)return e.id;if(!x.data?.findings)return;let t=G(e.category,e.title,e.file,e.line),a=x.data.findings.find(e=>G(e.category,e.title,e.file,e.line)===t);return a?.id})();return(0,t.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,t.jsxs)(g.Button,{variant:"outline",size:"sm",onClick:()=>{r.mutate({kind:"xray_finding",title:e.title,content:[`Title: ${e.title}`,`Description: ${e.description}`,e.file?`File: ${e.line?`${e.file}:${e.line}`:e.file}`:"",e.evidence?`Evidence: ${e.evidence}`:"",e.guidance?.whatItMeans?`Scanner meaning: ${e.guidance.whatItMeans}`:"",e.guidance?.whatToDo?`Scanner guidance: ${e.guidance.whatToDo}`:"",e.guidance?.falsePositiveNote?`False positive note: ${e.guidance.falsePositiveNote}`:""].filter(Boolean).join("\n"),source:e.file?`xray:${e.file}`:"xray",signals:[e.severity,e.category,e.status??"",e.guidance?.urgency??"",e.systemFile?"system-file":""].filter(Boolean),metadata:{id:e.id,file:e.file,line:e.line,severity:e.severity,category:e.category,status:e.status,detectedAt:e.detectedAt,systemFile:e.systemFile,guidance:e.guidance}},{onSuccess:e=>{m.toast.success(e.explanation.synthetic?"Fallback explanation generated":"Local explanation generated")},onError:e=>m.toast.error(e instanceof Error?e.message:"Local explanation failed")})},disabled:r.isPending,pulse:r.isPending,children:[(0,t.jsx)(D.Sparkles,{size:13}),r.isPending?"Explaining":"Explain"]}),r.data?.explanation&&(0,t.jsx)(T.LocalAiExplanationPanel,{explanation:r.data.explanation,actions:(()=>{let a=[];if(e.file){let s=(0,I.buildEditorUrl)(e.file,e.line);a.push({key:"open",label:"Open in editor",icon:(0,t.jsx)(P.ExternalLink,{size:13}),variant:"outline",onClick:()=>{s&&(window.location.href=s)}})}if(!v)return o&&x.isLoading&&a.push({key:"lookup",label:"Loading actions",variant:"outline",disabled:!0,pending:!0,onClick:()=>void 0}),a;let s=i.isPending||n.isPending,r=c.has("reviewed");a.push({key:"reviewed",label:r?"Reviewed":"Mark reviewed",icon:r?(0,t.jsx)(b.Check,{size:13}):(0,t.jsx)(M.ShieldCheck,{size:13}),variant:r?"cyan":"outline",pending:i.isPending&&i.variables?.status==="reviewed",disabled:s||r,onClick:()=>{i.mutate({id:v,status:"reviewed"},{onSuccess:()=>{d("reviewed"),m.toast.success("Marked as reviewed")},onError:e=>m.toast.error(e instanceof Error?e.message:"Failed to mark reviewed")})}});let l=c.has("dismiss");a.push({key:"dismiss",label:l?"Dismissed":"Dismiss",icon:l?(0,t.jsx)(b.Check,{size:13}):(0,t.jsx)(q,{size:13}),variant:l?"cyan":"ghost",pending:i.isPending&&i.variables?.status==="ignored",disabled:s||l,onClick:()=>{i.mutate({id:v,status:"ignored"},{onSuccess:()=>{d("dismiss"),m.toast.success("Finding dismissed")},onError:e=>m.toast.error(e instanceof Error?e.message:"Failed to dismiss")})}});let u=c.has("quarantine");return a.push({key:"quarantine",label:u?"Quarantined":"Quarantine file",icon:u?(0,t.jsx)(b.Check,{size:13}):(0,t.jsx)(L.ShieldAlert,{size:13}),variant:u?"cyan":"coral",pending:n.isPending,disabled:s||u,onClick:()=>{n.mutate({id:v},{onSuccess:()=>{d("quarantine"),m.toast.success("File quarantined")},onError:e=>m.toast.error(e instanceof Error?e.message:"Failed to quarantine")})}}),a})()}),r.error&&(0,t.jsx)(H,{message:r.error instanceof Error?r.error.message:"Local explanation failed"})]})}function H({message:e}){let a=e.toLowerCase();return a.includes("disabled")||a.includes("not cached")||a.includes("not enabled")?(0,t.jsxs)("div",{className:"space-y-2 rounded-lg border border-[var(--sc-border)] bg-[var(--sc-surface)]/40 p-3 text-sm text-[var(--sc-text-secondary)]",children:[(0,t.jsx)("p",{className:"font-medium text-[var(--sc-text-primary)]",children:e}),(0,t.jsx)("p",{children:"The Local AI Explainer is opt-in. Enable it from a terminal:"}),(0,t.jsx)("pre",{className:"overflow-x-auto rounded bg-black/30 p-2 text-xs text-[var(--sc-text-primary)]",children:"shieldcortex review-copilot enable --accept-download"}),(0,t.jsx)("p",{className:"text-xs text-[var(--sc-text-muted)]",children:"Runs a small local model (Qwen2.5-0.5B) on this machine — nothing leaves your device. Requires a Pro licence."})]}):(0,t.jsx)("div",{className:"rounded-lg border border-[var(--sc-coral)]/30 bg-[var(--sc-coral)]/10 p-3 text-sm text-[var(--sc-coral)]",children:e})}var X=e.i(31309);function K(e){return e?new Date(e).toLocaleString():"—"}function O(){let[e,n]=(0,a.useState)("scanner"),[b,N]=(0,a.useState)(""),[k,w]=(0,a.useState)(!1),[S,B]=(0,a.useState)(null),[E,z]=(0,a.useState)("ALL"),[A,P]=(0,a.useState)("all"),[L,M]=(0,a.useState)("all"),[q,D]=(0,a.useState)(""),[T,W]=(0,a.useState)("all"),[I,G]=(0,a.useState)("all"),[H,O]=(0,a.useState)(""),[V,U]=(0,a.useState)(!1),[_,J]=(0,a.useState)("new"),{data:Y}=(0,X.useXRayHistory)({risk:E,targetType:A,deep:L,search:q}),{data:Z}=(0,X.useXRayActivity)(8,{kind:T}),{data:ee}=(0,X.useXRayWatchSessions)(8,{state:I}),{data:et}=(0,X.useXRayStatus)(),{data:ea}=(0,C.useQuery)({queryKey:["xray-findings-stats"],queryFn:async()=>{let e=await (0,v.gatedFetch)(`${F}/api/xray/findings/stats`);if(!e.ok)throw Error(await (0,v.readApiError)(e,"Failed to fetch finding stats"));return e.json()},refetchInterval:15e3}),{data:es}=$({status:"all"===_?void 0:_}),er=(0,a.useMemo)(()=>Y?.entries??[],[Y?.entries]),ei=Z?.entries??[],en=ee?.entries??[],ec=(0,X.useXRayScan)(),el=(0,X.usePickXRayTarget)(),ed=S??(er.length>0?er[0].id:null),eo=(0,X.useXRayHistoryEntry)(ed),{data:ex}=(0,X.useActiveWatchers)(),em=(0,X.useStartWatch)(),ev=(0,X.useStopWatch)(),eu=ex?.watchers??[],eh=ec.data?.result,ep=ec.data?.persistedFindings??[],eg=ec.error,ey=eg instanceof v.FeatureLockedError;(0,u.useWebSocketEvent)(e=>{if("xray_detection"===e.type){let t=e.data;m.toast.warning(t.summary||"X-Ray detection",{description:`Risk: ${t.riskLevel||"unknown"}`,duration:8e3})}});let ef=eo.data?.entry??er.find(e=>e.id===ed)??null,ej=eh??ef?.result??null,eb=(0,a.useMemo)(()=>({total:er.length,avgScore:er.length?Math.round(er.reduce((e,t)=>e+t.trustScore,0)/er.length):null}),[er]),eN=et?.capabilities,ek=et?.summary,ew=[{id:"scanner",label:"Scanner",icon:(0,t.jsx)(x.ScanSearch,{size:14})},{id:"history",label:"History",count:eb.total},{id:"watch",label:"Watch",count:ek?.activeWatchRoots??0},{id:"activity",label:"Activity"},{id:"findings",label:"Findings",count:ea?.new??0}];return(0,t.jsx)("div",{className:"h-full overflow-y-auto",children:(0,t.jsxs)("div",{className:"mx-auto max-w-7xl space-y-6 p-6",children:[(0,t.jsx)(y.PageHeader,{eyebrow:"Supply Chain Security",title:"X-Ray Scanner",subtitle:"Scan packages, files, and directories for hidden risk signals.",tabs:ew,activeTab:e,onTabChange:e=>n(e),actions:(0,t.jsx)("div",{className:"flex items-center gap-3",children:(0,t.jsxs)(p.Badge,{variant:eN?.deepScan?"cyan":"muted",dot:!0,children:["Deep scan ",eN?.deepScan?"enabled":"gated"]})})}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4 lg:grid-cols-4",children:[(0,t.jsx)(f.StatCard,{label:"Total Scans",value:ek?.scans??0,icon:x.ScanSearch,accent:"cyan"}),(0,t.jsx)(f.StatCard,{label:"High Risk",value:ek?.highRiskScans??0,icon:s.Activity,accent:"coral"}),(0,t.jsx)(f.StatCard,{label:"Watch Roots",value:ek?.activeWatchRoots??0,icon:i.Eye,accent:"cyan"}),(0,t.jsx)(f.StatCard,{label:"Avg Trust",value:eb.avgScore??"—",icon:c,accent:eb.avgScore&&eb.avgScore>=70?"cyan":"amber"})]}),"scanner"===e&&(0,t.jsxs)("div",{className:"grid gap-6 xl:grid-cols-[1.2fr_0.8fr]",children:[(0,t.jsxs)("div",{className:"space-y-6",children:[(0,t.jsxs)(h.GlassCard,{strong:!0,className:"p-6",children:[(0,t.jsxs)("form",{onSubmit:e=>{e.preventDefault(),b.trim()&&ec.mutate({target:b.trim(),deep:k})},children:[(0,t.jsx)("label",{className:"text-sm font-semibold text-[var(--sc-text-primary)]",children:"What do you want to scan?"}),(0,t.jsx)("input",{value:b,onChange:e=>N(e.target.value),placeholder:"Package name, file path, or directory...",className:"mt-3 w-full rounded-xl border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-4 py-3 text-sm text-[var(--sc-text-primary)] placeholder:text-[var(--sc-text-muted)] focus-ring-cyan"}),(0,t.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-3",children:[(0,t.jsxs)("button",{type:"button",onClick:()=>el.mutate("file",{onSuccess:e=>{e.path&&N(e.path)}}),className:"inline-flex items-center gap-2 rounded-xl border border-[var(--sc-border)] bg-[var(--sc-surface-interactive)] px-4 py-2.5 text-sm font-medium text-[var(--sc-text-secondary)] transition-all hover:bg-[var(--sc-surface-interactive-hover)] hover:text-[var(--sc-text-primary)]",children:[(0,t.jsx)(c,{size:14})," Browse file"]}),(0,t.jsxs)("button",{type:"button",onClick:()=>el.mutate("folder",{onSuccess:e=>{e.path&&N(e.path)}}),className:"inline-flex items-center gap-2 rounded-xl border border-[var(--sc-border)] bg-[var(--sc-surface-interactive)] px-4 py-2.5 text-sm font-medium text-[var(--sc-text-secondary)] transition-all hover:bg-[var(--sc-surface-interactive-hover)] hover:text-[var(--sc-text-primary)]",children:[(0,t.jsx)(l,{size:14})," Browse folder"]}),(0,t.jsxs)("label",{className:"inline-flex items-center gap-2 rounded-xl border border-[var(--sc-border)] bg-[var(--sc-surface-interactive)] px-3 py-2.5 text-sm text-[var(--sc-text-secondary)]",children:[(0,t.jsx)("input",{type:"checkbox",checked:k,onChange:e=>w(e.target.checked),className:"h-4 w-4 rounded border-[var(--sc-border)] accent-[var(--sc-cyan)]"}),"Deep scan",!eN?.deepScan&&(0,t.jsx)(d.Lock,{size:12,className:"text-[var(--sc-coral)]"})]}),(0,t.jsxs)(g.Button,{type:"submit",variant:"coral",glow:!0,disabled:ec.isPending||!b.trim(),children:[ec.isPending?"Scanning…":"Run Scan",(0,t.jsx)(r.ArrowRight,{size:14})]})]}),(0,t.jsx)("p",{className:"mt-3 text-xs text-[var(--sc-text-muted)]",children:"Native macOS picker via local API, or paste a path / package name directly."})]}),el.isError&&(0,t.jsx)("div",{className:"mt-3 rounded-xl border border-[var(--sc-coral)]/20 bg-[var(--sc-coral)]/5 px-4 py-3 text-sm text-[var(--sc-coral)]",children:el.error instanceof Error?el.error.message:"Failed to open native picker"}),eg&&(0,t.jsx)("div",{className:`mt-4 rounded-xl px-4 py-3 text-sm ${ey?"border border-[var(--sc-amber)]/20 bg-[var(--sc-amber)]/5 text-[var(--sc-amber)]":"border border-[var(--sc-coral)]/20 bg-[var(--sc-coral)]/5 text-[var(--sc-coral)]"}`,children:eg.message})]}),(0,t.jsxs)(h.GlassCard,{className:`p-6 ${ec.isPending?"scan-sweep":""}`,children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold text-[var(--sc-text-primary)]",children:"Scan Result"}),(0,t.jsxs)("div",{className:"flex gap-2",children:[(0,t.jsxs)(p.Badge,{variant:"muted",children:[eb.total," scans"]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:["Avg ",eb.avgScore??"—"]})]})]}),ej?(0,t.jsxs)("div",{className:"mt-5 space-y-4",children:[(0,t.jsxs)("div",{className:"flex items-start gap-6",children:[(0,t.jsx)(j,{score:ej.trustScore,size:120}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,t.jsx)("h4",{className:"min-w-0 break-words text-lg font-semibold text-[var(--sc-text-primary)]",children:ej.target}),(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(ej.riskLevel),children:ej.riskLevel})]}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap gap-2",children:[(0,t.jsxs)(p.Badge,{variant:"muted",children:[ej.filesScanned," files"]}),(0,t.jsx)(p.Badge,{variant:"muted",children:ej.deepScan?"Deep":"Standard"}),(0,t.jsx)(p.Badge,{variant:"muted",children:K(ej.scannedAt)})]})]})]}),(0,t.jsx)("div",{className:"space-y-3",children:0===ej.findings.length?(0,t.jsx)("div",{className:"rounded-xl border border-[var(--sc-cyan)]/20 bg-[var(--sc-cyan)]/5 px-4 py-4 text-sm text-[var(--sc-cyan)]",children:"No findings detected. This target looks clean."}):ej.findings.map((e,a)=>(0,t.jsxs)(h.GlassCard,{severity:e.severity,className:"p-4",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(e.severity),children:e.severity}),(0,t.jsx)(p.Badge,{variant:"muted",children:e.category})]}),(0,t.jsx)("p",{className:"mt-2 text-sm font-semibold text-[var(--sc-text-primary)]",children:e.title}),(0,t.jsx)("p",{className:"mt-1 text-sm text-[var(--sc-text-secondary)]",children:e.description}),(e.file||e.evidence)&&(0,t.jsxs)("div",{className:"mt-2 space-y-0.5 font-mono text-xs text-[var(--sc-text-muted)]",children:[e.file&&(0,t.jsxs)("div",{children:["File: ",e.line?`${e.file}:${e.line}`:e.file]}),e.evidence&&(0,t.jsxs)("div",{children:["Evidence: ",e.evidence]})]}),(0,t.jsx)(Q,{finding:{...e,id:ep[a]?.id,status:ep[a]?.status},target:ej.target}),ep[a]&&(0,t.jsx)("div",{className:"mt-3 border-t border-[var(--sc-border)] pt-3",children:(0,t.jsx)(R,{findingId:ep[a].id,status:ep[a].status,hasFile:!!e.file,compact:!0})})]},`${e.title}-${a}`))})]}):(0,t.jsx)("div",{className:"mt-5 rounded-xl bg-[var(--sc-bg-elevated)] px-5 py-8 text-center text-sm text-[var(--sc-text-muted)]",children:"Run a scan or select one from history to see results here."})]})]}),(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)(h.GlassCard,{strong:!0,className:"p-5",children:[(0,t.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-[0.18em] text-[var(--sc-text-muted)]",children:"Capabilities"}),(0,t.jsx)("div",{className:"mt-4 space-y-3",children:[{label:"Local scan",enabled:eN?.localScan??!0},{label:"Watch mode",enabled:eN?.watchMode??!0},{label:"Preinstall hook",enabled:eN?.preinstallHook??!1},{label:"npm inspection",enabled:eN?.npmInspection??!1},{label:"Deep scan",enabled:eN?.deepScan??!1}].map(e=>(0,t.jsxs)("div",{className:"flex items-center justify-between rounded-lg bg-[var(--sc-bg-elevated)] px-3 py-2",children:[(0,t.jsx)("span",{className:"text-sm text-[var(--sc-text-secondary)]",children:e.label}),(0,t.jsx)(p.Badge,{variant:e.enabled?"cyan":"muted",dot:!0,children:e.enabled?"On":"Off"})]},e.label))})]}),(0,t.jsxs)(h.GlassCard,{strong:!0,className:"p-5",children:[(0,t.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-[0.18em] text-[var(--sc-text-muted)]",children:"Quick stats"}),(0,t.jsxs)("div",{className:"mt-4 space-y-3",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between rounded-lg bg-[var(--sc-bg-elevated)] px-3 py-2",children:[(0,t.jsx)("span",{className:"text-sm text-[var(--sc-text-secondary)]",children:"Watch roots"}),(0,t.jsxs)("span",{className:"text-sm font-semibold text-[var(--sc-text-primary)]",children:[ek?.activeWatchRoots??0," active"]})]}),(0,t.jsxs)("div",{className:"flex items-center justify-between rounded-lg bg-[var(--sc-bg-elevated)] px-3 py-2",children:[(0,t.jsx)("span",{className:"text-sm text-[var(--sc-text-secondary)]",children:"Stale roots"}),(0,t.jsx)("span",{className:"text-sm font-semibold text-[var(--sc-amber)]",children:ek?.staleWatchRoots??0})]}),(0,t.jsxs)("div",{className:"flex items-center justify-between rounded-lg bg-[var(--sc-bg-elevated)] px-3 py-2",children:[(0,t.jsx)("span",{className:"text-sm text-[var(--sc-text-secondary)]",children:"Blocked events"}),(0,t.jsx)("span",{className:"text-sm font-semibold text-[var(--sc-coral)]",children:ek?.blockedEvents??0})]})]})]})]})]}),"history"===e&&(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)(h.GlassCard,{className:"p-4",children:[(0,t.jsxs)("div",{className:"grid gap-3 lg:grid-cols-[1fr_auto_auto]",children:[(0,t.jsx)("input",{value:q,onChange:e=>D(e.target.value),placeholder:"Filter by file, folder, or package...",className:"rounded-xl border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-4 py-2.5 text-sm text-[var(--sc-text-primary)] placeholder:text-[var(--sc-text-muted)] focus-ring-cyan"}),(0,t.jsxs)("select",{value:E,onChange:e=>z(e.target.value),className:"rounded-xl border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-4 py-2.5 text-sm text-[var(--sc-text-primary)]",children:[(0,t.jsx)("option",{value:"ALL",children:"All risk"}),(0,t.jsx)("option",{value:"CRITICAL",children:"Critical"}),(0,t.jsx)("option",{value:"HIGH",children:"High"}),(0,t.jsx)("option",{value:"MEDIUM",children:"Medium"}),(0,t.jsx)("option",{value:"LOW",children:"Low"}),(0,t.jsx)("option",{value:"SAFE",children:"Safe"})]}),(0,t.jsxs)("select",{value:A,onChange:e=>P(e.target.value),className:"rounded-xl border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-4 py-2.5 text-sm text-[var(--sc-text-primary)]",children:[(0,t.jsx)("option",{value:"all",children:"All targets"}),(0,t.jsx)("option",{value:"file",children:"Files"}),(0,t.jsx)("option",{value:"dir",children:"Directories"}),(0,t.jsx)("option",{value:"npm",children:"Packages"})]})]}),(0,t.jsx)("div",{className:"mt-3 flex gap-2",children:["all","true","false"].map(e=>(0,t.jsx)("button",{onClick:()=>M(e),className:`rounded-lg px-3 py-1.5 text-xs font-medium transition-all ${L===e?"bg-[var(--sc-coral)] text-white":"bg-[var(--sc-surface-interactive)] text-[var(--sc-text-muted)] hover:text-[var(--sc-text-secondary)]"}`,children:"all"===e?"All scans":"true"===e?"Deep only":"Standard only"},e))})]}),(0,t.jsxs)("div",{className:"grid gap-6 xl:grid-cols-[0.45fr_0.55fr]",children:[(0,t.jsx)("div",{className:"space-y-3",children:0===er.length?(0,t.jsx)(h.GlassCard,{className:"p-5 text-center text-sm text-[var(--sc-text-muted)]",children:"No matching scan history yet."}):er.map(e=>(0,t.jsxs)(h.GlassCard,{hover:!0,selected:ed===e.id,onClick:()=>{B(e.id),N(e.target),w(e.deepScan)},className:"p-4",children:[(0,t.jsx)("div",{className:"truncate text-sm font-semibold text-[var(--sc-text-primary)]",children:e.target}),(0,t.jsx)("div",{className:"mt-1 text-xs text-[var(--sc-text-muted)]",children:K(e.scannedAt)}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap gap-2",children:[(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(e.riskLevel),children:e.riskLevel}),(0,t.jsxs)(p.Badge,{variant:"muted",children:["Score ",e.trustScore]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[e.findingCount," findings"]})]})]},e.id))}),ej?(0,t.jsxs)(h.GlassCard,{strong:!0,className:"p-6",children:[(0,t.jsxs)("div",{className:"flex items-start gap-5",children:[(0,t.jsx)(j,{score:ej.trustScore,size:100}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("h4",{className:"break-words text-lg font-semibold text-[var(--sc-text-primary)]",children:ej.target}),(0,t.jsxs)("div",{className:"mt-2 flex flex-wrap gap-2",children:[(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(ej.riskLevel),children:ej.riskLevel}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[ej.filesScanned," files"]}),(0,t.jsx)(p.Badge,{variant:"muted",children:ej.deepScan?"Deep":"Standard"})]})]})]}),(0,t.jsx)("div",{className:"mt-5 space-y-3",children:0===ej.findings.length?(0,t.jsx)("div",{className:"rounded-xl border border-[var(--sc-cyan)]/20 bg-[var(--sc-cyan)]/5 px-4 py-3 text-sm text-[var(--sc-cyan)]",children:"Clean — no findings."}):ej.findings.map((e,a)=>(0,t.jsxs)(h.GlassCard,{severity:e.severity,className:"p-3",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(e.severity),children:e.severity}),(0,t.jsx)("span",{className:"text-sm font-medium text-[var(--sc-text-primary)]",children:e.title})]}),(0,t.jsx)("p",{className:"mt-1 text-xs text-[var(--sc-text-secondary)]",children:e.description}),(0,t.jsx)(Q,{finding:e,target:ej.target})]},`${e.title}-${a}`))})]}):(0,t.jsx)(h.GlassCard,{className:"flex items-center justify-center p-8 text-sm text-[var(--sc-text-muted)]",children:"Select a scan from the list to view details."})]})]}),"watch"===e&&(0,t.jsxs)("div",{className:"space-y-6",children:[(0,t.jsxs)(h.GlassCard,{strong:!0,className:"p-6",children:[(0,t.jsx)("h3",{className:"text-lg font-semibold text-[var(--sc-text-primary)]",children:"Start Watching"}),(0,t.jsx)("p",{className:"mt-1 text-sm text-[var(--sc-text-muted)]",children:"Monitor a directory for file changes and automatically scan for threats in real-time."}),(0,t.jsxs)("form",{className:"mt-4 flex flex-wrap items-end gap-3",onSubmit:e=>{e.preventDefault(),H.trim()&&em.mutate({target:H.trim(),deep:V})},children:[(0,t.jsx)("div",{className:"flex-1",children:(0,t.jsx)("input",{value:H,onChange:e=>O(e.target.value),placeholder:"Directory path, e.g. /Users/michael/Development/project",className:"w-full rounded-xl border border-[var(--sc-border)] bg-[var(--sc-bg-elevated)] px-4 py-3 text-sm text-[var(--sc-text-primary)] placeholder:text-[var(--sc-text-muted)] focus-ring-cyan"})}),(0,t.jsxs)("button",{type:"button",onClick:()=>el.mutate("folder",{onSuccess:e=>{e.path&&O(e.path)}}),className:"inline-flex items-center gap-2 rounded-xl border border-[var(--sc-border)] bg-[var(--sc-surface-interactive)] px-4 py-3 text-sm font-medium text-[var(--sc-text-secondary)] transition-all hover:bg-[var(--sc-surface-interactive-hover)] hover:text-[var(--sc-text-primary)]",children:[(0,t.jsx)(l,{size:14})," Browse"]}),(0,t.jsxs)("label",{className:"inline-flex items-center gap-2 rounded-xl border border-[var(--sc-border)] bg-[var(--sc-surface-interactive)] px-3 py-3 text-sm text-[var(--sc-text-secondary)]",children:[(0,t.jsx)("input",{type:"checkbox",checked:V,onChange:e=>U(e.target.checked),className:"h-4 w-4 rounded accent-[var(--sc-cyan)]"}),"Deep"]}),(0,t.jsxs)(g.Button,{type:"submit",variant:"cyan",disabled:em.isPending||!H.trim(),children:[em.isPending?"Starting…":"Start Watch",(0,t.jsx)(i.Eye,{size:14})]})]}),em.isSuccess&&(0,t.jsxs)("p",{className:"mt-3 text-sm text-[var(--sc-cyan)]",children:["Watching ",em.data.root]}),em.isError&&(0,t.jsx)("p",{className:"mt-3 text-sm text-[var(--sc-coral)]",children:em.error instanceof Error?em.error.message:"Failed to start watch"})]}),eu.length>0&&(0,t.jsxs)("div",{children:[(0,t.jsx)("h4",{className:"mb-3 text-sm font-semibold uppercase tracking-wider text-[var(--sc-text-muted)]",children:"Active Watchers (This Session)"}),(0,t.jsx)("div",{className:"grid gap-3 lg:grid-cols-2",children:eu.map(e=>(0,t.jsxs)(h.GlassCard,{className:"flex items-center justify-between p-4",children:[(0,t.jsxs)("div",{className:"min-w-0",children:[(0,t.jsx)("p",{className:"truncate text-sm font-semibold text-[var(--sc-text-primary)]",children:e.root}),(0,t.jsxs)("p",{className:"text-xs text-[var(--sc-text-muted)]",children:["PID ",e.pid]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(p.Badge,{variant:"cyan",dot:!0,pulse:!0,children:"Watching"}),(0,t.jsx)(g.Button,{variant:"outline",size:"sm",onClick:()=>ev.mutate(e.root),disabled:ev.isPending,children:"Stop"})]})]},e.root))})]}),(0,t.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,t.jsx)("h4",{className:"text-sm font-semibold uppercase tracking-wider text-[var(--sc-text-muted)]",children:"Session History"}),(0,t.jsx)("div",{className:"flex gap-2",children:["all","active","stale","ended"].map(e=>(0,t.jsx)("button",{onClick:()=>G(e),className:`rounded-lg px-3 py-1.5 text-xs font-medium capitalize transition-all ${I===e?"bg-[var(--sc-coral)] text-white":"bg-[var(--sc-surface-interactive)] text-[var(--sc-text-muted)] hover:text-[var(--sc-text-secondary)]"}`,children:e},e))})]}),0===en.length?(0,t.jsxs)(h.GlassCard,{className:"p-8 text-center text-sm text-[var(--sc-text-muted)]",children:["No watch sessions recorded yet. Start a watcher above or use ",(0,t.jsx)("code",{className:"font-mono text-[var(--sc-cyan)]",children:"shieldcortex xray --watch ./src"})," from the CLI."]}):(0,t.jsx)("div",{className:"grid gap-4 lg:grid-cols-2",children:en.map(e=>(0,t.jsxs)(h.GlassCard,{className:"p-5",children:[(0,t.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,t.jsxs)("div",{className:"min-w-0",children:[(0,t.jsx)("p",{className:"truncate text-sm font-semibold text-[var(--sc-text-primary)]",children:e.root}),(0,t.jsxs)("p",{className:"mt-1 text-xs text-[var(--sc-text-muted)]",children:["Started ",K(e.startedAt)]})]}),(0,t.jsx)(p.Badge,{variant:"active"===e.state?"cyan":"stale"===e.state?"amber":"muted",dot:!0,pulse:"active"===e.state,children:e.state})]}),(0,t.jsx)("p",{className:"mt-2 text-sm text-[var(--sc-text-secondary)]",children:e.lastEventSummary??"No detections yet"}),(0,t.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,t.jsxs)(p.Badge,{variant:"muted",children:[e.changesDetected," changes"]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[e.findingsDetected," findings"]}),(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(e.highestRiskLevel),children:e.highestRiskLevel})]})]},e.id))})]}),"activity"===e&&(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsx)("div",{className:"flex gap-2",children:["all","scan","watch","preinstall"].map(e=>(0,t.jsx)("button",{onClick:()=>W(e),className:`rounded-lg px-3 py-1.5 text-xs font-medium capitalize transition-all ${T===e?"bg-[var(--sc-coral)] text-white":"bg-[var(--sc-surface-interactive)] text-[var(--sc-text-muted)] hover:text-[var(--sc-text-secondary)]"}`,children:"all"===e?"All activity":e},e))}),0===ei.length?(0,t.jsx)(h.GlassCard,{className:"p-8 text-center text-sm text-[var(--sc-text-muted)]",children:"No matching automatic events yet."}):(0,t.jsx)("div",{className:"space-y-3",children:ei.map(e=>(0,t.jsx)(h.GlassCard,{className:"p-4",children:(0,t.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(o,{size:14,className:"shrink-0 text-[var(--sc-coral)]"}),(0,t.jsx)("span",{className:"text-sm font-semibold capitalize text-[var(--sc-text-primary)]",children:e.kind})]}),(0,t.jsx)("p",{className:"mt-1 truncate text-sm text-[var(--sc-text-secondary)]",children:e.target}),(0,t.jsx)("p",{className:"mt-1 text-xs text-[var(--sc-text-muted)]",children:e.summary})]}),(0,t.jsx)(p.Badge,{variant:"pass"===e.status?"safe":"blocked"===e.status?"critical":"warn"===e.status?"medium":"amber",children:e.status})]})},e.id))})]}),"findings"===e&&(0,t.jsxs)("div",{className:"space-y-4",children:[ea&&(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,t.jsxs)(p.Badge,{variant:"coral",children:[ea.new," new"]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[ea.reviewed," reviewed"]}),(0,t.jsxs)(p.Badge,{variant:"cyan",children:[ea.resolved," resolved"]}),(0,t.jsxs)(p.Badge,{variant:"amber",children:[ea.quarantined," quarantined"]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[ea.ignored," ignored"]}),(0,t.jsxs)(p.Badge,{variant:"muted",children:[ea.total," total"]})]}),(0,t.jsx)("div",{className:"flex flex-wrap gap-2",children:[{key:"new",label:"Needs attention",accent:!0},{key:"reviewed",label:"Reviewed",accent:!1},{key:"resolved",label:"Resolved",accent:!1},{key:"ignored",label:"Ignored",accent:!1},{key:"quarantined",label:"Quarantined",accent:!1},{key:"all",label:"Everything",accent:!1}].map(({key:e,label:a,accent:s})=>(0,t.jsxs)("button",{onClick:()=>J(e),className:`rounded-lg px-3 py-1.5 text-xs font-medium transition-all ${_===e?s?"bg-[var(--sc-coral)] text-white":"bg-[var(--sc-cyan)] text-[var(--sc-bg-deep)]":"bg-[var(--sc-surface-interactive)] text-[var(--sc-text-muted)] hover:text-[var(--sc-text-secondary)]"}`,children:[a,"new"===e&&ea&&ea.new>0&&(0,t.jsx)("span",{className:"ml-1.5 rounded-full bg-white/20 px-1.5 py-0.5 text-[10px] font-bold",children:ea.new})]},e))}),es?.findings&&0!==es.findings.length?(0,t.jsx)("div",{className:"space-y-3",children:es.findings.map(e=>(0,t.jsxs)(h.GlassCard,{severity:e.severity,className:"p-5",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsx)(p.Badge,{variant:(0,p.riskVariant)(e.severity),children:e.severity}),(0,t.jsx)(p.Badge,{variant:"muted",children:e.category}),e.systemFile&&(0,t.jsx)(p.Badge,{variant:"muted",children:"System file — likely safe"}),e.guidance?.urgency==="usually-safe"&&!e.systemFile&&(0,t.jsx)(p.Badge,{variant:"cyan",children:"Usually safe"}),e.guidance?.urgency==="act-now"&&(0,t.jsx)(p.Badge,{variant:"critical",dot:!0,pulse:!0,children:"Act now"})]}),(0,t.jsx)("p",{className:"mt-3 text-sm font-semibold text-[var(--sc-text-primary)]",children:e.title}),e.guidance&&(0,t.jsxs)("div",{className:"mt-3 space-y-3 rounded-xl bg-[var(--sc-bg-elevated)] p-4",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-[11px] font-semibold uppercase tracking-wider text-[var(--sc-text-muted)]",children:"What this means"}),(0,t.jsx)("p",{className:"mt-1 text-sm leading-relaxed text-[var(--sc-text-secondary)]",children:e.guidance.whatItMeans})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-[11px] font-semibold uppercase tracking-wider text-[var(--sc-cyan)]",children:"What to do"}),(0,t.jsx)("p",{className:"mt-1 text-sm leading-relaxed text-[var(--sc-text-secondary)]",children:e.guidance.whatToDo})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-[11px] font-semibold uppercase tracking-wider text-[var(--sc-text-muted)]",children:"False positive?"}),(0,t.jsx)("p",{className:"mt-1 text-xs leading-relaxed text-[var(--sc-text-muted)]",children:e.guidance.falsePositiveNote})]})]}),(e.file||e.evidence)&&(0,t.jsxs)("div",{className:"mt-3 space-y-0.5 font-mono text-xs text-[var(--sc-text-muted)]",children:[e.file&&(0,t.jsxs)("div",{children:["File: ",e.line?`${e.file}:${e.line}`:e.file]}),e.evidence&&(0,t.jsxs)("div",{children:["Evidence: ",e.evidence]})]}),(0,t.jsx)(Q,{finding:e}),(0,t.jsx)("div",{className:"mt-2 text-xs text-[var(--sc-text-muted)]",children:K(e.detectedAt)}),(0,t.jsx)("div",{className:"mt-3 border-t border-[var(--sc-border)] pt-3",children:(0,t.jsx)(R,{findingId:e.id,status:e.status,hasFile:!!e.file,compact:!0})})]},e.id))}):(0,t.jsxs)(h.GlassCard,{className:"p-8 text-center",children:[(0,t.jsx)("p",{className:"text-sm text-[var(--sc-text-primary)]",children:"new"===_?"All clear — no findings need attention":`No ${"all"===_?"":_+" "}findings`}),(0,t.jsx)("p",{className:"mt-1 text-xs text-[var(--sc-text-muted)]",children:"new"===_?"Run an X-Ray scan or start a watcher to monitor for threats.":"Findings move here when you take action on them."})]})]})]})})}e.s(["XRayOverview",()=>O],27918)}]);
|
package/dist/api/events.js
CHANGED
|
@@ -41,6 +41,8 @@ export function emitMemoryUpdated(memory) {
|
|
|
41
41
|
memoryEvents.emit('memory_updated', { memory });
|
|
42
42
|
}
|
|
43
43
|
export function emitMemoryDeleted(memoryId, title) {
|
|
44
|
+
// The bare `title` is masked centrally when broadcast (deepRedactRestrictedContent
|
|
45
|
+
// scrubs every title-keyed string), so no per-emit redaction is needed here.
|
|
44
46
|
memoryEvents.emit('memory_deleted', { memoryId, title });
|
|
45
47
|
}
|
|
46
48
|
export function emitConsolidation(result, promotedMemories = [], deletedMemories = []) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Express middleware: deep-redact RESTRICTED (credential-class) memory content
|
|
4
|
+
* from every JSON response the visualization API sends.
|
|
5
|
+
*
|
|
6
|
+
* The dashboard renders in a BROWSER, so a raw credential reaching the DOM is a
|
|
7
|
+
* leak vector (screenshots, screen-shares, disk cache). Memories surface at many
|
|
8
|
+
* nesting depths across the API (`{ memories: [...] }`, recall `results[].memory`,
|
|
9
|
+
* openclaw `sessions[].memories[]`, review-queue `sections.stale[]`,
|
|
10
|
+
* `contradictions[].memoryA`), so a single response interceptor that walks the
|
|
11
|
+
* whole tree is the only way to guarantee none is missed. The row itself stays
|
|
12
|
+
* intact (title/metadata) so the owner can still see/manage it; full content
|
|
13
|
+
* remains available via the CLI, which is not a browser surface.
|
|
14
|
+
*/
|
|
15
|
+
export declare function redactRestrictedResponses(_req: Request, res: Response, next: NextFunction): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { deepRedactRestrictedContent } from '../defence/trust/read-guard.js';
|
|
2
|
+
/**
|
|
3
|
+
* Express middleware: deep-redact RESTRICTED (credential-class) memory content
|
|
4
|
+
* from every JSON response the visualization API sends.
|
|
5
|
+
*
|
|
6
|
+
* The dashboard renders in a BROWSER, so a raw credential reaching the DOM is a
|
|
7
|
+
* leak vector (screenshots, screen-shares, disk cache). Memories surface at many
|
|
8
|
+
* nesting depths across the API (`{ memories: [...] }`, recall `results[].memory`,
|
|
9
|
+
* openclaw `sessions[].memories[]`, review-queue `sections.stale[]`,
|
|
10
|
+
* `contradictions[].memoryA`), so a single response interceptor that walks the
|
|
11
|
+
* whole tree is the only way to guarantee none is missed. The row itself stays
|
|
12
|
+
* intact (title/metadata) so the owner can still see/manage it; full content
|
|
13
|
+
* remains available via the CLI, which is not a browser surface.
|
|
14
|
+
*/
|
|
15
|
+
export function redactRestrictedResponses(_req, res, next) {
|
|
16
|
+
const originalJson = res.json.bind(res);
|
|
17
|
+
res.json = ((body) => originalJson(deepRedactRestrictedContent(body)));
|
|
18
|
+
next();
|
|
19
|
+
}
|
|
@@ -1,13 +1,40 @@
|
|
|
1
1
|
import { homedir } from 'os';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { existsSync, readdirSync, readFileSync } from 'fs';
|
|
4
|
-
import { getDatabase } from '../../database/init.js';
|
|
4
|
+
import { getDatabase, withTransaction } from '../../database/init.js';
|
|
5
5
|
import { searchMemories, getRecentMemories, getHighPriorityMemories, countMemories, countHighPriorityMemories, getMemoryStats, getMemoryById, addMemory, deleteMemory, accessMemory, updateMemory, mergeMemories, promoteMemory, createMemoryLink, rowToMemory, enrichMemory, } from '../../memory/store.js';
|
|
6
6
|
import { calculateDecayedScore } from '../../memory/decay.js';
|
|
7
7
|
import { consolidate, findDuplicateMemoryPairs, formatContextSummary, generateContextSummary, } from '../../memory/consolidate.js';
|
|
8
8
|
import { getActivationStats, getActiveMemories } from '../../memory/activation.js';
|
|
9
9
|
import { detectContradictions, getContradictionsFor } from '../../memory/contradiction.js';
|
|
10
10
|
import { emitConsolidation } from '../events.js';
|
|
11
|
+
import { guardDashboardContextSummary, RESTRICTED_CONTENT_PLACEHOLDER } from '../../defence/trust/read-guard.js';
|
|
12
|
+
/** Upper bound on memories a single bulk-review call may touch (actions are reversible). */
|
|
13
|
+
const MAX_BULK_REVIEW = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a review action keyword into the `updateMemory` field updates. Shared
|
|
16
|
+
* by the single PATCH /api/memories/:id/review route and the bulk endpoint so the
|
|
17
|
+
* action vocabulary lives in one place. Returns null for an unknown action.
|
|
18
|
+
*/
|
|
19
|
+
function buildReviewUpdates(action, opts) {
|
|
20
|
+
const reviewActor = typeof opts.reviewedBy === 'string' && opts.reviewedBy.trim() ? opts.reviewedBy.trim() : 'dashboard';
|
|
21
|
+
const map = {
|
|
22
|
+
archive: { status: 'archived', reviewedBy: reviewActor },
|
|
23
|
+
suppress: { status: 'suppressed', reviewedBy: reviewActor },
|
|
24
|
+
restore: { status: 'active', reviewedBy: reviewActor },
|
|
25
|
+
pin: { pinned: true, reviewedBy: reviewActor },
|
|
26
|
+
unpin: { pinned: false, reviewedBy: reviewActor },
|
|
27
|
+
canonicalize: { status: 'canonical', pinned: true, reviewedBy: reviewActor },
|
|
28
|
+
excludeCloud: { cloudExcluded: true, reviewedBy: reviewActor },
|
|
29
|
+
includeCloud: { cloudExcluded: false, reviewedBy: reviewActor },
|
|
30
|
+
rescopeProject: { scope: 'project', project: opts.project ?? null, reviewedBy: reviewActor },
|
|
31
|
+
rescopeGlobal: { scope: 'global', project: null, reviewedBy: reviewActor },
|
|
32
|
+
};
|
|
33
|
+
const updates = map[action];
|
|
34
|
+
if (!updates)
|
|
35
|
+
return null;
|
|
36
|
+
return { ...updates, ...(opts.scope ? { scope: opts.scope } : {}) };
|
|
37
|
+
}
|
|
11
38
|
export function registerMemoryRoutes(app, deps) {
|
|
12
39
|
const { requireNotLocked, requireIronDomeAction } = deps;
|
|
13
40
|
function deriveLocalOpenClawSessionId(memory) {
|
|
@@ -251,6 +278,10 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
251
278
|
total = countMemories(project, filters);
|
|
252
279
|
}
|
|
253
280
|
const hasMore = offset + limit < total;
|
|
281
|
+
// RESTRICTED content is redacted globally by the response interceptor; no
|
|
282
|
+
// per-row dropping here (the dashboard is a management surface — low-trust
|
|
283
|
+
// rows must stay visible to be triaged, and dropping post-slice would also
|
|
284
|
+
// desync total/hasMore).
|
|
254
285
|
const paginatedMemories = memories.slice(offset, offset + limit);
|
|
255
286
|
// Batch-load entity_ids per memory so the constellation graph client
|
|
256
287
|
// can map list rows to graph nodes without an N+1 fetch.
|
|
@@ -963,7 +994,10 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
963
994
|
app.get('/api/context', requireNotLocked, async (req, res) => {
|
|
964
995
|
try {
|
|
965
996
|
const project = typeof req.query.project === 'string' ? req.query.project : undefined;
|
|
966
|
-
|
|
997
|
+
// Redact RESTRICTED content BEFORE formatting — the `formatted` string bakes
|
|
998
|
+
// content in, so the response interceptor (which only walks structured JSON)
|
|
999
|
+
// cannot reach it. Guarding the summary first covers both fields.
|
|
1000
|
+
const summary = guardDashboardContextSummary(await generateContextSummary(project));
|
|
967
1001
|
res.json({
|
|
968
1002
|
summary,
|
|
969
1003
|
formatted: formatContextSummary(summary),
|
|
@@ -1151,7 +1185,11 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
1151
1185
|
const updates = {};
|
|
1152
1186
|
if (title !== undefined)
|
|
1153
1187
|
updates.title = title.trim();
|
|
1154
|
-
|
|
1188
|
+
// Never persist the redaction placeholder as real content. RESTRICTED content
|
|
1189
|
+
// is withheld from the browser, so a dashboard edit form can only echo the
|
|
1190
|
+
// placeholder back — writing it would silently destroy the real secret. Drop
|
|
1191
|
+
// a content update that is exactly the placeholder (true edits are unaffected).
|
|
1192
|
+
if (content !== undefined && content !== RESTRICTED_CONTENT_PLACEHOLDER)
|
|
1155
1193
|
updates.content = content;
|
|
1156
1194
|
if (category !== undefined)
|
|
1157
1195
|
updates.category = category;
|
|
@@ -1193,26 +1231,10 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
1193
1231
|
if (Number.isNaN(id)) {
|
|
1194
1232
|
return res.status(400).json({ error: 'Invalid memory ID' });
|
|
1195
1233
|
}
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
archive: { status: 'archived', reviewedBy: reviewActor },
|
|
1199
|
-
suppress: { status: 'suppressed', reviewedBy: reviewActor },
|
|
1200
|
-
restore: { status: 'active', reviewedBy: reviewActor },
|
|
1201
|
-
pin: { pinned: true, reviewedBy: reviewActor },
|
|
1202
|
-
unpin: { pinned: false, reviewedBy: reviewActor },
|
|
1203
|
-
canonicalize: { status: 'canonical', pinned: true, reviewedBy: reviewActor },
|
|
1204
|
-
excludeCloud: { cloudExcluded: true, reviewedBy: reviewActor },
|
|
1205
|
-
includeCloud: { cloudExcluded: false, reviewedBy: reviewActor },
|
|
1206
|
-
rescopeProject: { scope: 'project', project: project ?? null, reviewedBy: reviewActor },
|
|
1207
|
-
rescopeGlobal: { scope: 'global', project: null, reviewedBy: reviewActor },
|
|
1208
|
-
};
|
|
1209
|
-
if (!action || !actionMap[action]) {
|
|
1234
|
+
const updates = buildReviewUpdates(action ?? '', { reviewedBy, project, scope });
|
|
1235
|
+
if (!updates) {
|
|
1210
1236
|
return res.status(400).json({ error: 'Unsupported review action' });
|
|
1211
1237
|
}
|
|
1212
|
-
const updates = {
|
|
1213
|
-
...actionMap[action],
|
|
1214
|
-
...(scope ? { scope } : {}),
|
|
1215
|
-
};
|
|
1216
1238
|
const updated = updateMemory(id, updates);
|
|
1217
1239
|
if (!updated) {
|
|
1218
1240
|
return res.status(404).json({ error: 'Memory not found' });
|
|
@@ -1223,6 +1245,49 @@ export function registerMemoryRoutes(app, deps) {
|
|
|
1223
1245
|
res.status(500).json({ error: error.message });
|
|
1224
1246
|
}
|
|
1225
1247
|
});
|
|
1248
|
+
// Bulk review: apply one reversible review action to many memories at once, so
|
|
1249
|
+
// the dashboard's large triage queues (Never Used, Noisy Auto, …) can be cleared
|
|
1250
|
+
// without one round-trip per card. Mirrors the quarantine bulk-approve pattern.
|
|
1251
|
+
// Reversible actions only (archive/suppress/restore/pin/…) — there is no bulk
|
|
1252
|
+
// delete here. Best-effort with a per-row failure list; capped at MAX_BULK_REVIEW.
|
|
1253
|
+
app.post('/api/memories/review/bulk', requireNotLocked, requireIronDomeAction({
|
|
1254
|
+
action: 'modify_records',
|
|
1255
|
+
channel: 'dashboard',
|
|
1256
|
+
sourceIdentifier: 'dashboard:memory-review-bulk',
|
|
1257
|
+
enforceAmber: true,
|
|
1258
|
+
}), (req, res) => {
|
|
1259
|
+
try {
|
|
1260
|
+
const { ids, action, reviewedBy, project, scope } = req.body;
|
|
1261
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
1262
|
+
return res.status(400).json({ error: 'ids must be a non-empty array' });
|
|
1263
|
+
}
|
|
1264
|
+
const numericIds = Array.from(new Set(ids.filter((x) => Number.isInteger(x))));
|
|
1265
|
+
if (numericIds.length === 0) {
|
|
1266
|
+
return res.status(400).json({ error: 'ids must contain integers' });
|
|
1267
|
+
}
|
|
1268
|
+
if (numericIds.length > MAX_BULK_REVIEW) {
|
|
1269
|
+
return res.status(400).json({ error: `Too many ids (max ${MAX_BULK_REVIEW}) — narrow the selection.` });
|
|
1270
|
+
}
|
|
1271
|
+
const updates = buildReviewUpdates(action ?? '', { reviewedBy, project, scope });
|
|
1272
|
+
if (!updates) {
|
|
1273
|
+
return res.status(400).json({ error: 'Unsupported review action' });
|
|
1274
|
+
}
|
|
1275
|
+
let updated = 0;
|
|
1276
|
+
const failed = [];
|
|
1277
|
+
withTransaction(() => {
|
|
1278
|
+
for (const id of numericIds) {
|
|
1279
|
+
if (updateMemory(id, updates))
|
|
1280
|
+
updated += 1;
|
|
1281
|
+
else
|
|
1282
|
+
failed.push(id);
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1285
|
+
res.json({ success: true, updated, total: numericIds.length, failed });
|
|
1286
|
+
}
|
|
1287
|
+
catch (error) {
|
|
1288
|
+
res.status(500).json({ error: error.message });
|
|
1289
|
+
}
|
|
1290
|
+
});
|
|
1226
1291
|
app.post('/api/memories/:id/quarantine', requireNotLocked, requireIronDomeAction({
|
|
1227
1292
|
action: 'modify_records',
|
|
1228
1293
|
channel: 'dashboard',
|
|
@@ -16,6 +16,8 @@ import { getDatabase, initDatabase, checkpointWal } from '../database/init.js';
|
|
|
16
16
|
import { DEFAULT_CONFIG } from '../memory/types.js';
|
|
17
17
|
import { getRecentMemories, getMemoryStats, rowToMemory, updateDecayScores } from '../memory/store.js';
|
|
18
18
|
import { calculateDecayedScore } from '../memory/decay.js';
|
|
19
|
+
import { deepRedactRestrictedContent, redactRestrictedForDisplay } from '../defence/trust/read-guard.js';
|
|
20
|
+
import { redactRestrictedResponses } from './redact-response.js';
|
|
19
21
|
import { memoryEvents, emitDecayTick, getUnprocessedEvents, markEventsProcessed, cleanupOldEvents, } from './events.js';
|
|
20
22
|
import { BrainWorker } from '../worker/brain-worker.js';
|
|
21
23
|
import { isKillSwitchActive, getKillSwitchMeta, activateKillSwitch, deactivateKillSwitch } from './control.js';
|
|
@@ -300,6 +302,11 @@ export function startVisualizationServer(dbPath) {
|
|
|
300
302
|
}
|
|
301
303
|
next();
|
|
302
304
|
});
|
|
305
|
+
// ── RESTRICTED content redaction ────────────────────────
|
|
306
|
+
// Deep-redact RESTRICTED (credential-class) memory content from every JSON
|
|
307
|
+
// response — the dashboard is a browser surface, so the secret must never reach
|
|
308
|
+
// the DOM. The row stays visible so the owner can manage it. See the middleware.
|
|
309
|
+
app.use(redactRestrictedResponses);
|
|
303
310
|
// Token handshake — dashboard claims on load (survives page refresh)
|
|
304
311
|
app.get('/api/auth/session-token', (_req, res) => {
|
|
305
312
|
const token = getSessionToken();
|
|
@@ -778,9 +785,11 @@ export function startVisualizationServer(dbPath) {
|
|
|
778
785
|
ws.on('pong', () => { ws.isAlive = true; });
|
|
779
786
|
clients.add(ws);
|
|
780
787
|
console.log(`[WS] Client connected. Total: ${clients.size}`);
|
|
781
|
-
// Send initial state
|
|
788
|
+
// Send initial state. The WS feed renders in the same browser surface as the
|
|
789
|
+
// REST API but does not pass through the res.json interceptor, so redact
|
|
790
|
+
// RESTRICTED content here explicitly.
|
|
782
791
|
const stats = getMemoryStats();
|
|
783
|
-
const memories = getRecentMemories(100);
|
|
792
|
+
const memories = redactRestrictedForDisplay(getRecentMemories(100));
|
|
784
793
|
const memoriesWithDecay = memories.map(m => ({
|
|
785
794
|
...m,
|
|
786
795
|
decayedScore: calculateDecayedScore(m),
|
|
@@ -811,9 +820,11 @@ export function startVisualizationServer(dbPath) {
|
|
|
811
820
|
catch { /* already closing */ }
|
|
812
821
|
});
|
|
813
822
|
});
|
|
814
|
-
// Broadcast events to all connected clients
|
|
823
|
+
// Broadcast events to all connected clients. memory_created/updated/accessed
|
|
824
|
+
// events carry the full memory in `data.memory`, so redact RESTRICTED content
|
|
825
|
+
// before it leaves over the WS (mirrors the REST response interceptor).
|
|
815
826
|
function broadcast(event) {
|
|
816
|
-
const message = JSON.stringify(event);
|
|
827
|
+
const message = JSON.stringify(deepRedactRestrictedContent(event));
|
|
817
828
|
for (const client of clients) {
|
|
818
829
|
try {
|
|
819
830
|
if (client.readyState === WebSocket.OPEN) {
|
package/dist/cloud/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCloudConfig, setCloudConfig, getCloudSyncControls, setCloudSyncControls, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, getToolResponseScanConfig, setToolResponseScanConfig, } from './config.js';
|
|
1
|
+
import { getCloudConfig, setCloudConfig, getCloudSyncControls, setCloudSyncControls, getDefenceMode, setDefenceMode, getVerifyConfig, setVerifyConfig, getReviewCopilotConfig, getOpenClawAutoMemory, setOpenClawAutoMemory, isProactiveRecallEnabled, setProactiveRecall, restore410Defaults, getRankerConfig, setRankerConfig, getToolResponseScanConfig, setToolResponseScanConfig, isRevokeBySourceEnabled, setRevokeBySourceEnabled, } 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';
|
|
@@ -22,6 +22,7 @@ export function handleCloudConfig(args) {
|
|
|
22
22
|
console.log('\nShieldCortex Configuration:');
|
|
23
23
|
console.log(` Defence Mode: ${mode}`);
|
|
24
24
|
console.log(` Tool-Output Firewall: ${toolFirewall.scanToolResponses ? toolFirewall.toolResponseMode : 'Off'}`);
|
|
25
|
+
console.log(` Revoke-by-source: ${isRevokeBySourceEnabled() ? 'Enabled (destructive)' : 'Disabled (default)'}`);
|
|
25
26
|
console.log(` Cloud Enabled: ${config.cloudEnabled ? 'Yes' : 'No'}`);
|
|
26
27
|
console.log(` API Key: ${config.cloudApiKey ? config.cloudApiKey.substring(0, 12) + '...' : 'Not set'}`);
|
|
27
28
|
console.log(` Base URL: ${config.cloudBaseUrl}`);
|
|
@@ -210,6 +211,16 @@ export function handleCloudConfig(args) {
|
|
|
210
211
|
console.log('Tool-output firewall enabled (scanning on).');
|
|
211
212
|
changed = true;
|
|
212
213
|
}
|
|
214
|
+
if (args.includes('--allow-revoke-by-source')) {
|
|
215
|
+
setRevokeBySourceEnabled(true);
|
|
216
|
+
console.log('Revoke-by-source ENABLED. `forget --fromSource` can now bulk-delete a source\'s memories (trust-hierarchy ACL still applies). Disable again with --disallow-revoke-by-source when done.');
|
|
217
|
+
changed = true;
|
|
218
|
+
}
|
|
219
|
+
if (args.includes('--disallow-revoke-by-source')) {
|
|
220
|
+
setRevokeBySourceEnabled(false);
|
|
221
|
+
console.log('Revoke-by-source disabled (default).');
|
|
222
|
+
changed = true;
|
|
223
|
+
}
|
|
213
224
|
if (args.includes('--upsell-mute')) {
|
|
214
225
|
setUpsellState({ proMuted: true });
|
|
215
226
|
console.log('Pro upsell muted. Re-enable with --upsell-unmute.');
|
|
@@ -238,6 +249,7 @@ export function handleCloudConfig(args) {
|
|
|
238
249
|
console.log(' --tool-firewall-enforce Redact/withhold threatening tool output before the agent sees it');
|
|
239
250
|
console.log(' --tool-firewall-advisory Log tool-output threats but deliver intact (default)');
|
|
240
251
|
console.log(' --tool-firewall-off / --tool-firewall-on Disable / enable tool-output scanning');
|
|
252
|
+
console.log(' --allow-revoke-by-source / --disallow-revoke-by-source Enable/disable destructive forget --fromSource (default: disabled)');
|
|
241
253
|
console.log(' --restore-4.10-defaults Restore pre-v4.11.0 defaults (recall on, strict interceptor, minimal preamble)');
|
|
242
254
|
console.log(' --upsell-mute Suppress the Pro upsell footer in doctor');
|
|
243
255
|
console.log(' --upsell-unmute Allow the Pro upsell footer to surface again');
|
package/dist/cloud/config.d.ts
CHANGED
|
@@ -191,6 +191,16 @@ export declare function getToolResponseScanConfig(): ToolResponseScanConfig;
|
|
|
191
191
|
* Persists tool response scanning config.
|
|
192
192
|
*/
|
|
193
193
|
export declare function setToolResponseScanConfig(updates: Partial<ToolResponseScanConfig>): void;
|
|
194
|
+
/**
|
|
195
|
+
* revoke-by-source (bulk delete all memories from a source) is a destructive
|
|
196
|
+
* mass-delete primitive. Because a prompt-injection adversary runs AS the agent
|
|
197
|
+
* at the agent's own trust, no in-band (trust) check can distinguish "the human
|
|
198
|
+
* asked" from "an injection asked". So it is gated OFF by default and can only
|
|
199
|
+
* be enabled by an out-of-band human action (editing config / the CLI flag) that
|
|
200
|
+
* a hijacked agent cannot perform.
|
|
201
|
+
*/
|
|
202
|
+
export declare function isRevokeBySourceEnabled(): boolean;
|
|
203
|
+
export declare function setRevokeBySourceEnabled(enabled: boolean): void;
|
|
194
204
|
/**
|
|
195
205
|
* Returns a stable UUID for this machine.
|
|
196
206
|
* Generates and persists on first call; reads from config thereafter.
|
package/dist/cloud/config.js
CHANGED
|
@@ -938,6 +938,21 @@ export function setToolResponseScanConfig(updates) {
|
|
|
938
938
|
raw.toolResponseMode = updates.toolResponseMode;
|
|
939
939
|
});
|
|
940
940
|
}
|
|
941
|
+
// ── Revoke-by-source gate ─────────────────────────────
|
|
942
|
+
/**
|
|
943
|
+
* revoke-by-source (bulk delete all memories from a source) is a destructive
|
|
944
|
+
* mass-delete primitive. Because a prompt-injection adversary runs AS the agent
|
|
945
|
+
* at the agent's own trust, no in-band (trust) check can distinguish "the human
|
|
946
|
+
* asked" from "an injection asked". So it is gated OFF by default and can only
|
|
947
|
+
* be enabled by an out-of-band human action (editing config / the CLI flag) that
|
|
948
|
+
* a hijacked agent cannot perform.
|
|
949
|
+
*/
|
|
950
|
+
export function isRevokeBySourceEnabled() {
|
|
951
|
+
return readRawConfig().allowRevokeBySource === true;
|
|
952
|
+
}
|
|
953
|
+
export function setRevokeBySourceEnabled(enabled) {
|
|
954
|
+
mutateRawConfig((raw) => { raw.allowRevokeBySource = enabled; });
|
|
955
|
+
}
|
|
941
956
|
// ── Device Identity ────────────────────────────────────
|
|
942
957
|
/**
|
|
943
958
|
* Returns a stable UUID for this machine.
|
|
@@ -21,7 +21,7 @@ export interface AgentTimelinePoint {
|
|
|
21
21
|
export interface AuditQueryOptions {
|
|
22
22
|
startTime?: string;
|
|
23
23
|
endTime?: string;
|
|
24
|
-
operation?: 'write' | 'read' | 'delete' | 'update';
|
|
24
|
+
operation?: 'write' | 'read' | 'delete' | 'update' | 'revoke';
|
|
25
25
|
source?: string;
|
|
26
26
|
firewallResult?: FirewallResult;
|
|
27
27
|
memoryId?: number;
|
|
@@ -22,7 +22,4 @@ export interface AccessCheckMemory {
|
|
|
22
22
|
source?: string | null;
|
|
23
23
|
sensitivity_level?: string | null;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
* Check whether a source has access to a memory for a given operation.
|
|
27
|
-
*/
|
|
28
|
-
export declare function checkAccess(memory: AccessCheckMemory, source: DefenceSource, operation: 'read' | 'write' | 'delete'): AccessPolicy;
|
|
25
|
+
export declare function checkAccess(memory: AccessCheckMemory, source: DefenceSource, operation: 'read' | 'write' | 'delete' | 'revoke'): AccessPolicy;
|
|
@@ -12,6 +12,13 @@ import { scoreSource } from './source-scorer.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* Check whether a source has access to a memory for a given operation.
|
|
14
14
|
*/
|
|
15
|
+
/** Parse a stored "type:identifier" source string back into a DefenceSource. */
|
|
16
|
+
function parseStoredSource(stored) {
|
|
17
|
+
const i = stored.indexOf(':');
|
|
18
|
+
if (i === -1)
|
|
19
|
+
return { type: 'agent', identifier: stored }; // unknown shape → low-trust agent
|
|
20
|
+
return { type: stored.slice(0, i), identifier: stored.slice(i + 1) };
|
|
21
|
+
}
|
|
15
22
|
export function checkAccess(memory, source, operation) {
|
|
16
23
|
const trust = scoreSource(source).score;
|
|
17
24
|
const memorySource = memory.source || '__system:unattributed';
|
|
@@ -50,6 +57,31 @@ export function checkAccess(memory, source, operation) {
|
|
|
50
57
|
}
|
|
51
58
|
return deny('Can only delete own memories (trust ≥0.5)');
|
|
52
59
|
}
|
|
60
|
+
if (operation === 'revoke') {
|
|
61
|
+
// Trust-hierarchy revoke (revoke-by-source remediation): own cleanup, OR a
|
|
62
|
+
// high-trust caller may purge a STRICTLY lower-trust source's memories.
|
|
63
|
+
// Equal/higher-trust targets are protected, so a 0.9 agent can never revoke
|
|
64
|
+
// user:direct (1.0). Single-row 'delete' stays own-only — this override is
|
|
65
|
+
// reachable only through the explicit revoke path.
|
|
66
|
+
if (isOwner && trust >= 0.5) {
|
|
67
|
+
return { canRead: true, canWrite: false, canDelete: true, writeRequiresQuarantine: false, reason: 'Owner revoke' };
|
|
68
|
+
}
|
|
69
|
+
// Fail-safe: never mass-revoke unattributed / unclassifiable memories. They
|
|
70
|
+
// have no clear owner to outrank, and a 0-trust target would be outranked by
|
|
71
|
+
// any caller — so a high-trust caller must NOT be able to sweep null-source
|
|
72
|
+
// rows by source.
|
|
73
|
+
if (!memory.source || memorySource === '__system:unattributed') {
|
|
74
|
+
return deny('Revoke denied: unattributed memories cannot be revoked by source');
|
|
75
|
+
}
|
|
76
|
+
const targetTrust = scoreSource(parseStoredSource(memorySource)).score;
|
|
77
|
+
if (targetTrust > 0 && trust >= 0.7 && trust > targetTrust) {
|
|
78
|
+
return {
|
|
79
|
+
canRead: true, canWrite: false, canDelete: true, writeRequiresQuarantine: false,
|
|
80
|
+
reason: `Trust-hierarchy revoke (caller ${trust.toFixed(2)} > target ${targetTrust.toFixed(2)})`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return deny('Revoke denied: must own the source or outrank it (trust ≥0.7 and strictly > a known target source trust)');
|
|
84
|
+
}
|
|
53
85
|
return deny('Unknown operation');
|
|
54
86
|
}
|
|
55
87
|
function allow(reason) {
|
|
@@ -43,3 +43,45 @@ export declare function guardReadBySensitivity(memories: Memory[]): Memory[];
|
|
|
43
43
|
export declare function guardContextSummary(summary: ContextSummary): ContextSummary;
|
|
44
44
|
/** Guard a single memory; returns null if the caller may not read it. */
|
|
45
45
|
export declare function guardReadMemory(memory: Memory | null | undefined, source: DefenceSource | undefined): Memory | null;
|
|
46
|
+
/**
|
|
47
|
+
* Dashboard / HTTP visualization-API read guard.
|
|
48
|
+
*
|
|
49
|
+
* The dashboard is the OWNER's surface, but it renders in a BROWSER — so raw
|
|
50
|
+
* RESTRICTED (credential-class) content there is a leak vector (screenshots,
|
|
51
|
+
* screen-shares, the browser's disk cache). Policy (REDACT, don't drop):
|
|
52
|
+
*
|
|
53
|
+
* - RESTRICTED rows are KEPT (so the owner sees the memory exists and can
|
|
54
|
+
* review/delete it) but their `content` is replaced with a placeholder;
|
|
55
|
+
* - because sensitivity is classified on TITLE + CONTENT together, a secret can
|
|
56
|
+
* also live in the title or metadata — so credential SPANS in those fields are
|
|
57
|
+
* masked too (a benign label like "AWS deploy key" is left intact);
|
|
58
|
+
* - low-trust / trust-0 rows are NOT dropped: the dashboard is a management
|
|
59
|
+
* surface (its Review queue exists to triage exactly these), so the owner must
|
|
60
|
+
* see them. Only RESTRICTED *content* is withheld, never whole rows.
|
|
61
|
+
*
|
|
62
|
+
* RESTRICTED full content remains available via the CLI (`recall`/`get_memory`),
|
|
63
|
+
* which is not a browser-render surface. Dropping quarantined rows is the MCP
|
|
64
|
+
* read-boundary's job (a subagent caller), not the owner's dashboard.
|
|
65
|
+
*/
|
|
66
|
+
export declare const RESTRICTED_CONTENT_PLACEHOLDER = "\uD83D\uDD12 [RESTRICTED content withheld \u2014 view via CLI]";
|
|
67
|
+
/** Redact RESTRICTED memories for display (content withheld; title/metadata secret-scrubbed). */
|
|
68
|
+
export declare function redactRestrictedForDisplay(memories: Memory[]): Memory[];
|
|
69
|
+
/** Apply the dashboard redaction to every memory list in a context summary (used before formatting). */
|
|
70
|
+
export declare function guardDashboardContextSummary(summary: ContextSummary): ContextSummary;
|
|
71
|
+
/**
|
|
72
|
+
* Deep-walk an arbitrary HTTP-response payload and redact every RESTRICTED memory
|
|
73
|
+
* object it contains (withhold `content`; mask credential spans in `title` and
|
|
74
|
+
* string `metadata`), returning a redacted COPY (the input is never mutated —
|
|
75
|
+
* payloads often reference the live row cache).
|
|
76
|
+
*
|
|
77
|
+
* This is the comprehensive backstop for the visualization API: memories surface
|
|
78
|
+
* at many different nesting depths (`{ memories: [...] }`, recall
|
|
79
|
+
* `results[].memory`, openclaw `sessions[].memories[]`, review-queue
|
|
80
|
+
* `sections.stale[]`, `contradictions[].memoryA`), so guarding each route by hand
|
|
81
|
+
* would inevitably miss one. A single response interceptor that walks the whole
|
|
82
|
+
* tree cannot. It does NOT reach content already baked into a pre-rendered string
|
|
83
|
+
* (e.g. `/api/context`'s `formatted`) or bare title fields stripped of their
|
|
84
|
+
* sensitivity label (the contradictions endpoints, the `memory_deleted` event) —
|
|
85
|
+
* those are scrubbed at their own surface.
|
|
86
|
+
*/
|
|
87
|
+
export declare function deepRedactRestrictedContent<T>(value: T, seen?: WeakSet<object>): T;
|