Skip to main content

allow_report/
contracts.rs

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";
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct ArtifactContract {
24    pub name: &'static str,
25    pub schema_id: &'static str,
26    pub schema_version: u32,
27    pub inventory_scanner: &'static str,
28    pub fixed_command: Option<&'static str>,
29}
30
31pub const ARTIFACT_STATUS_PASSED: &str = "passed";
32pub const ARTIFACT_STATUS_FAILED: &str = "failed";
33pub const ARTIFACT_STATUSES: &[&str] = &[ARTIFACT_STATUS_PASSED, ARTIFACT_STATUS_FAILED];
34
35pub const REPORT_COMMAND_AUDIT: &str = "audit";
36pub const REPORT_COMMAND_CHECK: &str = "check";
37pub const REPORT_COMMAND_DIFF: &str = "diff";
38pub const REPORT_COMMANDS: &[&str] = &[
39    REPORT_COMMAND_AUDIT,
40    REPORT_COMMAND_CHECK,
41    REPORT_COMMAND_DIFF,
42];
43pub const RECEIPT_COMMAND_CHECK: &str = "check";
44
45pub const INVENTORY_SCOPE_SOURCE_TREE: &str = "source_tree";
46pub const INVENTORY_SCANNER_SOURCE_SYNTAX: &str = "source_syntax";
47pub const INVENTORY_SCANNER_POLICY_MIGRATION: &str = "policy_migration";
48pub const INVENTORY_SOURCE_UNKNOWN: &str = "unknown";
49
50pub(crate) const ADD_ARTIFACT: ArtifactContract = ArtifactContract {
51    name: "add",
52    schema_id: ADD_SCHEMA_ID,
53    schema_version: ADD_SCHEMA_VERSION,
54    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
55    fixed_command: Some("add"),
56};
57
58pub(crate) const DOCTOR_ARTIFACT: ArtifactContract = ArtifactContract {
59    name: "doctor",
60    schema_id: DOCTOR_SCHEMA_ID,
61    schema_version: DOCTOR_SCHEMA_VERSION,
62    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
63    fixed_command: Some("doctor"),
64};
65
66pub(crate) const EXPLAIN_ARTIFACT: ArtifactContract = ArtifactContract {
67    name: "explain",
68    schema_id: EXPLAIN_SCHEMA_ID,
69    schema_version: EXPLAIN_SCHEMA_VERSION,
70    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
71    fixed_command: Some("explain"),
72};
73
74pub(crate) const LIST_ARTIFACT: ArtifactContract = ArtifactContract {
75    name: "list",
76    schema_id: LIST_SCHEMA_ID,
77    schema_version: LIST_SCHEMA_VERSION,
78    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
79    fixed_command: Some("list"),
80};
81
82pub(crate) const MIGRATE_ARTIFACT: ArtifactContract = ArtifactContract {
83    name: "migrate",
84    schema_id: MIGRATE_SCHEMA_ID,
85    schema_version: MIGRATE_SCHEMA_VERSION,
86    inventory_scanner: INVENTORY_SCANNER_POLICY_MIGRATION,
87    fixed_command: Some("migrate"),
88};
89
90pub(crate) const PROPOSE_ARTIFACT: ArtifactContract = ArtifactContract {
91    name: "propose",
92    schema_id: PROPOSE_SCHEMA_ID,
93    schema_version: PROPOSE_SCHEMA_VERSION,
94    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
95    fixed_command: Some("propose"),
96};
97
98pub(crate) const PRUNE_ARTIFACT: ArtifactContract = ArtifactContract {
99    name: "prune",
100    schema_id: PRUNE_SCHEMA_ID,
101    schema_version: PRUNE_SCHEMA_VERSION,
102    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
103    fixed_command: Some("prune"),
104};
105
106pub(crate) const RECEIPT_ARTIFACT: ArtifactContract = ArtifactContract {
107    name: "receipt",
108    schema_id: RECEIPT_SCHEMA_ID,
109    schema_version: RECEIPT_SCHEMA_VERSION,
110    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
111    fixed_command: Some(RECEIPT_COMMAND_CHECK),
112};
113
114pub(crate) const REPORT_ARTIFACT: ArtifactContract = ArtifactContract {
115    name: "report",
116    schema_id: REPORT_SCHEMA_ID,
117    schema_version: REPORT_SCHEMA_VERSION,
118    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
119    fixed_command: None,
120};
121
122pub(crate) const WORKLIST_ARTIFACT: ArtifactContract = ArtifactContract {
123    name: "worklist",
124    schema_id: WORKLIST_SCHEMA_ID,
125    schema_version: WORKLIST_SCHEMA_VERSION,
126    inventory_scanner: INVENTORY_SCANNER_SOURCE_SYNTAX,
127    fixed_command: Some("worklist"),
128};
129
130pub const ARTIFACT_CONTRACTS: &[ArtifactContract] = &[
131    ADD_ARTIFACT,
132    DOCTOR_ARTIFACT,
133    EXPLAIN_ARTIFACT,
134    LIST_ARTIFACT,
135    MIGRATE_ARTIFACT,
136    PROPOSE_ARTIFACT,
137    PRUNE_ARTIFACT,
138    RECEIPT_ARTIFACT,
139    REPORT_ARTIFACT,
140    WORKLIST_ARTIFACT,
141];
142
143pub fn artifact_contract_for_schema_id(schema_id: &str) -> Option<ArtifactContract> {
144    ARTIFACT_CONTRACTS
145        .iter()
146        .copied()
147        .find(|contract| contract.schema_id == schema_id)
148}
149
150pub const CLAIM_BOUNDARY: &[&str] = &[
151    "source_tree_inventory",
152    "source_syntax_only",
153    "cargo_metadata_not_invoked",
154    "cargo_commands_not_invoked",
155    "rustc_not_invoked",
156    "clippy_not_invoked",
157    "build_scripts_not_executed",
158    "proc_macros_not_executed",
159    "macro_expansion_not_analyzed",
160    "macro_token_tree_contents_not_analyzed",
161    "type_information_not_analyzed",
162    "mir_not_analyzed",
163    "build_output_not_analyzed",
164    "control_flow_not_analyzed",
165    "data_flow_not_analyzed",
166    "external_evidence_tools_not_invoked",
167    "repository_code_not_executed",
168];
169
170pub const SCANNER_LIMITATIONS: &[&str] = &[
171    "cargo_metadata_not_invoked",
172    "cargo_commands_not_invoked",
173    "rustc_not_invoked",
174    "clippy_not_invoked",
175    "build_scripts_not_executed",
176    "proc_macros_not_executed",
177    "macro_expansion_not_analyzed",
178    "macro_token_tree_contents_not_analyzed",
179    "type_information_not_analyzed",
180    "mir_not_analyzed",
181    "build_output_not_analyzed",
182    "control_flow_not_analyzed",
183    "data_flow_not_analyzed",
184    "external_evidence_tools_not_invoked",
185    "repository_code_not_executed",
186];
187
188pub 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.";
189
190#[derive(Debug, Clone, Copy)]
191pub struct InventoryContext<'a> {
192    pub scope: &'a str,
193    pub scanner: &'a str,
194    pub source: &'a str,
195    pub root: Option<&'a str>,
196    pub files_scanned: Option<usize>,
197}
198
199impl<'a> InventoryContext<'a> {
200    pub const fn new(
201        scope: &'a str,
202        scanner: &'a str,
203        source: &'a str,
204        root: Option<&'a str>,
205        files_scanned: Option<usize>,
206    ) -> Self {
207        Self {
208            scope,
209            scanner,
210            source,
211            root,
212            files_scanned,
213        }
214    }
215
216    pub const fn source_syntax(
217        source: &'a str,
218        root: Option<&'a str>,
219        files_scanned: Option<usize>,
220    ) -> Self {
221        Self::new(
222            INVENTORY_SCOPE_SOURCE_TREE,
223            INVENTORY_SCANNER_SOURCE_SYNTAX,
224            source,
225            root,
226            files_scanned,
227        )
228    }
229
230    pub const fn unknown_source_syntax() -> InventoryContext<'static> {
231        InventoryContext::source_syntax(INVENTORY_SOURCE_UNKNOWN, None, None)
232    }
233
234    pub const fn policy_migration(
235        source: &'a str,
236        root: Option<&'a str>,
237        files_scanned: Option<usize>,
238    ) -> Self {
239        Self::new(
240            INVENTORY_SCOPE_SOURCE_TREE,
241            INVENTORY_SCANNER_POLICY_MIGRATION,
242            source,
243            root,
244            files_scanned,
245        )
246    }
247}
248
249impl<'a> Default for InventoryContext<'a> {
250    fn default() -> Self {
251        Self::unknown_source_syntax()
252    }
253}
254
255#[derive(Debug, Clone, Copy, Default)]
256pub struct ReportContext<'a> {
257    pub inventory: InventoryContext<'a>,
258    pub baseline_debt_entries: Option<usize>,
259    pub policy_missing_evidence_entries: Option<usize>,
260    pub broken_evidence_links: Option<usize>,
261    pub weak_evidence_references: Option<usize>,
262}
263
264impl<'a> ReportContext<'a> {
265    pub const fn source_syntax(
266        inventory_source: &'a str,
267        source_tree_root: Option<&'a str>,
268        inventory_files: Option<usize>,
269        baseline_debt_entries: Option<usize>,
270    ) -> Self {
271        Self {
272            inventory: InventoryContext::source_syntax(
273                inventory_source,
274                source_tree_root,
275                inventory_files,
276            ),
277            baseline_debt_entries,
278            policy_missing_evidence_entries: None,
279            broken_evidence_links: None,
280            weak_evidence_references: None,
281        }
282    }
283}
284
285impl<'a> From<ReportContext<'a>> for InventoryContext<'a> {
286    fn from(context: ReportContext<'a>) -> Self {
287        context.inventory
288    }
289}