Skip to main content

provenant/models/
output.rs

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