1use super::super::CanisterControlClassV1;
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub struct LifecycleAuthorityReportV1 {
9 pub schema_version: u32,
10 pub report_id: String,
11 pub report_digest: String,
12 pub check_id: String,
13 pub plan_id: String,
14 pub inventory_id: String,
15 pub authorities: Vec<LifecycleAuthorityV1>,
16 pub external_action_required_count: usize,
17 pub blocked_count: usize,
18}
19
20#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
24pub struct LifecycleAuthorityV1 {
25 pub subject: String,
26 pub canister_id: Option<String>,
27 pub role: Option<String>,
28 pub control_class: CanisterControlClassV1,
29 pub lifecycle_mode: LifecycleModeV1,
30 pub observed_controllers: Vec<String>,
31 pub expected_deployment_controllers: Vec<String>,
32 pub external_controllers: Vec<String>,
33 pub required_controllers: Vec<String>,
34 pub consent_requirements: Vec<ConsentRequirementV1>,
35 pub allowed_upgrade_modes: Vec<LifecycleUpgradeModeV1>,
36 pub verification_requirements: Vec<LifecycleVerificationRequirementV1>,
37 pub external_action_required: bool,
38 pub blocked: bool,
39 pub blockers: Vec<String>,
40 pub warnings: Vec<String>,
41 pub reason: String,
42}
43
44#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
48pub enum LifecycleModeV1 {
49 DirectDeploymentAuthority,
50 ProposalRequired,
51 DelegatedInstallRequired,
52 ExternalCompletionOnly,
53 VerifyOnly,
54 MustNotTouch,
55 UnknownUnsafeBlocked,
56}
57
58impl LifecycleModeV1 {
59 #[must_use]
60 pub const fn label(self) -> &'static str {
61 match self {
62 Self::DirectDeploymentAuthority => "direct_deployment_authority",
63 Self::ProposalRequired => "proposal_required",
64 Self::DelegatedInstallRequired => "delegated_install_required",
65 Self::ExternalCompletionOnly => "external_completion_only",
66 Self::VerifyOnly => "verify_only",
67 Self::MustNotTouch => "must_not_touch",
68 Self::UnknownUnsafeBlocked => "unknown_unsafe_blocked",
69 }
70 }
71}
72
73#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
77pub enum LifecycleUpgradeModeV1 {
78 DirectByDeploymentAuthority,
79 ExternalProposal,
80 ExternalExecution,
81 VerifyExternalCompletion,
82 ObserveOnly,
83 Blocked,
84}
85
86#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
90pub enum LifecycleVerificationRequirementV1 {
91 LiveInventory,
92 ControllerObservation,
93 ModuleHash,
94 CanonicalEmbeddedConfig,
95 ProtectedCallReadiness,
96}
97
98impl LifecycleVerificationRequirementV1 {
99 #[must_use]
100 pub const fn label(self) -> &'static str {
101 match self {
102 Self::LiveInventory => "live_inventory",
103 Self::ControllerObservation => "controller_observation",
104 Self::ModuleHash => "module_hash",
105 Self::CanonicalEmbeddedConfig => "canonical_embedded_config",
106 Self::ProtectedCallReadiness => "protected_call_readiness",
107 }
108 }
109}
110
111#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
115pub struct ConsentRequirementV1 {
116 pub consent_subject_kind: ConsentSubjectKindV1,
117 pub required_principals: Vec<String>,
118 pub required_controller_set_digest: Option<String>,
119 pub consent_channel_kind: ConsentChannelKindV1,
120 pub required_action: ExternalUpgradeAuthorizationModeV1,
121}
122
123#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
127pub enum ConsentSubjectKindV1 {
128 UserPrincipal,
129 ProjectHub,
130 GovernanceCanister,
131 CustomerController,
132 DelegatedInstallCanister,
133 MultisigAuthority,
134 UnknownExternalController,
135}
136
137impl ConsentSubjectKindV1 {
138 #[must_use]
139 pub const fn label(self) -> &'static str {
140 match self {
141 Self::UserPrincipal => "user_principal",
142 Self::ProjectHub => "project_hub",
143 Self::GovernanceCanister => "governance_canister",
144 Self::CustomerController => "customer_controller",
145 Self::DelegatedInstallCanister => "delegated_install_canister",
146 Self::MultisigAuthority => "multisig_authority",
147 Self::UnknownExternalController => "unknown_external_controller",
148 }
149 }
150}
151
152#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
156pub enum ConsentChannelKindV1 {
157 OutOfBand,
158 GeneratedCommand,
159 DelegatedInstall,
160 GovernanceProposal,
161 ApplicationSpecific,
162}
163
164impl ConsentChannelKindV1 {
165 #[must_use]
166 pub const fn label(self) -> &'static str {
167 match self {
168 Self::OutOfBand => "out_of_band",
169 Self::GeneratedCommand => "generated_command",
170 Self::DelegatedInstall => "delegated_install",
171 Self::GovernanceProposal => "governance_proposal",
172 Self::ApplicationSpecific => "application_specific",
173 }
174 }
175}
176
177#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
181pub enum ExternalUpgradeAuthorizationModeV1 {
182 ConsentForDirectInstall,
183 DelegatedInstallAuthority,
184 ExternalControllerExecution,
185 ObserveAndVerifyOnly,
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn lifecycle_mode_owns_text_labels() {
194 assert_eq!(
195 LifecycleModeV1::DirectDeploymentAuthority.label(),
196 "direct_deployment_authority"
197 );
198 assert_eq!(
199 LifecycleModeV1::ProposalRequired.label(),
200 "proposal_required"
201 );
202 assert_eq!(
203 LifecycleModeV1::DelegatedInstallRequired.label(),
204 "delegated_install_required"
205 );
206 assert_eq!(
207 LifecycleModeV1::ExternalCompletionOnly.label(),
208 "external_completion_only"
209 );
210 assert_eq!(LifecycleModeV1::VerifyOnly.label(), "verify_only");
211 assert_eq!(LifecycleModeV1::MustNotTouch.label(), "must_not_touch");
212 assert_eq!(
213 LifecycleModeV1::UnknownUnsafeBlocked.label(),
214 "unknown_unsafe_blocked"
215 );
216 }
217
218 #[test]
219 fn lifecycle_verification_requirement_owns_text_labels() {
220 assert_eq!(
221 LifecycleVerificationRequirementV1::LiveInventory.label(),
222 "live_inventory"
223 );
224 assert_eq!(
225 LifecycleVerificationRequirementV1::ControllerObservation.label(),
226 "controller_observation"
227 );
228 assert_eq!(
229 LifecycleVerificationRequirementV1::ModuleHash.label(),
230 "module_hash"
231 );
232 assert_eq!(
233 LifecycleVerificationRequirementV1::CanonicalEmbeddedConfig.label(),
234 "canonical_embedded_config"
235 );
236 assert_eq!(
237 LifecycleVerificationRequirementV1::ProtectedCallReadiness.label(),
238 "protected_call_readiness"
239 );
240 }
241
242 #[test]
243 fn consent_subject_kind_owns_text_labels() {
244 assert_eq!(
245 ConsentSubjectKindV1::UserPrincipal.label(),
246 "user_principal"
247 );
248 assert_eq!(ConsentSubjectKindV1::ProjectHub.label(), "project_hub");
249 assert_eq!(
250 ConsentSubjectKindV1::GovernanceCanister.label(),
251 "governance_canister"
252 );
253 assert_eq!(
254 ConsentSubjectKindV1::CustomerController.label(),
255 "customer_controller"
256 );
257 assert_eq!(
258 ConsentSubjectKindV1::DelegatedInstallCanister.label(),
259 "delegated_install_canister"
260 );
261 assert_eq!(
262 ConsentSubjectKindV1::MultisigAuthority.label(),
263 "multisig_authority"
264 );
265 assert_eq!(
266 ConsentSubjectKindV1::UnknownExternalController.label(),
267 "unknown_external_controller"
268 );
269 }
270
271 #[test]
272 fn consent_channel_kind_owns_text_labels() {
273 assert_eq!(ConsentChannelKindV1::OutOfBand.label(), "out_of_band");
274 assert_eq!(
275 ConsentChannelKindV1::GeneratedCommand.label(),
276 "generated_command"
277 );
278 assert_eq!(
279 ConsentChannelKindV1::DelegatedInstall.label(),
280 "delegated_install"
281 );
282 assert_eq!(
283 ConsentChannelKindV1::GovernanceProposal.label(),
284 "governance_proposal"
285 );
286 assert_eq!(
287 ConsentChannelKindV1::ApplicationSpecific.label(),
288 "application_specific"
289 );
290 }
291}