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 transforms: Vec<ArtifactTransformProvenanceV1>,
32 pub warnings: Vec<EvidenceMessageV1>,
33}
34
35#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
37pub struct ProtocolProfileProvenanceV1 {
38 pub candid_sha256: String,
39 pub protocol_profile_digest: String,
40}
41
42#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
46#[serde(rename_all = "snake_case")]
47pub enum BuildProvenanceStatusV1 {
48 Success,
49 Failed,
50 NotRecorded,
51}
52
53#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub struct SourceProvenanceV1 {
58 pub schema_version: u8,
59 pub vcs: SourceVcsV1,
60 pub revision: Option<String>,
61 pub branch: Option<String>,
62 pub dirty: Option<bool>,
63 pub dirty_policy: SourceDirtyPolicyV1,
64 pub dirty_summary_digest: Option<String>,
65 pub dirty_summary_algorithm: Option<String>,
66}
67
68#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
72#[serde(rename_all = "snake_case")]
73pub enum SourceVcsV1 {
74 Git,
75 Unknown,
76}
77
78#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
82#[serde(rename_all = "snake_case")]
83pub enum SourceDirtyPolicyV1 {
84 Clean,
85 DirtyRecorded,
86 Unknown,
87}
88
89#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
93pub struct CargoProvenanceV1 {
94 pub cargo_lock_sha256: Option<String>,
95 pub package_manifest_sha256: Option<String>,
96 pub package_name: String,
97 pub package_manifest: String,
98 pub package_metadata_app: String,
99 pub package_metadata_role: String,
100 pub rustc_version: Option<String>,
101 pub cargo_version: Option<String>,
102 pub target: Option<String>,
103 pub profile: String,
104 pub features: Vec<String>,
105 pub default_features: Option<bool>,
106 pub rustflags_digest: Option<String>,
107 pub rustflags_digest_algorithm: Option<String>,
108 pub cargo_config_fingerprints: Vec<InputFingerprintV1>,
109 pub build_script_inputs: BuildScriptInputStateV1,
110}
111
112#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
116#[serde(rename_all = "snake_case")]
117pub enum BuildScriptInputStateV1 {
118 NotRecorded,
119 Recorded,
120 Unknown,
121}
122
123#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
127pub struct ArtifactProvenanceV1 {
128 pub role: String,
129 pub app: String,
130 pub artifact_kind: ArtifactProvenanceKindV1,
131 pub path: Option<String>,
132 pub path_display: InputPathDisplayV1,
133 pub hash_algorithm: String,
134 pub sha256: String,
135 pub size_bytes: u64,
136 pub produced_by: String,
137}
138
139#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
143#[serde(rename_all = "snake_case")]
144pub enum ArtifactProvenanceKindV1 {
145 Wasm,
146 WasmGzip,
147 Candid,
148 Metadata,
149 Other,
150}
151
152#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
156pub struct ArtifactTransformProvenanceV1 {
157 pub role: String,
158 pub transform: ArtifactTransformKindV1,
159 pub tool: String,
160 pub tool_version: Option<String>,
161 pub tool_sha256: Option<String>,
162 pub outcome: ArtifactTransformOutcomeV1,
163 pub metrics: Option<WasmTransformMetricsV1>,
164}
165
166#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
168#[serde(rename_all = "snake_case")]
169pub enum ArtifactTransformKindV1 {
170 Shrink,
171 CandidMetadata,
172 Optimize,
173}
174
175#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
177#[serde(rename_all = "snake_case")]
178pub enum ArtifactTransformOutcomeV1 {
179 Applied,
180 NotRequested,
181}
182
183#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
185pub struct WasmTransformMetricsV1 {
186 pub before: WasmArtifactMetricsV1,
187 pub after: WasmArtifactMetricsV1,
188}
189
190#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
192pub struct WasmArtifactMetricsV1 {
193 pub raw_bytes: u64,
194 pub gzip_bytes: u64,
195 pub code_section_bytes: u64,
196 pub data_section_bytes: u64,
197 pub defined_functions: u32,
198}
199
200#[derive(Clone, Debug)]
204pub struct BuildProvenanceRequest {
205 pub app: String,
206 pub role: String,
207 pub environment: String,
208 pub build_network: BuildNetwork,
209 pub profile: CanisterBuildProfile,
210 pub workspace_root: PathBuf,
211 pub config_path: PathBuf,
212 pub output: CanisterArtifactBuildOutput,
213 pub command: CommandProvenanceV1,
214 pub generated_at: String,
215 pub canic_version: String,
216}