1use anyhow::{anyhow, Result};
2use serde::{Deserialize, Serialize};
3use serde_json::{json, Map, Value};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ArtifactDoc {
7 pub id: String,
8 pub repo: String,
9 pub kind: String,
10 pub side: Option<String>,
11 pub language: Option<String>,
12 pub name: Option<String>,
13 pub display_name: Option<String>,
14 pub source_path: Option<String>,
15 pub line_start: Option<u32>,
16 pub line_end: Option<u32>,
17 pub column_start: Option<u32>,
18 pub column_end: Option<u32>,
19 pub package_name: Option<String>,
20 pub comments: Vec<String>,
21 pub tags: Vec<String>,
22 pub related_symbols: Vec<String>,
23 pub related_tests: Vec<String>,
24 pub risk_level: String,
25 pub risk_reasons: Vec<String>,
26 pub contains_phi: bool,
27 pub has_related_tests: bool,
28 pub updated_at: String,
29 #[serde(flatten)]
30 pub data: Map<String, Value>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct EdgeDoc {
35 pub id: String,
36 pub repo: String,
37 pub kind: String,
38 pub edge_type: String,
39 pub from_id: String,
40 pub from_kind: String,
41 pub from_name: Option<String>,
42 pub to_id: String,
43 pub to_kind: String,
44 pub to_name: Option<String>,
45 pub confidence: f32,
46 pub reason: String,
47 pub source_path: Option<String>,
48 pub line_start: Option<u32>,
49 pub risk_level: String,
50 pub updated_at: String,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct WarningDoc {
55 pub id: String,
56 pub repo: String,
57 pub kind: String,
58 pub warning_type: String,
59 pub severity: String,
60 pub message: String,
61 pub source_path: Option<String>,
62 pub line_start: Option<u32>,
63 pub related_id: Option<String>,
64 pub risk_level: String,
65 pub remediation: Option<String>,
66 pub updated_at: String,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ScanSummary {
71 pub repo: String,
72 pub artifact_count: usize,
73 pub edge_count: usize,
74 pub warning_count: usize,
75 pub artifact_kinds: Vec<String>,
76 pub warning_types: Vec<String>,
77 pub scanned_at: String,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ProjectInfo {
82 pub repo: String,
83 pub repo_path: String,
84 pub output_dir: String,
85 pub index_uid: String,
86 pub artifact_count: usize,
87 pub edge_count: usize,
88 pub warning_count: usize,
89 pub scanned_at: String,
90}
91
92pub fn schema_for_kind(kind: &str) -> Result<Value> {
93 match kind {
94 "artifact" => Ok(json!({
95 "type": "object",
96 "required": ["id", "repo", "kind", "risk_level", "contains_phi", "has_related_tests", "related_tests"],
97 "properties": {
98 "id": {"type": "string"},
99 "repo": {"type": "string"},
100 "kind": {"type": "string"},
101 "source_path": {"type": ["string", "null"]},
102 "name": {"type": ["string", "null"]},
103 "risk_level": {"enum": ["low", "medium", "high", "critical"]},
104 "contains_phi": {"type": "boolean"},
105 "has_related_tests": {"type": "boolean"},
106 "related_tests": {"type": "array", "items": {"type": "string"}}
107 }
108 })),
109 "edge" => Ok(json!({
110 "type": "object",
111 "required": ["id", "repo", "kind", "edge_type", "from_id", "to_id"],
112 "properties": {
113 "kind": {"const": "edge"},
114 "edge_type": {"type": "string"},
115 "from_id": {"type": "string"},
116 "to_id": {"type": "string"},
117 "confidence": {"type": "number"}
118 }
119 })),
120 "warning" => Ok(json!({
121 "type": "object",
122 "required": ["id", "repo", "kind", "warning_type", "severity", "message"],
123 "properties": {
124 "kind": {"const": "warning"},
125 "warning_type": {"type": "string"},
126 "severity": {"enum": ["info", "warning", "error"]},
127 "message": {"type": "string"}
128 }
129 })),
130 other => Err(anyhow!("unsupported schema kind {other}")),
131 }
132}