Add DAST, graph modules, toast notifications, and dashboard enhancements

Add DAST scanning and code knowledge graph features across the stack:
- compliance-dast and compliance-graph workspace crates
- Agent API handlers and routes for DAST targets/scans and graph builds
- Core models and traits for DAST and graph domains
- Dashboard pages for DAST targets/findings/overview and graph explorer/impact
- Toast notification system with auto-dismiss for async action feedback
- Button click animations and disabled states for better UX

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-03-04 13:53:50 +01:00
parent 03ee69834d
commit cea8f59e10
69 changed files with 8745 additions and 54 deletions

View File

@@ -88,6 +88,70 @@ impl Database {
)
.await?;
// graph_nodes: compound (repo_id, graph_build_id)
self.graph_nodes()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "graph_build_id": 1 })
.build(),
)
.await?;
// graph_edges: compound (repo_id, graph_build_id)
self.graph_edges()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "graph_build_id": 1 })
.build(),
)
.await?;
// graph_builds: compound (repo_id, started_at DESC)
self.graph_builds()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "started_at": -1 })
.build(),
)
.await?;
// impact_analyses: unique (repo_id, finding_id)
self.impact_analyses()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "finding_id": 1 })
.options(IndexOptions::builder().unique(true).build())
.build(),
)
.await?;
// dast_targets: index on repo_id
self.dast_targets()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1 })
.build(),
)
.await?;
// dast_scan_runs: compound (target_id, started_at DESC)
self.dast_scan_runs()
.create_index(
IndexModel::builder()
.keys(doc! { "target_id": 1, "started_at": -1 })
.build(),
)
.await?;
// dast_findings: compound (scan_run_id, vuln_type)
self.dast_findings()
.create_index(
IndexModel::builder()
.keys(doc! { "scan_run_id": 1, "vuln_type": 1 })
.build(),
)
.await?;
tracing::info!("Database indexes ensured");
Ok(())
}
@@ -116,8 +180,43 @@ impl Database {
self.inner.collection("tracker_issues")
}
// Graph collections
pub fn graph_nodes(&self) -> Collection<compliance_core::models::graph::CodeNode> {
self.inner.collection("graph_nodes")
}
pub fn graph_edges(&self) -> Collection<compliance_core::models::graph::CodeEdge> {
self.inner.collection("graph_edges")
}
pub fn graph_builds(&self) -> Collection<compliance_core::models::graph::GraphBuildRun> {
self.inner.collection("graph_builds")
}
pub fn impact_analyses(&self) -> Collection<compliance_core::models::graph::ImpactAnalysis> {
self.inner.collection("impact_analyses")
}
// DAST collections
pub fn dast_targets(&self) -> Collection<DastTarget> {
self.inner.collection("dast_targets")
}
pub fn dast_scan_runs(&self) -> Collection<DastScanRun> {
self.inner.collection("dast_scan_runs")
}
pub fn dast_findings(&self) -> Collection<DastFinding> {
self.inner.collection("dast_findings")
}
#[allow(dead_code)]
pub fn raw_collection(&self, name: &str) -> Collection<mongodb::bson::Document> {
self.inner.collection(name)
}
/// Get the raw MongoDB database handle (for graph persistence)
pub fn inner(&self) -> &mongodb::Database {
&self.inner
}
}