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 artifacts: Vec<ArtifactProvenanceV1>,
30 pub transforms: Vec<ArtifactTransformProvenanceV1>,
31 pub warnings: Vec<EvidenceMessageV1>,
32}
33
34#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
38#[serde(rename_all = "snake_case")]
39pub enum BuildProvenanceStatusV1 {
40 Success,
41 Failed,
42 NotRecorded,
43}
44
45#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
49pub struct SourceProvenanceV1 {
50 pub schema_version: u8,
51 pub vcs: SourceVcsV1,
52 pub revision: Option<String>,
53 pub branch: Option<String>,
54 pub dirty: Option<bool>,
55 pub dirty_policy: SourceDirtyPolicyV1,
56 pub dirty_summary_digest: Option<String>,
57 pub dirty_summary_algorithm: Option<String>,
58}
59
60#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
64#[serde(rename_all = "snake_case")]
65pub enum SourceVcsV1 {
66 Git,
67 Unknown,
68}
69
70#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
74#[serde(rename_all = "snake_case")]
75pub enum SourceDirtyPolicyV1 {
76 Clean,
77 DirtyRecorded,
78 Unknown,
79}
80
81#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
85pub struct CargoProvenanceV1 {
86 pub cargo_lock_sha256: Option<String>,
87 pub package_manifest_sha256: Option<String>,
88 pub package_name: String,
89 pub package_manifest: String,
90 pub package_metadata_fleet: String,
91 pub package_metadata_role: String,
92 pub rustc_version: Option<String>,
93 pub cargo_version: Option<String>,
94 pub target: Option<String>,
95 pub profile: String,
96 pub features: Vec<String>,
97 pub default_features: Option<bool>,
98 pub rustflags_digest: Option<String>,
99 pub rustflags_digest_algorithm: Option<String>,
100 pub cargo_config_fingerprints: Vec<InputFingerprintV1>,
101 pub build_script_inputs: BuildScriptInputStateV1,
102}
103
104#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
108#[serde(rename_all = "snake_case")]
109pub enum BuildScriptInputStateV1 {
110 NotRecorded,
111 Recorded,
112 Unknown,
113}
114
115#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct ArtifactProvenanceV1 {
120 pub role: String,
121 pub fleet: String,
122 pub artifact_kind: ArtifactProvenanceKindV1,
123 pub path: Option<String>,
124 pub path_display: InputPathDisplayV1,
125 pub hash_algorithm: String,
126 pub sha256: String,
127 pub size_bytes: u64,
128 pub produced_by: String,
129}
130
131#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
135#[serde(rename_all = "snake_case")]
136pub enum ArtifactProvenanceKindV1 {
137 Wasm,
138 WasmGzip,
139 Candid,
140 Metadata,
141 Other,
142}
143
144#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
148pub struct ArtifactTransformProvenanceV1 {
149 pub role: String,
150 pub transform: ArtifactTransformKindV1,
151 pub mode: ArtifactTransformModeV1,
152 pub tool: String,
153 pub tool_version: Option<String>,
154 pub outcome: ArtifactTransformOutcomeV1,
155}
156
157#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
159#[serde(rename_all = "snake_case")]
160pub enum ArtifactTransformKindV1 {
161 Shrink,
162 CandidMetadata,
163}
164
165#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
167#[serde(rename_all = "snake_case")]
168pub enum ArtifactTransformModeV1 {
169 Optional,
170}
171
172#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
174#[serde(rename_all = "snake_case")]
175pub enum ArtifactTransformOutcomeV1 {
176 Applied,
177 ToolUnavailable,
178 NotRequested,
179}
180
181#[derive(Clone, Debug)]
185pub struct BuildProvenanceRequest {
186 pub fleet: String,
187 pub role: String,
188 pub environment: String,
189 pub build_network: BuildNetwork,
190 pub profile: CanisterBuildProfile,
191 pub workspace_root: PathBuf,
192 pub config_path: PathBuf,
193 pub output: CanisterArtifactBuildOutput,
194 pub command: CommandProvenanceV1,
195 pub generated_at: String,
196 pub canic_version: String,
197}