Initial commit: Compliance Scanner Agent

Autonomous security and compliance scanning agent for git repositories.
Features: SAST (Semgrep), SBOM (Syft), CVE monitoring (OSV.dev/NVD),
GDPR/OAuth pattern detection, LLM triage, issue creation (GitHub/GitLab/Jira),
PR reviews, and Dioxus fullstack dashboard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-03-02 13:30:17 +01:00
commit 0867e401bc
97 changed files with 11750 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
use mongodb::bson::doc;
use mongodb::{Client, Collection, IndexModel};
use mongodb::options::IndexOptions;
use compliance_core::models::*;
use crate::error::AgentError;
#[derive(Clone, Debug)]
pub struct Database {
inner: mongodb::Database,
}
impl Database {
pub async fn connect(uri: &str, db_name: &str) -> Result<Self, AgentError> {
let client = Client::with_uri_str(uri).await?;
let db = client.database(db_name);
db.run_command(doc! { "ping": 1 }).await?;
tracing::info!("Connected to MongoDB database '{db_name}'");
Ok(Self { inner: db })
}
pub async fn ensure_indexes(&self) -> Result<(), AgentError> {
// repositories: unique git_url
self.repositories()
.create_index(
IndexModel::builder()
.keys(doc! { "git_url": 1 })
.options(IndexOptions::builder().unique(true).build())
.build(),
)
.await?;
// findings: unique fingerprint
self.findings()
.create_index(
IndexModel::builder()
.keys(doc! { "fingerprint": 1 })
.options(IndexOptions::builder().unique(true).build())
.build(),
)
.await?;
// findings: repo_id + severity compound
self.findings()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "severity": 1 })
.build(),
)
.await?;
// scan_runs: repo_id + started_at descending
self.scan_runs()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "started_at": -1 })
.build(),
)
.await?;
// sbom_entries: compound
self.sbom_entries()
.create_index(
IndexModel::builder()
.keys(doc! { "repo_id": 1, "name": 1, "version": 1 })
.build(),
)
.await?;
// cve_alerts: unique cve_id + repo_id
self.cve_alerts()
.create_index(
IndexModel::builder()
.keys(doc! { "cve_id": 1, "repo_id": 1 })
.options(IndexOptions::builder().unique(true).build())
.build(),
)
.await?;
// tracker_issues: unique finding_id
self.tracker_issues()
.create_index(
IndexModel::builder()
.keys(doc! { "finding_id": 1 })
.options(IndexOptions::builder().unique(true).build())
.build(),
)
.await?;
tracing::info!("Database indexes ensured");
Ok(())
}
pub fn repositories(&self) -> Collection<TrackedRepository> {
self.inner.collection("repositories")
}
pub fn findings(&self) -> Collection<Finding> {
self.inner.collection("findings")
}
pub fn scan_runs(&self) -> Collection<ScanRun> {
self.inner.collection("scan_runs")
}
pub fn sbom_entries(&self) -> Collection<SbomEntry> {
self.inner.collection("sbom_entries")
}
pub fn cve_alerts(&self) -> Collection<CveAlert> {
self.inner.collection("cve_alerts")
}
pub fn tracker_issues(&self) -> Collection<TrackerIssue> {
self.inner.collection("tracker_issues")
}
pub fn raw_collection(&self, name: &str) -> Collection<mongodb::bson::Document> {
self.inner.collection(name)
}
}