1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5pub mod agents;
6pub mod audit;
7pub mod cache;
8pub mod config;
9pub mod docs;
10pub mod firewall;
11pub mod license;
12pub mod manifest;
13pub mod pipeline;
14pub mod registry;
15pub mod sbom;
16pub mod scan;
17pub mod store;
18pub mod validator;
19pub mod web;
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26#[serde(rename_all = "lowercase")]
27pub enum Ecosystem {
28 Npm,
29 PyPI,
30 Crates,
31 Go,
32}
33
34impl std::fmt::Display for Ecosystem {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 Ecosystem::Npm => write!(f, "npm"),
38 Ecosystem::PyPI => write!(f, "pypi"),
39 Ecosystem::Crates => write!(f, "crates"),
40 Ecosystem::Go => write!(f, "go"),
41 }
42 }
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct PackageRef {
51 pub name: String,
52 pub version_constraint: String,
53 pub ecosystem: Ecosystem,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ParsedManifest {
58 pub manifest_type: String,
59 pub packages: Vec<PackageRef>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct PackageMetadata {
68 pub name: String,
69 pub version: String,
70 pub ecosystem: Ecosystem,
71 pub description: Option<String>,
72 pub license: Option<String>,
73 pub repository_url: Option<String>,
74 pub homepage_url: Option<String>,
75 pub unpacked_size: Option<u64>,
76 pub registry_url: String,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct DocEntry {
85 pub name: String,
86 pub content: String,
87 pub source_url: Option<String>,
88 pub content_hash: String,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct Documentation {
93 pub package: PackageMetadata,
94 pub documents: Vec<DocEntry>,
95 pub content_hash: String,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct CspDocument {
104 pub filename: String,
105 pub content: String,
106 pub content_hash: String,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct CspSpec {
111 pub package_name: String,
112 pub package_version: String,
113 pub documents: Vec<CspDocument>,
114 pub generated_at: DateTime<Utc>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct Implementation {
123 pub package_name: String,
124 pub files: HashMap<String, String>,
125 pub target_language: String,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct SimilarityReport {
134 pub token_similarity: f64,
135 pub name_overlap: f64,
136 pub string_overlap: f64,
137 pub structural_similarity: f64,
138 pub overall_score: f64,
139 pub threshold: f64,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(rename_all = "lowercase")]
144pub enum Verdict {
145 Pass,
146 Fail,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct ValidationReport {
151 pub package: PackageMetadata,
152 pub syntax_ok: bool,
153 pub tests_passed: u32,
154 pub tests_failed: u32,
155 pub api_coverage: f64,
156 pub license_ok: bool,
157 pub similarity: SimilarityReport,
158 pub verdict: Verdict,
159}
160
161pub fn resolve_license_text(license_id: &str, year: &str, holder: &str) -> Option<String> {
166 let template = match license_id {
167 "mit" => include_str!("../licenses/mit.txt"),
168 "apache-2.0" => include_str!("../licenses/apache-2.0.txt"),
169 "bsd-2" => include_str!("../licenses/bsd-2.txt"),
170 "bsd-3" => include_str!("../licenses/bsd-3.txt"),
171 "isc" => include_str!("../licenses/isc.txt"),
172 "unlicense" => include_str!("../licenses/unlicense.txt"),
173 "cc0" => include_str!("../licenses/cc0.txt"),
174 _ => return None,
175 };
176 Some(template.replace("{year}", year).replace("{holder}", holder))
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
185#[serde(rename_all = "kebab-case")]
186pub enum LicenseClass {
187 Permissive,
188 CopyleftWeak,
189 CopyleftStrong,
190 Proprietary,
191 Unknown,
192}
193
194impl std::fmt::Display for LicenseClass {
195 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 match self {
197 LicenseClass::Permissive => write!(f, "permissive"),
198 LicenseClass::CopyleftWeak => write!(f, "copyleft-weak"),
199 LicenseClass::CopyleftStrong => write!(f, "copyleft-strong"),
200 LicenseClass::Proprietary => write!(f, "proprietary"),
201 LicenseClass::Unknown => write!(f, "unknown"),
202 }
203 }
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct ScannedPackage {
209 pub name: String,
210 pub version: String,
211 pub ecosystem: Ecosystem,
212 pub raw_license: Option<String>,
214 pub spdx_license: Option<String>,
216 pub classification: LicenseClass,
218 pub source: String,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct ScanResult {
225 pub id: String,
226 pub path: String,
227 pub scanned_at: DateTime<Utc>,
228 pub packages: Vec<ScannedPackage>,
229 pub manifest_files: Vec<String>,
230 pub sbom_files: Vec<String>,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
238#[serde(rename_all = "lowercase")]
239pub enum IsolationMode {
240 Context,
241 Process,
242 Container,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize)]
246#[serde(rename_all = "lowercase")]
247pub enum TargetLanguage {
248 Same,
249 Rust,
250 Go,
251 Python,
252 TypeScript,
253}
254
255impl std::fmt::Display for TargetLanguage {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 match self {
258 TargetLanguage::Same => write!(f, "same"),
259 TargetLanguage::Rust => write!(f, "rust"),
260 TargetLanguage::Go => write!(f, "go"),
261 TargetLanguage::Python => write!(f, "python"),
262 TargetLanguage::TypeScript => write!(f, "typescript"),
263 }
264 }
265}