Some checks failed
CI / Deploy Agent (push) Has been skipped
CI / Deploy Dashboard (push) Has been skipped
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Format (push) Failing after 3s
CI / Clippy (push) Failing after 2m44s
CI / Security Audit (push) Has been skipped
CI / Tests (push) Has been skipped
CI / Format (pull_request) Failing after 3s
CI / Clippy (pull_request) Failing after 2m51s
CI / Security Audit (pull_request) Has been skipped
CI / Tests (pull_request) Has been skipped
CI / Detect Changes (push) Has been skipped
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
- Add gitleaks secret detection, lint scanning (clippy/eslint/ruff), and LLM code review scanners - Enhance LLM triage with multi-action support (confirm/downgrade/upgrade/dismiss), surrounding code context, and file-path classification confidence adjustment - Add text search, column sorting, and bulk status update to findings dashboard - Fix finding detail page status refresh and add developer feedback field - Fix BSON DateTime deserialization across all models with shared serde helpers - Add scan progress spinner with polling to repositories page - Batch OSV.dev queries to avoid "Too many queries" errors - Add gitleaks, semgrep, and ruff to Dockerfile.agent for deployment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use super::scan::ScanType;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum Severity {
|
|
Info,
|
|
Low,
|
|
Medium,
|
|
High,
|
|
Critical,
|
|
}
|
|
|
|
impl std::fmt::Display for Severity {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Info => write!(f, "info"),
|
|
Self::Low => write!(f, "low"),
|
|
Self::Medium => write!(f, "medium"),
|
|
Self::High => write!(f, "high"),
|
|
Self::Critical => write!(f, "critical"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum FindingStatus {
|
|
Open,
|
|
Triaged,
|
|
FalsePositive,
|
|
Resolved,
|
|
Ignored,
|
|
}
|
|
|
|
impl std::fmt::Display for FindingStatus {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Open => write!(f, "open"),
|
|
Self::Triaged => write!(f, "triaged"),
|
|
Self::FalsePositive => write!(f, "false_positive"),
|
|
Self::Resolved => write!(f, "resolved"),
|
|
Self::Ignored => write!(f, "ignored"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Finding {
|
|
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
|
pub id: Option<bson::oid::ObjectId>,
|
|
pub repo_id: String,
|
|
pub fingerprint: String,
|
|
pub scanner: String,
|
|
pub scan_type: ScanType,
|
|
pub rule_id: Option<String>,
|
|
pub title: String,
|
|
pub description: String,
|
|
pub severity: Severity,
|
|
pub confidence: Option<f64>,
|
|
pub cwe: Option<String>,
|
|
pub cve: Option<String>,
|
|
pub cvss_score: Option<f64>,
|
|
pub file_path: Option<String>,
|
|
pub line_number: Option<u32>,
|
|
pub code_snippet: Option<String>,
|
|
pub remediation: Option<String>,
|
|
pub suggested_fix: Option<String>,
|
|
pub status: FindingStatus,
|
|
pub tracker_issue_url: Option<String>,
|
|
pub scan_run_id: Option<String>,
|
|
/// LLM triage action and reasoning
|
|
pub triage_action: Option<String>,
|
|
pub triage_rationale: Option<String>,
|
|
/// Developer feedback on finding quality
|
|
pub developer_feedback: Option<String>,
|
|
#[serde(with = "super::serde_helpers::bson_datetime")]
|
|
pub created_at: DateTime<Utc>,
|
|
#[serde(with = "super::serde_helpers::bson_datetime")]
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
impl Finding {
|
|
pub fn new(
|
|
repo_id: String,
|
|
fingerprint: String,
|
|
scanner: String,
|
|
scan_type: ScanType,
|
|
title: String,
|
|
description: String,
|
|
severity: Severity,
|
|
) -> Self {
|
|
let now = Utc::now();
|
|
Self {
|
|
id: None,
|
|
repo_id,
|
|
fingerprint,
|
|
scanner,
|
|
scan_type,
|
|
rule_id: None,
|
|
title,
|
|
description,
|
|
severity,
|
|
confidence: None,
|
|
cwe: None,
|
|
cve: None,
|
|
cvss_score: None,
|
|
file_path: None,
|
|
line_number: None,
|
|
code_snippet: None,
|
|
remediation: None,
|
|
suggested_fix: None,
|
|
status: FindingStatus::Open,
|
|
tracker_issue_url: None,
|
|
scan_run_id: None,
|
|
triage_action: None,
|
|
triage_rationale: None,
|
|
developer_feedback: None,
|
|
created_at: now,
|
|
updated_at: now,
|
|
}
|
|
}
|
|
}
|