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
190 lines
5.9 KiB
Rust
190 lines
5.9 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Type of code node in the knowledge graph
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum CodeNodeKind {
|
|
Function,
|
|
Method,
|
|
Class,
|
|
Struct,
|
|
Enum,
|
|
Interface,
|
|
Trait,
|
|
Module,
|
|
File,
|
|
}
|
|
|
|
impl std::fmt::Display for CodeNodeKind {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Function => write!(f, "function"),
|
|
Self::Method => write!(f, "method"),
|
|
Self::Class => write!(f, "class"),
|
|
Self::Struct => write!(f, "struct"),
|
|
Self::Enum => write!(f, "enum"),
|
|
Self::Interface => write!(f, "interface"),
|
|
Self::Trait => write!(f, "trait"),
|
|
Self::Module => write!(f, "module"),
|
|
Self::File => write!(f, "file"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A node in the code knowledge graph
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct CodeNode {
|
|
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
|
pub id: Option<bson::oid::ObjectId>,
|
|
pub repo_id: String,
|
|
pub graph_build_id: String,
|
|
/// Unique identifier within the graph (e.g., "src/main.rs::main")
|
|
pub qualified_name: String,
|
|
pub name: String,
|
|
pub kind: CodeNodeKind,
|
|
pub file_path: String,
|
|
pub start_line: u32,
|
|
pub end_line: u32,
|
|
/// Language of the source file
|
|
pub language: String,
|
|
/// Community ID from Louvain clustering
|
|
pub community_id: Option<u32>,
|
|
/// Whether this is a public entry point (main, exported fn, HTTP handler, etc.)
|
|
pub is_entry_point: bool,
|
|
/// Internal petgraph node index for fast lookups
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub graph_index: Option<u32>,
|
|
}
|
|
|
|
/// Type of relationship between code nodes
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum CodeEdgeKind {
|
|
Calls,
|
|
Imports,
|
|
Inherits,
|
|
Implements,
|
|
Contains,
|
|
/// A type reference (e.g., function parameter type, return type)
|
|
TypeRef,
|
|
}
|
|
|
|
impl std::fmt::Display for CodeEdgeKind {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Calls => write!(f, "calls"),
|
|
Self::Imports => write!(f, "imports"),
|
|
Self::Inherits => write!(f, "inherits"),
|
|
Self::Implements => write!(f, "implements"),
|
|
Self::Contains => write!(f, "contains"),
|
|
Self::TypeRef => write!(f, "type_ref"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An edge in the code knowledge graph
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct CodeEdge {
|
|
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
|
pub id: Option<bson::oid::ObjectId>,
|
|
pub repo_id: String,
|
|
pub graph_build_id: String,
|
|
/// Qualified name of source node
|
|
pub source: String,
|
|
/// Qualified name of target node
|
|
pub target: String,
|
|
pub kind: CodeEdgeKind,
|
|
/// File where this relationship was found
|
|
pub file_path: String,
|
|
pub line_number: Option<u32>,
|
|
}
|
|
|
|
/// Status of a graph build operation
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum GraphBuildStatus {
|
|
Running,
|
|
Completed,
|
|
Failed,
|
|
}
|
|
|
|
/// Tracks a graph build operation for a repo/commit
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct GraphBuildRun {
|
|
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
|
pub id: Option<bson::oid::ObjectId>,
|
|
pub repo_id: String,
|
|
pub commit_sha: Option<String>,
|
|
pub status: GraphBuildStatus,
|
|
pub node_count: u32,
|
|
pub edge_count: u32,
|
|
pub community_count: u32,
|
|
pub languages_parsed: Vec<String>,
|
|
pub error_message: Option<String>,
|
|
#[serde(with = "super::serde_helpers::bson_datetime")]
|
|
pub started_at: DateTime<Utc>,
|
|
#[serde(default, with = "super::serde_helpers::opt_bson_datetime")]
|
|
pub completed_at: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
impl GraphBuildRun {
|
|
pub fn new(repo_id: String) -> Self {
|
|
Self {
|
|
id: None,
|
|
repo_id,
|
|
commit_sha: None,
|
|
status: GraphBuildStatus::Running,
|
|
node_count: 0,
|
|
edge_count: 0,
|
|
community_count: 0,
|
|
languages_parsed: Vec::new(),
|
|
error_message: None,
|
|
started_at: Utc::now(),
|
|
completed_at: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Impact analysis result for a finding
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ImpactAnalysis {
|
|
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
|
pub id: Option<bson::oid::ObjectId>,
|
|
pub repo_id: String,
|
|
pub finding_id: String,
|
|
pub graph_build_id: String,
|
|
/// Number of nodes reachable from the finding location
|
|
pub blast_radius: u32,
|
|
/// Entry points affected by this finding (via reverse call chain)
|
|
pub affected_entry_points: Vec<String>,
|
|
/// Call chains from entry points to the finding location
|
|
pub call_chains: Vec<Vec<String>>,
|
|
/// Community IDs affected
|
|
pub affected_communities: Vec<u32>,
|
|
/// Direct callers of the affected function
|
|
pub direct_callers: Vec<String>,
|
|
/// Direct callees of the affected function
|
|
pub direct_callees: Vec<String>,
|
|
#[serde(with = "super::serde_helpers::bson_datetime")]
|
|
pub created_at: DateTime<Utc>,
|
|
}
|
|
|
|
impl ImpactAnalysis {
|
|
pub fn new(repo_id: String, finding_id: String, graph_build_id: String) -> Self {
|
|
Self {
|
|
id: None,
|
|
repo_id,
|
|
finding_id,
|
|
graph_build_id,
|
|
blast_radius: 0,
|
|
affected_entry_points: Vec::new(),
|
|
call_chains: Vec::new(),
|
|
affected_communities: Vec::new(),
|
|
direct_callers: Vec::new(),
|
|
direct_callees: Vec::new(),
|
|
created_at: Utc::now(),
|
|
}
|
|
}
|
|
}
|