Skip to main content

canic_host/build_provenance/
model.rs

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///
18/// BuildProvenanceV1
19///
20#[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///
35/// BuildProvenanceStatusV1
36///
37#[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///
46/// SourceProvenanceV1
47///
48#[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///
61/// SourceVcsV1
62///
63#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
64#[serde(rename_all = "snake_case")]
65pub enum SourceVcsV1 {
66    Git,
67    Unknown,
68}
69
70///
71/// SourceDirtyPolicyV1
72///
73#[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///
82/// CargoProvenanceV1
83///
84#[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///
105/// BuildScriptInputStateV1
106///
107#[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///
116/// ArtifactProvenanceV1
117///
118#[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///
132/// ArtifactProvenanceKindV1
133///
134#[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///
145/// ArtifactTransformProvenanceV1
146///
147#[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/// Artifact-changing operation selected by the host builder.
158#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
159#[serde(rename_all = "snake_case")]
160pub enum ArtifactTransformKindV1 {
161    Shrink,
162    CandidMetadata,
163}
164
165/// Admission mode for an artifact transform.
166#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
167#[serde(rename_all = "snake_case")]
168pub enum ArtifactTransformModeV1 {
169    Optional,
170}
171
172/// Recorded outcome of one artifact transform decision.
173#[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///
182/// BuildProvenanceRequest
183///
184#[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}