1use super::inventory::ObservationStatusV1;
2use super::safety::SafetyFindingV1;
3use serde::{Deserialize, Serialize};
4
5#[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#[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#[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#[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#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
78pub enum DeploymentExecutorBackendV1 {
79 CurrentCli,
80 PocketIc,
81 DirectAgent,
82 Other { name: String },
83}
84
85#[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#[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#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
115pub struct VerifiedPostconditionV1 {
116 pub status: ObservationStatusV1,
117 pub evidence: Vec<String>,
118}
119
120#[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#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
151pub enum DeploymentCommandResultV1 {
152 NotFinished,
153 Succeeded,
154 Failed { code: String, message: String },
155}
156
157#[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#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
177pub enum RolePhaseResultV1 {
178 Applied,
179 Failed,
180 Skipped,
181 NotAttempted,
182 VerifiedAlreadyApplied,
183}
184
185impl RolePhaseResultV1 {
186 #[must_use]
187 pub const fn label(self) -> &'static str {
188 match self {
189 Self::Applied => "Applied",
190 Self::Failed => "Failed",
191 Self::Skipped => "Skipped",
192 Self::NotAttempted => "NotAttempted",
193 Self::VerifiedAlreadyApplied => "VerifiedAlreadyApplied",
194 }
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn deployment_execution_preflight_status_owns_text_labels() {
204 assert_eq!(DeploymentExecutionPreflightStatusV1::Ready.label(), "ready");
205 assert_eq!(
206 DeploymentExecutionPreflightStatusV1::Blocked.label(),
207 "blocked"
208 );
209 }
210
211 #[test]
212 fn deployment_execution_status_owns_text_labels() {
213 assert_eq!(
214 DeploymentExecutionStatusV1::NotStarted.label(),
215 "not_started"
216 );
217 assert_eq!(
218 DeploymentExecutionStatusV1::InProgress.label(),
219 "in_progress"
220 );
221 assert_eq!(
222 DeploymentExecutionStatusV1::FailedBeforeMutation.label(),
223 "failed_before_mutation"
224 );
225 assert_eq!(
226 DeploymentExecutionStatusV1::PartiallyApplied.label(),
227 "partially_applied"
228 );
229 assert_eq!(
230 DeploymentExecutionStatusV1::FailedAfterMutation.label(),
231 "failed_after_mutation"
232 );
233 assert_eq!(DeploymentExecutionStatusV1::Complete.label(), "complete");
234 }
235
236 #[test]
237 fn role_phase_result_owns_text_labels() {
238 assert_eq!(RolePhaseResultV1::Applied.label(), "Applied");
239 assert_eq!(RolePhaseResultV1::Failed.label(), "Failed");
240 assert_eq!(RolePhaseResultV1::Skipped.label(), "Skipped");
241 assert_eq!(RolePhaseResultV1::NotAttempted.label(), "NotAttempted");
242 assert_eq!(
243 RolePhaseResultV1::VerifiedAlreadyApplied.label(),
244 "VerifiedAlreadyApplied"
245 );
246 }
247}