Skip to main content

canic_host/deployment_truth/model/execution/
mod.rs

1use super::inventory::ObservationStatusV1;
2use super::safety::SafetyFindingV1;
3use serde::{Deserialize, Serialize};
4
5///
6/// DeploymentReceiptV1
7///
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
9pub struct DeploymentReceiptV1 {
10    pub schema_version: u32,
11    pub operation_id: String,
12    pub plan_id: String,
13    pub execution_context: Option<DeploymentExecutionContextV1>,
14    pub operation_status: DeploymentExecutionStatusV1,
15    pub started_at: String,
16    pub finished_at: Option<String>,
17    pub operator_principal: Option<String>,
18    pub root_principal: Option<String>,
19    pub previous_observed_deployment_epoch: Option<u64>,
20    pub phase_receipts: Vec<PhaseReceiptV1>,
21    pub role_phase_receipts: Vec<RolePhaseReceiptV1>,
22    pub final_inventory_id: Option<String>,
23    pub command_result: DeploymentCommandResultV1,
24}
25
26///
27/// DeploymentExecutionContextV1
28///
29#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
30pub struct DeploymentExecutionContextV1 {
31    pub workspace_root: Option<String>,
32    pub icp_root: Option<String>,
33    pub artifact_roots: Vec<String>,
34    pub backend: DeploymentExecutorBackendV1,
35    pub backend_capabilities: Vec<DeploymentExecutorCapabilityV1>,
36}
37
38///
39/// DeploymentExecutionPreflightV1
40///
41#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
42pub struct DeploymentExecutionPreflightV1 {
43    pub schema_version: u32,
44    pub plan_id: String,
45    pub safety_report_id: String,
46    pub authority_plan_id: String,
47    pub backend: DeploymentExecutorBackendV1,
48    pub status: DeploymentExecutionPreflightStatusV1,
49    pub planned_phases: Vec<String>,
50    pub required_capabilities: Vec<DeploymentExecutorCapabilityV1>,
51    pub missing_capabilities: Vec<DeploymentExecutorCapabilityV1>,
52    pub blockers: Vec<SafetyFindingV1>,
53}
54
55///
56/// DeploymentExecutionPreflightStatusV1
57///
58#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
59pub enum DeploymentExecutionPreflightStatusV1 {
60    Ready,
61    Blocked,
62}
63
64impl DeploymentExecutionPreflightStatusV1 {
65    #[must_use]
66    pub const fn label(self) -> &'static str {
67        match self {
68            Self::Ready => "ready",
69            Self::Blocked => "blocked",
70        }
71    }
72}
73
74///
75/// DeploymentExecutorBackendV1
76///
77#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
78pub enum DeploymentExecutorBackendV1 {
79    CurrentCli,
80    PocketIc,
81    DirectAgent,
82    Other { name: String },
83}
84
85///
86/// DeploymentExecutorCapabilityV1
87///
88#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
89pub enum DeploymentExecutorCapabilityV1 {
90    CreateCanister,
91    CanisterStatus,
92    UpdateSettings,
93    InstallCode,
94    Call,
95    Query,
96    StageArtifact,
97}
98
99///
100/// PhaseReceiptV1
101///
102#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
103pub struct PhaseReceiptV1 {
104    pub phase: String,
105    pub started_at: String,
106    pub finished_at: Option<String>,
107    pub attempted_action: String,
108    pub verified_postcondition: VerifiedPostconditionV1,
109}
110
111///
112/// VerifiedPostconditionV1
113///
114#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
115pub struct VerifiedPostconditionV1 {
116    pub status: ObservationStatusV1,
117    pub evidence: Vec<String>,
118}
119
120///
121/// DeploymentExecutionStatusV1
122///
123#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
124pub enum DeploymentExecutionStatusV1 {
125    NotStarted,
126    InProgress,
127    FailedBeforeMutation,
128    PartiallyApplied,
129    FailedAfterMutation,
130    Complete,
131}
132
133impl DeploymentExecutionStatusV1 {
134    #[must_use]
135    pub const fn label(self) -> &'static str {
136        match self {
137            Self::NotStarted => "not_started",
138            Self::InProgress => "in_progress",
139            Self::FailedBeforeMutation => "failed_before_mutation",
140            Self::PartiallyApplied => "partially_applied",
141            Self::FailedAfterMutation => "failed_after_mutation",
142            Self::Complete => "complete",
143        }
144    }
145}
146
147///
148/// DeploymentCommandResultV1
149///
150#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
151pub enum DeploymentCommandResultV1 {
152    NotFinished,
153    Succeeded,
154    Failed { code: String, message: String },
155}
156
157///
158/// RolePhaseReceiptV1
159///
160#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
161pub struct RolePhaseReceiptV1 {
162    pub role: String,
163    pub phase: String,
164    pub result: RolePhaseResultV1,
165    pub previous_module_hash: Option<String>,
166    pub target_module_hash: Option<String>,
167    pub observed_module_hash_after: Option<String>,
168    pub artifact_digest: Option<String>,
169    pub canonical_embedded_config_sha256: Option<String>,
170    pub error: Option<String>,
171}
172
173///
174/// RolePhaseResultV1
175///
176#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
177pub enum RolePhaseResultV1 {
178    Applied,
179    Failed,
180    Skipped,
181    NotAttempted,
182    VerifiedAlreadyApplied,
183}
184
185#[cfg(test)]
186mod tests {
187    use super::*;
188
189    #[test]
190    fn deployment_execution_preflight_status_owns_text_labels() {
191        assert_eq!(DeploymentExecutionPreflightStatusV1::Ready.label(), "ready");
192        assert_eq!(
193            DeploymentExecutionPreflightStatusV1::Blocked.label(),
194            "blocked"
195        );
196    }
197
198    #[test]
199    fn deployment_execution_status_owns_text_labels() {
200        assert_eq!(
201            DeploymentExecutionStatusV1::NotStarted.label(),
202            "not_started"
203        );
204        assert_eq!(
205            DeploymentExecutionStatusV1::InProgress.label(),
206            "in_progress"
207        );
208        assert_eq!(
209            DeploymentExecutionStatusV1::FailedBeforeMutation.label(),
210            "failed_before_mutation"
211        );
212        assert_eq!(
213            DeploymentExecutionStatusV1::PartiallyApplied.label(),
214            "partially_applied"
215        );
216        assert_eq!(
217            DeploymentExecutionStatusV1::FailedAfterMutation.label(),
218            "failed_after_mutation"
219        );
220        assert_eq!(DeploymentExecutionStatusV1::Complete.label(), "complete");
221    }
222}