feat: findings refinement, new scanners, and deployment tooling (#6)
Some checks failed
CI / Format (push) Successful in 3s
CI / Clippy (push) Successful in 4m3s
CI / Security Audit (push) Successful in 1m38s
CI / Tests (push) Successful in 4m44s
CI / Detect Changes (push) Successful in 2s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Failing after 2s

This commit was merged in pull request #6.
This commit is contained in:
2026-03-09 12:53:12 +00:00
parent 32e5fc21e7
commit 46bf9de549
40 changed files with 2048 additions and 118 deletions

View File

@@ -4,6 +4,9 @@ use dioxus::prelude::*;
use time::Duration;
use tower_sessions::{cookie::Key, MemoryStore, SessionManagerLayer};
use compliance_core::models::{McpServerConfig, McpServerStatus, McpTransport};
use mongodb::bson::doc;
use super::config;
use super::database::Database;
use super::error::DashboardError;
@@ -22,6 +25,9 @@ pub fn server_start(app: fn() -> Element) -> Result<(), DashboardError> {
KeycloakConfig::from_env().map(|kc| &*Box::leak(Box::new(kc)));
let db = Database::connect(&config.mongodb_uri, &config.mongodb_database).await?;
// Seed default MCP server configs
seed_default_mcp_servers(&db, config.mcp_endpoint_url.as_deref()).await;
if let Some(kc) = keycloak {
tracing::info!("Keycloak configured for realm '{}'", kc.realm);
} else {
@@ -70,3 +76,66 @@ pub fn server_start(app: fn() -> Element) -> Result<(), DashboardError> {
Ok(())
})
}
/// Seed three default MCP server configs (Findings, SBOM, DAST) if they don't already exist.
async fn seed_default_mcp_servers(db: &Database, mcp_endpoint_url: Option<&str>) {
let endpoint = mcp_endpoint_url.unwrap_or("http://localhost:8090");
let defaults = [
(
"Findings MCP",
"Exposes security findings, triage data, and finding summaries to LLM agents",
vec!["list_findings", "get_finding", "findings_summary"],
),
(
"SBOM MCP",
"Exposes software bill of materials and vulnerability reports to LLM agents",
vec!["list_sbom_packages", "sbom_vuln_report"],
),
(
"DAST MCP",
"Exposes DAST scan findings and scan summaries to LLM agents",
vec!["list_dast_findings", "dast_scan_summary"],
),
];
let collection = db.mcp_servers();
for (name, description, tools) in defaults {
// Skip if already exists
let exists = collection
.find_one(doc! { "name": name })
.await
.ok()
.flatten()
.is_some();
if exists {
continue;
}
let now = chrono::Utc::now();
let token = format!("mcp_{}", uuid::Uuid::new_v4().to_string().replace('-', ""));
let server = McpServerConfig {
id: None,
name: name.to_string(),
endpoint_url: format!("{endpoint}/mcp"),
transport: McpTransport::Http,
port: Some(8090),
status: McpServerStatus::Stopped,
access_token: token,
tools_enabled: tools.into_iter().map(|s| s.to_string()).collect(),
description: Some(description.to_string()),
mongodb_uri: None,
mongodb_database: None,
created_at: now,
updated_at: now,
};
match collection.insert_one(server).await {
Ok(_) => tracing::info!("Seeded default MCP server: {name}"),
Err(e) => tracing::warn!("Failed to seed MCP server '{name}': {e}"),
}
}
}