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