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 protocol_profile: ProtocolProfileProvenanceV1,
30    pub artifacts: Vec<ArtifactProvenanceV1>,
31    pub transforms: Vec<ArtifactTransformProvenanceV1>,
32    pub warnings: Vec<EvidenceMessageV1>,
33}
34
35/// Exact generated binding identity carried beside one build artifact.
36#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
37pub struct ProtocolProfileProvenanceV1 {
38    pub candid_sha256: String,
39    pub protocol_profile_digest: String,
40}
41
42///
43/// BuildProvenanceStatusV1
44///
45#[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///
54/// SourceProvenanceV1
55///
56#[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///
69/// SourceVcsV1
70///
71#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
72#[serde(rename_all = "snake_case")]
73pub enum SourceVcsV1 {
74    Git,
75    Unknown,
76}
77
78///
79/// SourceDirtyPolicyV1
80///
81#[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///
90/// CargoProvenanceV1
91///
92#[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///
113/// BuildScriptInputStateV1
114///
115#[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///
124/// ArtifactProvenanceV1
125///
126#[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///
140/// ArtifactProvenanceKindV1
141///
142#[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///
153/// ArtifactTransformProvenanceV1
154///
155#[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 outcome: ArtifactTransformOutcomeV1,
162}
163
164/// Artifact-changing operation selected by the host builder.
165#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
166#[serde(rename_all = "snake_case")]
167pub enum ArtifactTransformKindV1 {
168    Shrink,
169    CandidMetadata,
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 app: 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}