1use crate::ids::{FleetBinding, FleetKey, ReleaseBuildId};
8use candid::{CandidType, Principal};
9use serde::{Deserialize, Serialize};
10
11pub const MAX_FLEET_ACTIVATION_CANISTERS: usize = 4_096;
13pub const MAX_FLEET_CREDENTIAL_MANIFEST_ENTRIES: usize = 64;
15
16#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
21pub struct FleetCascadeManifestEntry {
22 pub principal: Principal,
23 pub state_snapshot_hash: [u8; 32],
24 pub topology_snapshot_hash: [u8; 32],
25}
26
27#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
32pub enum FleetCascadeActivationEvidence {
33 Source {
34 cascade_manifest_hash: [u8; 32],
35 },
36 Applied {
37 state_snapshot_hash: [u8; 32],
38 topology_snapshot_hash: [u8; 32],
39 },
40}
41
42#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
47pub struct FleetCredentialGenerationRef {
48 pub generation: u64,
49 pub manifest_hash: [u8; 32],
50}
51
52#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub struct FleetCredentialManifestEntry {
58 pub root_issuer: Principal,
59 pub subject_canister: Principal,
60 pub not_before_ns: u64,
61 pub expires_at_ns: u64,
62 pub key_identity_hash: [u8; 32],
63 pub cert_hash: [u8; 32],
64 pub proof_hash: [u8; 32],
65 pub bundle_hash: [u8; 32],
66}
67
68#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
73pub struct FleetCredentialManifest {
74 pub fleet: FleetKey,
75 pub activation_id: [u8; 32],
76 pub generation: u64,
77 pub root_policy_set_hash: [u8; 32],
78 pub renewal_template_set_hash: [u8; 32],
79 pub entries: Vec<FleetCredentialManifestEntry>,
80}
81
82#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
87pub struct FleetActivationIdentity {
88 pub fleet: FleetBinding,
89 pub operation_id: [u8; 32],
90 pub release_build_id: ReleaseBuildId,
91}
92
93#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
98pub enum FleetActivationPhase {
99 Prepared,
100 Active,
101}
102
103#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
108pub struct FleetActivationStatusResponse {
109 pub phase: FleetActivationPhase,
110 pub identity: FleetActivationIdentity,
111 pub cascade: Option<FleetCascadeActivationEvidence>,
112 pub cascade_manifest: Option<Vec<FleetCascadeManifestEntry>>,
113 pub credential: Option<FleetCredentialGenerationRef>,
114 pub credential_manifest: Option<FleetCredentialManifest>,
115 pub activated_at_ns: Option<u64>,
116}
117
118#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
119pub struct FleetActivationResumeRequest {
120 pub operation_id: [u8; 32],
121 pub credential: FleetCredentialGenerationRef,
122}
123
124#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
125pub struct FleetCredentialGenerationRequest {
126 pub operation_id: [u8; 32],
127 pub credential: FleetCredentialGenerationRef,
128}
129
130#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
131pub struct FleetActivationRequest {
132 pub operation_id: [u8; 32],
133 pub credential: FleetCredentialGenerationRef,
134 pub activation_evidence_hash: [u8; 32],
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use crate::ids::{AppId, CanonicalNetworkId, FleetId, FleetKey, ReleaseBuildNonce};
141
142 fn fleet_binding() -> FleetBinding {
143 FleetBinding {
144 fleet: FleetKey {
145 canonical_network_id: CanonicalNetworkId::ic_mainnet(),
146 fleet_id: FleetId::from_generated_bytes([7; 32]),
147 },
148 app: AppId::from("toko"),
149 }
150 }
151
152 #[test]
153 fn fleet_activation_status_roundtrips_as_named_candid_shapes() {
154 let input = FleetActivationStatusResponse {
155 phase: FleetActivationPhase::Prepared,
156 identity: FleetActivationIdentity {
157 fleet: fleet_binding(),
158 operation_id: [11; 32],
159 release_build_id: ReleaseBuildId::from_nonce(ReleaseBuildNonce::from_random_bytes(
160 [12; 32],
161 )),
162 },
163 cascade: Some(FleetCascadeActivationEvidence::Source {
164 cascade_manifest_hash: [13; 32],
165 }),
166 cascade_manifest: Some(vec![FleetCascadeManifestEntry {
167 principal: Principal::from_slice(&[14; 29]),
168 state_snapshot_hash: [15; 32],
169 topology_snapshot_hash: [16; 32],
170 }]),
171 credential: None,
172 credential_manifest: None,
173 activated_at_ns: None,
174 };
175
176 let bytes = candid::encode_one(&input).expect("encode activation status");
177 let decoded: FleetActivationStatusResponse =
178 candid::decode_one(&bytes).expect("decode activation status");
179
180 assert_eq!(decoded, input);
181 }
182}