1pub const REPORT_SCHEMA_VERSION: u32 = 1;
2pub const REPORT_SCHEMA_ID: &str = "cargo-allow.report.v1";
3pub const RECEIPT_SCHEMA_VERSION: u32 = 1;
4pub const RECEIPT_SCHEMA_ID: &str = "cargo-allow.receipt.v1";
5pub const WORKLIST_SCHEMA_VERSION: u32 = 1;
6pub const WORKLIST_SCHEMA_ID: &str = "cargo-allow.worklist.v1";
7pub const LIST_SCHEMA_VERSION: u32 = 1;
8pub const LIST_SCHEMA_ID: &str = "cargo-allow.list.v1";
9pub const EXPLAIN_SCHEMA_VERSION: u32 = 1;
10pub const EXPLAIN_SCHEMA_ID: &str = "cargo-allow.explain.v1";
11pub const PRUNE_SCHEMA_VERSION: u32 = 1;
12pub const PRUNE_SCHEMA_ID: &str = "cargo-allow.prune.v1";
13pub const DOCTOR_SCHEMA_VERSION: u32 = 1;
14pub const DOCTOR_SCHEMA_ID: &str = "cargo-allow.doctor.v1";
15pub const PROPOSE_SCHEMA_VERSION: u32 = 1;
16pub const PROPOSE_SCHEMA_ID: &str = "cargo-allow.propose.v1";
17pub const ADD_SCHEMA_VERSION: u32 = 1;
18pub const ADD_SCHEMA_ID: &str = "cargo-allow.add.v1";
19pub const MIGRATE_SCHEMA_VERSION: u32 = 1;
20pub const MIGRATE_SCHEMA_ID: &str = "cargo-allow.migrate.v1";
21pub const SPEC_SYSTEM_SCHEMA_VERSION: u32 = 1;
22pub const SPEC_SYSTEM_SCHEMA_ID: &str = "cargo-allow.spec-system.v1";
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub struct ArtifactContract {
26 pub name: &'static str,
27 pub schema_id: &'static str,
28 pub schema_version: u32,
29 pub inventory_scanner: &'static str,
30 pub fixed_command: Option<&'static str>,
31}
32
33pub const ARTIFACT_STATUS_PASSED: &str = "passed";
34pub const ARTIFACT_STATUS_FAILED: &str = "failed";
35pub const ARTIFACT_STATUS_ERROR: &str = "error";
36pub const ARTIFACT_STATUSES: &[&str] = &[ARTIFACT_STATUS_PASSED, ARTIFACT_STATUS_FAILED];
37pub const RECEIPT_STATUSES: &[&str] = &[
38 ARTIFACT_STATUS_PASSED,
39 ARTIFACT_STATUS_FAILED,
40 ARTIFACT_STATUS_ERROR,
41];
42pub const RECEIPT_ENFORCEMENT_ADVISORY: &str = "advisory";
43pub const RECEIPT_ENFORCEMENT_ENFORCING: &str = "enforcing";
44
45pub const REPORT_COMMAND_AUDIT: &str = "audit";
46pub const REPORT_COMMAND_CHECK: &str = "check";
47pub const REPORT_COMMAND_DIFF: &str = "diff";
48pub const REPORT_COMMANDS: &[&str] = &[
49 REPORT_COMMAND_AUDIT,
50 REPORT_COMMAND_CHECK,
51 REPORT_COMMAND_DIFF,
52];
53pub const RECEIPT_COMMAND_CHECK: &str = "check";
54
55pub const INVENTORY_SCOPE_SOURCE_TREE: &str = "source_tree";
56pub const INVENTORY_SCANNER_SOURCE_SYNTAX: &str = "source_syntax";
57pub const INVENTORY_SCANNER_POLICY_MIGRATION: &str = "policy_migration";
58pub const INVENTORY_SCANNER_SOURCE_TREE_GRAPH: &str = "source_tree_graph";
59pub const INVENTORY_SOURCE_UNKNOWN: &str = "unknown";
60
61pub(crate) const ADD_ARTIFACT: ArtifactContract = ArtifactContract {
62 name: "add",
63 schema_id: ADD_SCHEMA_ID,
64 schema_version: ADD_SCHEMA_VERSION,
65 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
66 fixed_command: Some("add"),
67};
68
69pub(crate) const DOCTOR_ARTIFACT: ArtifactContract = ArtifactContract {
70 name: "doctor",
71 schema_id: DOCTOR_SCHEMA_ID,
72 schema_version: DOCTOR_SCHEMA_VERSION,
73 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
74 fixed_command: Some("doctor"),
75};
76
77pub(crate) const EXPLAIN_ARTIFACT: ArtifactContract = ArtifactContract {
78 name: "explain",
79 schema_id: EXPLAIN_SCHEMA_ID,
80 schema_version: EXPLAIN_SCHEMA_VERSION,
81 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
82 fixed_command: Some("explain"),
83};
84
85pub(crate) const LIST_ARTIFACT: ArtifactContract = ArtifactContract {
86 name: "list",
87 schema_id: LIST_SCHEMA_ID,
88 schema_version: LIST_SCHEMA_VERSION,
89 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
90 fixed_command: Some("list"),
91};
92
93pub(crate) const MIGRATE_ARTIFACT: ArtifactContract = ArtifactContract {
94 name: "migrate",
95 schema_id: MIGRATE_SCHEMA_ID,
96 schema_version: MIGRATE_SCHEMA_VERSION,
97 inventory_scanner: INVENTORY_SCANNER_POLICY_MIGRATION,
98 fixed_command: Some("migrate"),
99};
100
101pub(crate) const PROPOSE_ARTIFACT: ArtifactContract = ArtifactContract {
102 name: "propose",
103 schema_id: PROPOSE_SCHEMA_ID,
104 schema_version: PROPOSE_SCHEMA_VERSION,
105 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
106 fixed_command: Some("propose"),
107};
108
109pub(crate) const PRUNE_ARTIFACT: ArtifactContract = ArtifactContract {
110 name: "prune",
111 schema_id: PRUNE_SCHEMA_ID,
112 schema_version: PRUNE_SCHEMA_VERSION,
113 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
114 fixed_command: Some("prune"),
115};
116
117pub(crate) const RECEIPT_ARTIFACT: ArtifactContract = ArtifactContract {
118 name: "receipt",
119 schema_id: RECEIPT_SCHEMA_ID,
120 schema_version: RECEIPT_SCHEMA_VERSION,
121 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
122 fixed_command: Some(RECEIPT_COMMAND_CHECK),
123};
124
125pub(crate) const REPORT_ARTIFACT: ArtifactContract = ArtifactContract {
126 name: "report",
127 schema_id: REPORT_SCHEMA_ID,
128 schema_version: REPORT_SCHEMA_VERSION,
129 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
130 fixed_command: None,
131};
132
133pub(crate) const SPEC_SYSTEM_ARTIFACT: ArtifactContract = ArtifactContract {
134 name: "spec-system",
135 schema_id: SPEC_SYSTEM_SCHEMA_ID,
136 schema_version: SPEC_SYSTEM_SCHEMA_VERSION,
137 inventory_scanner: INVENTORY_SCANNER_SOURCE_TREE_GRAPH,
138 fixed_command: None,
139};
140
141pub(crate) const WORKLIST_ARTIFACT: ArtifactContract = ArtifactContract {
142 name: "worklist",
143 schema_id: WORKLIST_SCHEMA_ID,
144 schema_version: WORKLIST_SCHEMA_VERSION,
145 inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
146 fixed_command: Some("worklist"),
147};
148
149pub const ARTIFACT_CONTRACTS: &[ArtifactContract] = &[
150 ADD_ARTIFACT,
151 DOCTOR_ARTIFACT,
152 EXPLAIN_ARTIFACT,
153 LIST_ARTIFACT,
154 MIGRATE_ARTIFACT,
155 PROPOSE_ARTIFACT,
156 PRUNE_ARTIFACT,
157 RECEIPT_ARTIFACT,
158 REPORT_ARTIFACT,
159 SPEC_SYSTEM_ARTIFACT,
160 WORKLIST_ARTIFACT,
161];
162
163pub fn artifact_contract_for_schema_id(schema_id: &str) -> Option<ArtifactContract> {
164 ARTIFACT_CONTRACTS
165 .iter()
166 .copied()
167 .find(|contract| contract.schema_id == schema_id)
168}
169
170pub const CLAIM_BOUNDARY: &[&str] = &[
171 "source_tree_inventory",
172 "source_syntax_only",
173 "cargo_metadata_not_invoked",
174 "cargo_commands_not_invoked",
175 "rustc_not_invoked",
176 "clippy_not_invoked",
177 "build_scripts_not_executed",
178 "proc_macros_not_executed",
179 "macro_expansion_not_analyzed",
180 "macro_token_tree_contents_not_analyzed",
181 "type_information_not_analyzed",
182 "mir_not_analyzed",
183 "build_output_not_analyzed",
184 "control_flow_not_analyzed",
185 "data_flow_not_analyzed",
186 "external_evidence_tools_not_invoked",
187 "repository_code_not_executed",
188];
189
190pub const SCANNER_LIMITATIONS: &[&str] = &[
191 "cargo_metadata_not_invoked",
192 "cargo_commands_not_invoked",
193 "rustc_not_invoked",
194 "clippy_not_invoked",
195 "build_scripts_not_executed",
196 "proc_macros_not_executed",
197 "macro_expansion_not_analyzed",
198 "macro_token_tree_contents_not_analyzed",
199 "type_information_not_analyzed",
200 "mir_not_analyzed",
201 "build_output_not_analyzed",
202 "control_flow_not_analyzed",
203 "data_flow_not_analyzed",
204 "external_evidence_tools_not_invoked",
205 "repository_code_not_executed",
206];
207
208pub const SPEC_SYSTEM_CLAIM_BOUNDARY: &[&str] = &[
209 "source_tree_inventory",
210 "source_tree_graph_validation",
211 "proof_commands_not_executed",
212 "cargo_metadata_not_invoked",
213 "cargo_commands_not_invoked",
214 "rustc_not_invoked",
215 "clippy_not_invoked",
216 "build_scripts_not_executed",
217 "proc_macros_not_executed",
218 "macro_expansion_not_analyzed",
219 "macro_token_tree_contents_not_analyzed",
220 "type_information_not_analyzed",
221 "mir_not_analyzed",
222 "build_output_not_analyzed",
223 "control_flow_not_analyzed",
224 "data_flow_not_analyzed",
225 "external_evidence_tools_not_invoked",
226 "repository_code_not_executed",
227 "network_not_used",
228 "github_api_not_used",
229];
230
231pub const SPEC_SYSTEM_SCANNER_LIMITATIONS: &[&str] = &[
232 "proof_commands_not_executed",
233 "cargo_metadata_not_invoked",
234 "cargo_commands_not_invoked",
235 "rustc_not_invoked",
236 "clippy_not_invoked",
237 "build_scripts_not_executed",
238 "proc_macros_not_executed",
239 "macro_expansion_not_analyzed",
240 "macro_token_tree_contents_not_analyzed",
241 "type_information_not_analyzed",
242 "mir_not_analyzed",
243 "build_output_not_analyzed",
244 "control_flow_not_analyzed",
245 "data_flow_not_analyzed",
246 "external_evidence_tools_not_invoked",
247 "repository_code_not_executed",
248 "network_not_used",
249 "github_api_not_used",
250];
251
252pub fn claim_boundary_for_schema_id(schema_id: &str) -> &'static [&'static str] {
253 if schema_id == SPEC_SYSTEM_SCHEMA_ID {
254 SPEC_SYSTEM_CLAIM_BOUNDARY
255 } else {
256 CLAIM_BOUNDARY
257 }
258}
259
260pub fn scanner_limitations_for_schema_id(schema_id: &str) -> &'static [&'static str] {
261 if schema_id == SPEC_SYSTEM_SCHEMA_ID {
262 SPEC_SYSTEM_SCANNER_LIMITATIONS
263 } else {
264 SCANNER_LIMITATIONS
265 }
266}
267
268pub const CLAIM_BOUNDARY_TEXT: &str = "Claim boundary: scanned source-tree/source syntax only; cargo-allow did not invoke Cargo metadata, Cargo commands, rustc, Clippy, build scripts, proc macros, external evidence tools, or repository code. Macro expansion, macro token-tree contents, type information, MIR, build output, control flow, and data flow were not analyzed.";
269
270#[derive(Debug, Clone, Copy)]
271pub struct InventoryContext<'a> {
272 pub scope: &'a str,
273 pub scanner: &'a str,
274 pub source: &'a str,
275 pub root: Option<&'a str>,
276 pub files_scanned: Option<usize>,
277}
278
279impl<'a> InventoryContext<'a> {
280 pub const fn new(
281 scope: &'a str,
282 scanner: &'a str,
283 source: &'a str,
284 root: Option<&'a str>,
285 files_scanned: Option<usize>,
286 ) -> Self {
287 Self {
288 scope,
289 scanner,
290 source,
291 root,
292 files_scanned,
293 }
294 }
295
296 pub const fn source_syntax(
297 source: &'a str,
298 root: Option<&'a str>,
299 files_scanned: Option<usize>,
300 ) -> Self {
301 Self::new(
302 INVENTORY_SCOPE_SOURCE_TREE,
303 INVENTORY_SCANNER_SOURCE_SYNTAX,
304 source,
305 root,
306 files_scanned,
307 )
308 }
309
310 pub const fn unknown_source_syntax() -> InventoryContext<'static> {
311 InventoryContext::source_syntax(INVENTORY_SOURCE_UNKNOWN, None, None)
312 }
313
314 pub const fn policy_migration(
315 source: &'a str,
316 root: Option<&'a str>,
317 files_scanned: Option<usize>,
318 ) -> Self {
319 Self::new(
320 INVENTORY_SCOPE_SOURCE_TREE,
321 INVENTORY_SCANNER_POLICY_MIGRATION,
322 source,
323 root,
324 files_scanned,
325 )
326 }
327}
328
329impl<'a> Default for InventoryContext<'a> {
330 fn default() -> Self {
331 Self::unknown_source_syntax()
332 }
333}
334
335#[derive(Debug, Clone, Copy, Default)]
336pub struct ReportContext<'a> {
337 pub inventory: InventoryContext<'a>,
338 pub baseline_debt_entries: Option<usize>,
339 pub policy_missing_evidence_entries: Option<usize>,
340 pub broken_evidence_links: Option<usize>,
341 pub weak_evidence_references: Option<usize>,
342 pub mode: Option<&'a str>,
343 pub enforcement: Option<&'a str>,
344 pub policy_config: Option<&'a str>,
345 pub tool_version: Option<&'a str>,
346}
347
348impl<'a> ReportContext<'a> {
349 pub const fn source_syntax(
350 inventory_source: &'a str,
351 source_tree_root: Option<&'a str>,
352 inventory_files: Option<usize>,
353 baseline_debt_entries: Option<usize>,
354 ) -> Self {
355 Self {
356 inventory: InventoryContext::source_syntax(
357 inventory_source,
358 source_tree_root,
359 inventory_files,
360 ),
361 baseline_debt_entries,
362 policy_missing_evidence_entries: None,
363 broken_evidence_links: None,
364 weak_evidence_references: None,
365 mode: None,
366 enforcement: None,
367 policy_config: None,
368 tool_version: None,
369 }
370 }
371}
372
373impl<'a> From<ReportContext<'a>> for InventoryContext<'a> {
374 fn from(context: ReportContext<'a>) -> Self {
375 context.inventory
376 }
377}