1use crate::ids::{FleetBinding, FleetKey, ReleaseBuildId};
8use candid::{CandidType, Principal};
9use serde::Deserialize;
10
11pub const MAX_FLEET_ACTIVATION_CANISTERS: usize = 4_096;
13pub const MAX_FLEET_CREDENTIAL_MANIFEST_ENTRIES: usize = 64;
15pub const MAX_FLEET_ACTIVATION_HOST_RECORD_BYTES: usize = 2_097_152;
17
18#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
24pub struct CurrentRootInstallIdentity {
25 pub fleet: FleetBinding,
26 pub install_id: [u8; 32],
27 pub release_build_id: ReleaseBuildId,
28 pub expected_module_hash: Option<[u8; 32]>,
29}
30
31#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
36pub struct FleetCascadeManifestEntry {
37 pub principal: Principal,
38 pub state_snapshot_hash: [u8; 32],
39 pub topology_snapshot_hash: [u8; 32],
40}
41
42#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
47pub enum FleetCascadeActivationEvidence {
48 Source {
49 cascade_manifest_hash: [u8; 32],
50 },
51 Applied {
52 state_snapshot_hash: [u8; 32],
53 topology_snapshot_hash: [u8; 32],
54 },
55}
56
57#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
62pub struct FleetCredentialGenerationRef {
63 pub generation: u64,
64 pub manifest_hash: [u8; 32],
65}
66
67#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
72pub struct FleetCredentialManifestEntry {
73 pub root_issuer: Principal,
74 pub subject_canister: Principal,
75 pub not_before_ns: u64,
76 pub expires_at_ns: u64,
77 pub key_identity_hash: [u8; 32],
78 pub cert_hash: [u8; 32],
79 pub proof_hash: [u8; 32],
80 pub bundle_hash: [u8; 32],
81}
82
83#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
88pub struct FleetCredentialManifest {
89 pub fleet: FleetKey,
90 pub activation_id: [u8; 32],
91 pub generation: u64,
92 pub root_policy_set_hash: [u8; 32],
93 pub renewal_template_set_hash: [u8; 32],
94 pub entries: Vec<FleetCredentialManifestEntry>,
95}
96
97#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
102pub struct FleetActivationIdentity {
103 pub fleet: FleetBinding,
104 pub operation_id: [u8; 32],
105 pub release_build_id: ReleaseBuildId,
106}
107
108#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
113pub enum FleetActivationPhase {
114 Prepared,
115 Active,
116}
117
118#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
123pub struct FleetActivationStatusResponse {
124 pub phase: FleetActivationPhase,
125 pub identity: FleetActivationIdentity,
126 pub cascade: Option<FleetCascadeActivationEvidence>,
127 pub cascade_manifest: Option<Vec<FleetCascadeManifestEntry>>,
128 pub credential: Option<FleetCredentialGenerationRef>,
129 pub credential_manifest: Option<FleetCredentialManifest>,
130 pub activated_at_ns: Option<u64>,
131}
132
133#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
134pub struct FleetActivationResumeRequest {
135 pub operation_id: [u8; 32],
136 pub credential: FleetCredentialGenerationRef,
137}
138
139#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
140pub struct FleetCredentialGenerationRequest {
141 pub operation_id: [u8; 32],
142 pub credential: FleetCredentialGenerationRef,
143}
144
145#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
146pub struct FleetActivationRequest {
147 pub operation_id: [u8; 32],
148 pub credential: FleetCredentialGenerationRef,
149 pub activation_evidence_hash: [u8; 32],
150}
151
152#[derive(Clone, Debug, Eq, PartialEq)]
157pub struct FleetHostCanisterActivationEvidence {
158 pub principal: Principal,
159 pub activation_evidence_hash: Option<[u8; 32]>,
160}
161
162#[derive(Clone, Debug, Eq, PartialEq)]
167pub struct FleetActivationHostRecord {
168 pub identity: FleetActivationIdentity,
169 pub cascade_manifest: Option<Vec<FleetCascadeManifestEntry>>,
170 pub credential: Option<FleetCredentialGenerationRef>,
171 pub credential_manifest: Option<FleetCredentialManifest>,
172 pub canisters: Vec<FleetHostCanisterActivationEvidence>,
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178 use crate::ids::{AppId, CanonicalNetworkId, FleetId, FleetKey, ReleaseBuildNonce};
179
180 fn fleet_binding() -> FleetBinding {
181 FleetBinding {
182 fleet: FleetKey {
183 network: CanonicalNetworkId::public_ic(),
184 fleet_id: FleetId::from_generated_bytes([7; 32]),
185 },
186 app: AppId::from("toko"),
187 }
188 }
189
190 #[test]
191 fn current_root_install_identity_roundtrips_with_text_ids() {
192 let input = CurrentRootInstallIdentity {
193 fleet: fleet_binding(),
194 install_id: [8; 32],
195 release_build_id: ReleaseBuildId::from_nonce(ReleaseBuildNonce::from_random_bytes(
196 [9; 32],
197 )),
198 expected_module_hash: Some([10; 32]),
199 };
200
201 let bytes = candid::encode_one(&input).expect("encode current root install identity");
202 let decoded: CurrentRootInstallIdentity =
203 candid::decode_one(&bytes).expect("decode current root install identity");
204
205 assert_eq!(decoded, input);
206 }
207
208 #[test]
209 fn fleet_activation_status_roundtrips_as_named_candid_shapes() {
210 let input = FleetActivationStatusResponse {
211 phase: FleetActivationPhase::Prepared,
212 identity: FleetActivationIdentity {
213 fleet: fleet_binding(),
214 operation_id: [11; 32],
215 release_build_id: ReleaseBuildId::from_nonce(ReleaseBuildNonce::from_random_bytes(
216 [12; 32],
217 )),
218 },
219 cascade: Some(FleetCascadeActivationEvidence::Source {
220 cascade_manifest_hash: [13; 32],
221 }),
222 cascade_manifest: Some(vec![FleetCascadeManifestEntry {
223 principal: Principal::from_slice(&[14; 29]),
224 state_snapshot_hash: [15; 32],
225 topology_snapshot_hash: [16; 32],
226 }]),
227 credential: None,
228 credential_manifest: None,
229 activated_at_ns: None,
230 };
231
232 let bytes = candid::encode_one(&input).expect("encode activation status");
233 let decoded: FleetActivationStatusResponse =
234 candid::decode_one(&bytes).expect("decode activation status");
235
236 assert_eq!(decoded, input);
237 }
238}