Skip to main content

provenant/models/
output.rs

1use super::{FileInfo, Match, Package, TopLevelDependency};
2use serde::{Deserialize, Serialize};
3use serde_json::{Map, Value};
4
5pub const OUTPUT_FORMAT_VERSION: &str = "4.1.0";
6pub const TOOL_NAME: &str = "provenant";
7pub const HEADER_NOTICE: &str = "Generated with Provenant and provided on an \"AS IS\" basis, without warranties or conditions of any kind, either express or implied. Provenant and its authors/providers do not provide legal advice, and are not responsible for how this output is used. Consult qualified legal counsel for legal advice.";
8
9#[derive(Debug)]
10/// Top-level ScanCode-compatible JSON payload.
11pub struct Output {
12    pub summary: Option<Summary>,
13    pub tallies: Option<Tallies>,
14    pub tallies_of_key_files: Option<Tallies>,
15    pub tallies_by_facet: Option<Vec<FacetTallies>>,
16    pub headers: Vec<Header>,
17    pub packages: Vec<Package>,
18    pub dependencies: Vec<TopLevelDependency>,
19    pub license_detections: Vec<TopLevelLicenseDetection>,
20    pub files: Vec<FileInfo>,
21    pub license_references: Vec<LicenseReference>,
22    pub license_rule_references: Vec<LicenseRuleReference>,
23}
24
25#[derive(Deserialize, Debug, Clone, PartialEq)]
26pub struct TopLevelLicenseDetection {
27    pub identifier: String,
28    pub license_expression: String,
29    pub license_expression_spdx: String,
30    pub detection_count: usize,
31    #[serde(default)]
32    pub detection_log: Vec<String>,
33    pub reference_matches: Vec<Match>,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct Summary {
38    pub declared_license_expression: Option<String>,
39    pub license_clarity_score: Option<LicenseClarityScore>,
40    pub declared_holder: Option<String>,
41    pub primary_language: Option<String>,
42    pub other_license_expressions: Vec<TallyEntry>,
43    pub other_holders: Vec<TallyEntry>,
44    pub other_languages: Vec<TallyEntry>,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct LicenseClarityScore {
49    pub score: usize,
50    pub declared_license: bool,
51    pub identification_precision: bool,
52    pub has_license_text: bool,
53    pub declared_copyrights: bool,
54    pub conflicting_license_categories: bool,
55    pub ambiguous_compound_licensing: bool,
56}
57
58#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
59pub struct TallyEntry {
60    pub value: Option<String>,
61    pub count: usize,
62}
63
64#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
65pub struct Tallies {
66    #[serde(default, skip_serializing_if = "Vec::is_empty")]
67    pub detected_license_expression: Vec<TallyEntry>,
68    #[serde(default, skip_serializing_if = "Vec::is_empty")]
69    pub copyrights: Vec<TallyEntry>,
70    #[serde(default, skip_serializing_if = "Vec::is_empty")]
71    pub holders: Vec<TallyEntry>,
72    #[serde(default, skip_serializing_if = "Vec::is_empty")]
73    pub authors: Vec<TallyEntry>,
74    #[serde(default, skip_serializing_if = "Vec::is_empty")]
75    pub programming_language: Vec<TallyEntry>,
76}
77
78impl Tallies {
79    pub fn is_empty(&self) -> bool {
80        self.detected_license_expression.is_empty()
81            && self.copyrights.is_empty()
82            && self.holders.is_empty()
83            && self.authors.is_empty()
84            && self.programming_language.is_empty()
85    }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct FacetTallies {
90    pub facet: String,
91    pub tallies: Tallies,
92}
93
94#[derive(Debug)]
95/// Scan execution metadata stored in `output.headers`.
96pub struct Header {
97    pub tool_name: String,
98    pub tool_version: String,
99    pub options: Map<String, Value>,
100    pub notice: String,
101    pub start_timestamp: String,
102    pub end_timestamp: String,
103    pub output_format_version: String,
104    pub duration: f64,
105    pub errors: Vec<String>,
106    pub warnings: Vec<String>,
107    pub extra_data: ExtraData,
108}
109
110#[derive(Debug)]
111/// Additional counters and environment details for a scan run.
112pub struct ExtraData {
113    pub system_environment: SystemEnvironment,
114    pub spdx_license_list_version: String,
115    pub files_count: usize,
116    pub directories_count: usize,
117    pub excluded_count: usize,
118    pub license_index_provenance: Option<LicenseIndexProvenance>,
119}
120
121#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
122pub struct LicenseIndexProvenance {
123    pub source: String,
124    pub dataset_fingerprint: String,
125    #[serde(default)]
126    pub ignored_rules: Vec<String>,
127    #[serde(default)]
128    pub ignored_licenses: Vec<String>,
129    #[serde(default)]
130    pub ignored_rules_due_to_licenses: Vec<String>,
131    #[serde(default)]
132    pub added_rules: Vec<String>,
133    #[serde(default)]
134    pub replaced_rules: Vec<String>,
135    #[serde(default)]
136    pub added_licenses: Vec<String>,
137    #[serde(default)]
138    pub replaced_licenses: Vec<String>,
139}
140
141#[derive(Debug)]
142/// Host environment information captured during scan execution.
143pub struct SystemEnvironment {
144    pub operating_system: String,
145    pub cpu_architecture: String,
146    pub platform: String,
147    pub platform_version: String,
148    pub rust_version: String,
149}
150
151#[derive(Deserialize, Debug)]
152/// Reference entry for a detected license.
153pub struct LicenseReference {
154    #[serde(default)]
155    pub key: Option<String>,
156    #[serde(default)]
157    pub language: Option<String>,
158    pub name: String,
159    pub short_name: String,
160    #[serde(default)]
161    pub owner: Option<String>,
162    #[serde(default)]
163    pub homepage_url: Option<String>,
164    pub spdx_license_key: String,
165    #[serde(default)]
166    pub other_spdx_license_keys: Vec<String>,
167    #[serde(default)]
168    pub osi_license_key: Option<String>,
169    #[serde(default)]
170    pub text_urls: Vec<String>,
171    #[serde(default)]
172    pub osi_url: Option<String>,
173    #[serde(default)]
174    pub faq_url: Option<String>,
175    #[serde(default)]
176    pub other_urls: Vec<String>,
177    #[serde(default)]
178    pub category: Option<String>,
179    #[serde(default)]
180    pub is_exception: bool,
181    #[serde(default)]
182    pub is_unknown: bool,
183    #[serde(default)]
184    pub is_generic: bool,
185    #[serde(default)]
186    pub notes: Option<String>,
187    #[serde(default)]
188    pub minimum_coverage: Option<u8>,
189    #[serde(default)]
190    pub standard_notice: Option<String>,
191    #[serde(default)]
192    pub ignorable_copyrights: Vec<String>,
193    #[serde(default)]
194    pub ignorable_holders: Vec<String>,
195    #[serde(default)]
196    pub ignorable_authors: Vec<String>,
197    #[serde(default)]
198    pub ignorable_urls: Vec<String>,
199    #[serde(default)]
200    pub ignorable_emails: Vec<String>,
201    #[serde(default)]
202    pub scancode_url: Option<String>,
203    #[serde(default)]
204    pub licensedb_url: Option<String>,
205    #[serde(default)]
206    pub spdx_url: Option<String>,
207    pub text: String,
208}
209
210#[derive(Deserialize, Debug)]
211/// Reference metadata for a license detection rule.
212pub struct LicenseRuleReference {
213    pub identifier: String,
214    pub license_expression: String,
215    pub is_license_text: bool,
216    pub is_license_notice: bool,
217    pub is_license_reference: bool,
218    pub is_license_tag: bool,
219    pub is_license_clue: bool,
220    pub is_license_intro: bool,
221    #[serde(default)]
222    pub language: Option<String>,
223    #[serde(default)]
224    pub rule_url: Option<String>,
225    #[serde(default)]
226    pub is_required_phrase: bool,
227    #[serde(default)]
228    pub skip_for_required_phrase_generation: bool,
229    #[serde(default)]
230    pub replaced_by: Vec<String>,
231    #[serde(default)]
232    pub is_continuous: bool,
233    #[serde(default)]
234    pub is_synthetic: bool,
235    #[serde(default)]
236    pub is_from_license: bool,
237    #[serde(default)]
238    pub length: usize,
239    #[serde(default)]
240    pub relevance: Option<u8>,
241    #[serde(default)]
242    pub minimum_coverage: Option<u8>,
243    #[serde(default)]
244    pub referenced_filenames: Vec<String>,
245    #[serde(default)]
246    pub notes: Option<String>,
247    #[serde(default)]
248    pub ignorable_copyrights: Vec<String>,
249    #[serde(default)]
250    pub ignorable_holders: Vec<String>,
251    #[serde(default)]
252    pub ignorable_authors: Vec<String>,
253    #[serde(default)]
254    pub ignorable_urls: Vec<String>,
255    #[serde(default)]
256    pub ignorable_emails: Vec<String>,
257    #[serde(default)]
258    pub text: Option<String>,
259}