1use crate::ids::{FleetBinding, FleetKey, ReleaseBuildId};
8use candid::{CandidType, Principal};
9use serde::Deserialize;
10
11#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
17pub struct CurrentRootInstallIdentity {
18 pub fleet: FleetBinding,
19 pub install_id: [u8; 32],
20 pub release_build_id: ReleaseBuildId,
21 pub expected_module_hash: Option<[u8; 32]>,
22}
23
24#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
29pub struct FleetCascadeManifestEntry {
30 pub principal: Principal,
31 pub state_snapshot_hash: [u8; 32],
32 pub topology_snapshot_hash: [u8; 32],
33}
34
35#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
40pub enum FleetCascadeActivationEvidence {
41 Source {
42 cascade_manifest_hash: [u8; 32],
43 },
44 Applied {
45 state_snapshot_hash: [u8; 32],
46 topology_snapshot_hash: [u8; 32],
47 },
48}
49
50#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
55pub struct FleetCredentialGenerationRef {
56 pub generation: u64,
57 pub manifest_hash: [u8; 32],
58}
59
60#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
65pub struct FleetCredentialManifestEntry {
66 pub root_issuer: Principal,
67 pub subject_canister: Principal,
68 pub not_before_ns: u64,
69 pub expires_at_ns: u64,
70 pub key_identity_hash: [u8; 32],
71 pub cert_hash: [u8; 32],
72 pub proof_hash: [u8; 32],
73 pub bundle_hash: [u8; 32],
74}
75
76#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
81pub struct FleetCredentialManifest {
82 pub fleet: FleetKey,
83 pub activation_id: [u8; 32],
84 pub generation: u64,
85 pub root_policy_set_hash: [u8; 32],
86 pub renewal_template_set_hash: [u8; 32],
87 pub entries: Vec<FleetCredentialManifestEntry>,
88}
89
90#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
95pub struct FleetActivationIdentity {
96 pub fleet: FleetBinding,
97 pub operation_id: [u8; 32],
98 pub release_build_id: ReleaseBuildId,
99}
100
101#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
106pub enum FleetActivationPhase {
107 Prepared,
108 Active,
109}
110
111#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
116pub struct FleetActivationStatusResponse {
117 pub phase: FleetActivationPhase,
118 pub identity: FleetActivationIdentity,
119 pub cascade: Option<FleetCascadeActivationEvidence>,
120 pub cascade_manifest: Option<Vec<FleetCascadeManifestEntry>>,
121 pub credential: Option<FleetCredentialGenerationRef>,
122 pub credential_manifest: Option<FleetCredentialManifest>,
123 pub activated_at_ns: Option<u64>,
124}
125
126#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
127pub struct FleetActivationResumeRequest {
128 pub operation_id: [u8; 32],
129 pub credential: FleetCredentialGenerationRef,
130}
131
132#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
133pub struct FleetCredentialGenerationRequest {
134 pub operation_id: [u8; 32],
135 pub credential: FleetCredentialGenerationRef,
136}
137
138#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
139pub struct FleetActivationRequest {
140 pub operation_id: [u8; 32],
141 pub credential: FleetCredentialGenerationRef,
142 pub activation_evidence_hash: [u8; 32],
143}
144
145#[derive(Clone, Debug, Eq, PartialEq)]
150pub struct FleetHostCanisterActivationEvidence {
151 pub principal: Principal,
152 pub activation_evidence_hash: Option<[u8; 32]>,
153}
154
155#[derive(Clone, Debug, Eq, PartialEq)]
160pub struct FleetActivationHostRecord {
161 pub identity: FleetActivationIdentity,
162 pub cascade_manifest: Option<Vec<FleetCascadeManifestEntry>>,
163 pub credential: Option<FleetCredentialGenerationRef>,
164 pub credential_manifest: Option<FleetCredentialManifest>,
165 pub canisters: Vec<FleetHostCanisterActivationEvidence>,
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 use crate::ids::{AppId, CanonicalNetworkId, FleetId, FleetKey, ReleaseBuildNonce};
172
173 fn fleet_binding() -> FleetBinding {
174 FleetBinding {
175 fleet: FleetKey {
176 network: CanonicalNetworkId::public_ic(),
177 fleet_id: FleetId::from_generated_bytes([7; 32]),
178 },
179 app: AppId::from("toko"),
180 }
181 }
182
183 #[test]
184 fn current_root_install_identity_roundtrips_with_text_ids() {
185 let input = CurrentRootInstallIdentity {
186 fleet: fleet_binding(),
187 install_id: [8; 32],
188 release_build_id: ReleaseBuildId::from_nonce(ReleaseBuildNonce::from_random_bytes(
189 [9; 32],
190 )),
191 expected_module_hash: Some([10; 32]),
192 };
193
194 let bytes = candid::encode_one(&input).expect("encode current root install identity");
195 let decoded: CurrentRootInstallIdentity =
196 candid::decode_one(&bytes).expect("decode current root install identity");
197
198 assert_eq!(decoded, input);
199 }
200
201 #[test]
202 fn fleet_activation_status_roundtrips_as_named_candid_shapes() {
203 let input = FleetActivationStatusResponse {
204 phase: FleetActivationPhase::Prepared,
205 identity: FleetActivationIdentity {
206 fleet: fleet_binding(),
207 operation_id: [11; 32],
208 release_build_id: ReleaseBuildId::from_nonce(ReleaseBuildNonce::from_random_bytes(
209 [12; 32],
210 )),
211 },
212 cascade: Some(FleetCascadeActivationEvidence::Source {
213 cascade_manifest_hash: [13; 32],
214 }),
215 cascade_manifest: Some(vec![FleetCascadeManifestEntry {
216 principal: Principal::from_slice(&[14; 29]),
217 state_snapshot_hash: [15; 32],
218 topology_snapshot_hash: [16; 32],
219 }]),
220 credential: None,
221 credential_manifest: None,
222 activated_at_ns: None,
223 };
224
225 let bytes = candid::encode_one(&input).expect("encode activation status");
226 let decoded: FleetActivationStatusResponse =
227 candid::decode_one(&bytes).expect("decode activation status");
228
229 assert_eq!(decoded, input);
230 }
231}