Skip to main content

canic_host/deployment_truth/model/lifecycle/authority/
mod.rs

1use super::super::CanisterControlClassV1;
2use serde::{Deserialize, Serialize};
3
4///
5/// LifecycleAuthorityReportV1
6///
7#[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///
21/// LifecycleAuthorityV1
22///
23#[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///
45/// LifecycleModeV1
46///
47#[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///
74/// LifecycleUpgradeModeV1
75///
76#[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///
87/// LifecycleVerificationRequirementV1
88///
89#[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///
112/// ConsentRequirementV1
113///
114#[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///
124/// ConsentSubjectKindV1
125///
126#[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///
153/// ConsentChannelKindV1
154///
155#[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///
178/// ExternalUpgradeAuthorizationModeV1
179///
180#[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}