1use std::path::PathBuf;
2
3use canic_core::ids::BuildNetwork;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 canister_build::{CanisterArtifactBuildOutput, CanisterBuildProfile},
8 evidence_envelope::{
9 CommandProvenanceV1, EvidenceMessageV1, InputFingerprintV1, InputPathDisplayV1,
10 },
11};
12
13pub const BUILD_PROVENANCE_SCHEMA_ID: &str = "canic.build_provenance.v1";
14pub(super) const WASM_TARGET: &str = "wasm32-unknown-unknown";
15pub(super) const DIRTY_SUMMARY_ALGORITHM: &str = "git-status-porcelain-v1-z-sha256";
16
17#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
21pub struct BuildProvenanceV1 {
22 pub schema_version: u8,
23 pub generated_at: String,
24 pub canic_version: String,
25 pub command: CommandProvenanceV1,
26 pub build_status: BuildProvenanceStatusV1,
27 pub source: SourceProvenanceV1,
28 pub cargo: CargoProvenanceV1,
29 pub protocol_profile: ProtocolProfileProvenanceV1,
30 pub artifacts: Vec<ArtifactProvenanceV1>,
31 pub final_wasm_metrics: WasmArtifactMetricsV1,
32 pub transforms: Vec<ArtifactTransformProvenanceV1>,
33 pub warnings: Vec<EvidenceMessageV1>,
34}
35
36#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub struct ProtocolProfileProvenanceV1 {
39 pub candid_sha256: String,
40 pub protocol_profile_digest: String,
41}
42
43#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
47#[serde(rename_all = "snake_case")]
48pub enum BuildProvenanceStatusV1 {
49 Success,
50 Failed,
51 NotRecorded,
52}
53
54#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
58pub struct SourceProvenanceV1 {
59 pub schema_version: u8,
60 pub vcs: SourceVcsV1,
61 pub revision: Option<String>,
62 pub branch: Option<String>,
63 pub dirty: Option<bool>,
64 pub dirty_policy: SourceDirtyPolicyV1,
65 pub dirty_summary_digest: Option<String>,
66 pub dirty_summary_algorithm: Option<String>,
67}
68
69#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
73#[serde(rename_all = "snake_case")]
74pub enum SourceVcsV1 {
75 Git,
76 Unknown,
77}
78
79#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
83#[serde(rename_all = "snake_case")]
84pub enum SourceDirtyPolicyV1 {
85 Clean,
86 DirtyRecorded,
87 Unknown,
88}
89
90#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94pub struct CargoProvenanceV1 {
95 pub cargo_lock_sha256: Option<String>,
96 pub package_manifest_sha256: Option<String>,
97 pub package_name: String,
98 pub package_manifest: String,
99 pub package_metadata_app: String,
100 pub package_metadata_role: String,
101 pub rustc_version: Option<String>,
102 pub cargo_version: Option<String>,
103 pub target: Option<String>,
104 pub profile: String,
105 pub features: Vec<String>,
106 pub default_features: Option<bool>,
107 pub rustflags_digest: Option<String>,
108 pub rustflags_digest_algorithm: Option<String>,
109 pub cargo_config_fingerprints: Vec<InputFingerprintV1>,
110 pub build_script_inputs: BuildScriptInputStateV1,
111}
112
113#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
117#[serde(rename_all = "snake_case")]
118pub enum BuildScriptInputStateV1 {
119 NotRecorded,
120 Recorded,
121 Unknown,
122}
123
124#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
128pub struct ArtifactProvenanceV1 {
129 pub role: String,
130 pub app: String,
131 pub artifact_kind: ArtifactProvenanceKindV1,
132 pub path: Option<String>,
133 pub path_display: InputPathDisplayV1,
134 pub hash_algorithm: String,
135 pub sha256: String,
136 pub size_bytes: u64,
137 pub produced_by: String,
138}
139
140#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
144#[serde(rename_all = "snake_case")]
145pub enum ArtifactProvenanceKindV1 {
146 Wasm,
147 WasmGzip,
148 Candid,
149 Metadata,
150 Other,
151}
152
153#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
157pub struct ArtifactTransformProvenanceV1 {
158 pub role: String,
159 pub transform: ArtifactTransformKindV1,
160 pub tool: String,
161 pub tool_version: Option<String>,
162 pub tool_sha256: Option<String>,
163 pub outcome: ArtifactTransformOutcomeV1,
164 pub metrics: Option<WasmTransformMetricsV1>,
165}
166
167#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
169#[serde(rename_all = "snake_case")]
170pub enum ArtifactTransformKindV1 {
171 Shrink,
172 CandidMetadata,
173 Optimize,
174}
175
176#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
178#[serde(rename_all = "snake_case")]
179pub enum ArtifactTransformOutcomeV1 {
180 Applied,
181 NotRequested,
182}
183
184#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
186pub struct WasmTransformMetricsV1 {
187 pub before: WasmArtifactMetricsV1,
188 pub after: WasmArtifactMetricsV1,
189}
190
191#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
193pub struct WasmArtifactMetricsV1 {
194 pub raw_bytes: u64,
195 pub gzip_bytes: u64,
196 pub code_section_bytes: u64,
197 pub data_section_bytes: u64,
198 pub defined_functions: u32,
199}
200
201#[derive(Clone, Debug)]
205pub struct BuildProvenanceRequest {
206 pub app: String,
207 pub role: String,
208 pub environment: String,
209 pub build_network: BuildNetwork,
210 pub profile: CanisterBuildProfile,
211 pub workspace_root: PathBuf,
212 pub config_path: PathBuf,
213 pub output: CanisterArtifactBuildOutput,
214 pub command: CommandProvenanceV1,
215 pub generated_at: String,
216 pub canic_version: String,
217}