Skip to main content

canic_core/dto/
fleet_registry.rs

1//! Module: dto::fleet_registry
2//!
3//! Responsibility: carry canonical Fleet Registry snapshots and versions across boundaries.
4//! Does not own: validation, canonical encoding, persistence, or lifecycle transitions.
5//! Boundary: Coordinator and Fleet Subnet Root workflows validate these passive shapes.
6
7use crate::{
8    config::{FleetServiceMemberPurpose, FleetServicePlacementPolicy},
9    dto::{
10        fleet_subnet_root::{
11            FleetSubnetRootDrainingResponse, FleetSubnetRootFinalInventoryResponse,
12        },
13        root_store::RootStoreBootstrapRequest,
14    },
15    ids::{
16        CanisterRole, ComponentGroupMemberPath, ComponentGroupPlacementId, ComponentInstanceId,
17        ComponentSpecAdmission, ComponentSpecId, ComponentTopologyDigest, FleetAdmissionPolicy,
18        FleetRegistryAuthority, FleetServiceId, FleetSubnetRootFundingAuthority,
19        FleetSubnetRootLimits, FleetSubnetRootReleaseSet, SubnetId,
20    },
21};
22use candid::{CandidType, Principal};
23use serde::{Deserialize, Serialize};
24
25///
26/// FleetSubnetRootStatus
27///
28/// Lifecycle state of one Fleet Subnet Root in the Fleet Registry snapshot.
29///
30
31#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
32pub enum FleetSubnetRootStatus {
33    Joining,
34    Active,
35    Draining,
36    Removed,
37}
38
39///
40/// FleetComponentSpecEntry
41///
42/// Fleet-wide immutable Component Spec declaration projected into the Registry.
43///
44
45#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
46pub struct FleetComponentSpecEntry {
47    pub component_spec: ComponentSpecId,
48    pub spec_hash: [u8; 32],
49    pub component_role: CanisterRole,
50    pub maximum_fleet_instances: u32,
51}
52
53///
54/// FleetSubnetRootEntry
55///
56/// One Fleet Subnet Root's immutable placement and admission facts plus lifecycle state.
57///
58
59#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
60pub struct FleetSubnetRootEntry {
61    pub placement_subnet: SubnetId,
62    pub fleet_subnet_root: Principal,
63    pub component_admissions: Vec<ComponentSpecAdmission>,
64    pub component_topology_digest: ComponentTopologyDigest,
65    pub active_release_set: FleetSubnetRootReleaseSet,
66    pub limits: FleetSubnetRootLimits,
67    pub funding: FleetSubnetRootFundingAuthority,
68    pub status: FleetSubnetRootStatus,
69}
70
71/// Published service mode after configuration-only Authority selectors have been resolved.
72#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
73pub enum FleetServiceMode {
74    AuthorityReplica,
75    ActivePool,
76}
77
78/// One exact configured Component member of a published Fleet service.
79#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
80#[serde(deny_unknown_fields)]
81pub struct FleetServiceComponentBinding {
82    pub member_purpose: FleetServiceMemberPurpose,
83    pub component: ComponentInstanceId,
84    pub fleet_subnet_root: Principal,
85    pub canister_id: Principal,
86    pub group_placement: ComponentGroupPlacementId,
87    pub member_path: ComponentGroupMemberPath,
88}
89
90/// Complete configured member set for one logical Fleet service.
91///
92/// This is topology intent only. It deliberately carries no health, readiness,
93/// replication progress, promotion, consistency or load-balancer eligibility.
94#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
95#[serde(deny_unknown_fields)]
96pub struct FleetServiceBinding {
97    pub service: FleetServiceId,
98    pub role: CanisterRole,
99    pub component_spec: ComponentSpecId,
100    pub mode: FleetServiceMode,
101    pub placement: FleetServicePlacementPolicy,
102    pub members: Vec<FleetServiceComponentBinding>,
103}
104
105///
106/// FleetRegistry
107///
108/// Complete canonical Fleet Registry snapshot distributed by one Coordinator.
109///
110
111#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
112pub struct FleetRegistry {
113    pub authority: FleetRegistryAuthority,
114    pub revision: u64,
115    pub admission: FleetAdmissionPolicy,
116    pub component_specs: Vec<FleetComponentSpecEntry>,
117    pub fleet_subnet_roots: Vec<FleetSubnetRootEntry>,
118    pub services: Vec<FleetServiceBinding>,
119}
120
121///
122/// FleetRegistryManifest
123///
124/// Compact current-head evidence for one complete canonical Registry snapshot.
125///
126
127#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
128pub struct FleetRegistryManifest {
129    pub authority: FleetRegistryAuthority,
130    pub revision: u64,
131    pub byte_length: u64,
132    pub content_hash: [u8; 32],
133}
134
135///
136/// FleetRegistryVersion
137///
138/// Compact immutable identity used by mirrors, acknowledgements, and journals.
139///
140
141#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
142pub struct FleetRegistryVersion {
143    pub authority: FleetRegistryAuthority,
144    pub revision: u64,
145    pub content_hash: [u8; 32],
146}
147
148///
149/// FleetSubnetRootJoinRequest
150///
151/// Controller command that compare-and-commits one exact root as Registry `Joining`.
152///
153
154#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
155pub struct FleetSubnetRootJoinRequest {
156    pub expected_registry: FleetRegistryVersion,
157    pub entry: FleetSubnetRootEntry,
158}
159
160///
161/// FleetSubnetRootJoinResponse
162///
163/// Durable response receipt for one exact root's original `Joining` commit.
164///
165
166#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
167pub struct FleetSubnetRootJoinResponse {
168    pub entry: FleetSubnetRootEntry,
169    pub version: FleetRegistryVersion,
170}
171
172///
173/// FleetRegistryActivationRequest
174///
175/// Controller compare-and-commit command for the complete acknowledged `Joining` root set.
176///
177
178#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
179pub struct FleetRegistryActivationRequest {
180    pub expected_registry: FleetRegistryVersion,
181}
182
183///
184/// FleetRegistryActivationResponse
185///
186/// Durable response authority for one atomic all-`Active` Registry transition.
187///
188
189#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
190pub struct FleetRegistryActivationResponse {
191    pub previous_version: FleetRegistryVersion,
192    pub version: FleetRegistryVersion,
193}
194
195///
196/// FleetSubnetRootDrainingReservationRequest
197///
198/// Controller command serializing one root's Fleet-wide draining decision against placement.
199///
200
201#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
202pub struct FleetSubnetRootDrainingReservationRequest {
203    pub asset_recipient: Principal,
204    pub operation_id: [u8; 32],
205    pub expected_registry: FleetRegistryVersion,
206    pub expected_root: FleetSubnetRootEntry,
207}
208
209///
210/// FleetSubnetRootDrainingReservationStatusRequest
211///
212/// Passive lookup key usable by the controller or the exact target root.
213///
214
215#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
216pub struct FleetSubnetRootDrainingReservationStatusRequest {
217    pub operation_id: [u8; 32],
218    pub fleet_subnet_root: Principal,
219}
220
221///
222/// FleetSubnetRootDrainingReservationResponse
223///
224/// Durable Coordinator authority that must precede the target root's local draining fence.
225///
226
227#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
228pub struct FleetSubnetRootDrainingReservationResponse {
229    pub request: FleetSubnetRootDrainingReservationRequest,
230    pub coordinator: Principal,
231    pub prepared_at_ns: u64,
232    pub reservation_hash: [u8; 32],
233}
234
235///
236/// FleetSubnetRootDrainingPublicationRequest
237///
238/// Controller command publishing one root's exact local draining fence to the Coordinator.
239///
240
241#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
242pub struct FleetSubnetRootDrainingPublicationRequest {
243    pub expected_registry: FleetRegistryVersion,
244    pub root_draining: FleetSubnetRootDrainingResponse,
245}
246
247///
248/// FleetSubnetRootDrainingPublicationResponse
249///
250/// Durable response authority for one root's canonical `Active -> Draining` transition.
251///
252
253#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
254pub struct FleetSubnetRootDrainingPublicationResponse {
255    pub root_draining: FleetSubnetRootDrainingResponse,
256    pub previous_version: FleetRegistryVersion,
257    pub version: FleetRegistryVersion,
258}
259
260///
261/// FleetSubnetRootRemovalPublicationRequest
262///
263/// Root-authenticated command publishing one exact terminal inventory to the Coordinator.
264///
265
266#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
267pub struct FleetSubnetRootRemovalPublicationRequest {
268    pub expected_registry: FleetRegistryVersion,
269    pub final_inventory: FleetSubnetRootFinalInventoryResponse,
270}
271
272///
273/// FleetSubnetRootRemovalPublicationResponse
274///
275/// Durable response authority for one root's canonical `Draining -> Removed` transition.
276///
277
278#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
279pub struct FleetSubnetRootRemovalPublicationResponse {
280    pub final_inventory: FleetSubnetRootFinalInventoryResponse,
281    pub previous_version: FleetRegistryVersion,
282    pub version: FleetRegistryVersion,
283}
284
285/// Exact default-account transfer retained before a Fleet retirement Ledger call.
286#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
287pub struct FleetLedgerTransferIntent {
288    pub source: Principal,
289    pub destination: Principal,
290    pub balance_before: u128,
291    pub fee: u128,
292    pub created_at_time: u64,
293    pub memo: [u8; 32],
294}
295
296/// Verified retirement transfer; an initially empty account has no Ledger block.
297#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
298pub struct FleetLedgerTransferReceipt {
299    pub intent: FleetLedgerTransferIntent,
300    pub block_index: Option<u128>,
301}
302
303/// Controller authority for returning a fully removed Fleet's Ledger balance.
304#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
305pub struct FleetRetirementRequest {
306    pub operation_id: [u8; 32],
307    pub expected_registry: FleetRegistryVersion,
308    pub destination: Principal,
309    pub maximum_ledger_fee: u128,
310}
311
312/// Coordinator retirement progress retained until the operator deletes the Coordinator.
313#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
314pub struct FleetRetirementStatus {
315    pub request: FleetRetirementRequest,
316    pub prepared_at_ns: u64,
317    pub ledger_transfer: Option<FleetLedgerTransferIntent>,
318    pub ledger_receipt: Option<FleetLedgerTransferReceipt>,
319}
320
321/// Root-authenticated command freezing its pre-transfer physical-deletion readiness authority.
322#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
323pub struct FleetSubnetRootDeletionReadinessIntentRequest {
324    pub operation_id: [u8; 32],
325    pub fleet_subnet_root: Principal,
326    pub final_inventory_hash: [u8; 32],
327    pub store_deletion_hash: [u8; 32],
328    pub observed_cycles_before_reclamation: u128,
329    pub retained_cycles_target: u128,
330    pub observed_reserved_cycles: u128,
331    pub observed_idle_cycles_burned_per_day: u128,
332    pub observed_freezing_threshold_seconds: u128,
333    pub prepared_at_ns: u64,
334}
335
336/// Coordinator receipt proving root-deletion readiness intent is durable before cycle transfer.
337#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
338pub struct FleetSubnetRootDeletionReadinessIntentResponse {
339    pub request: FleetSubnetRootDeletionReadinessIntentRequest,
340    pub coordinator: Principal,
341    pub recorded_at_ns: u64,
342    pub intent_hash: [u8; 32],
343}
344
345/// Root-authenticated command recording its converged post-transfer cycle balance.
346#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
347pub struct FleetSubnetRootDeletionReadinessRequest {
348    pub ledger_receipt: crate::dto::fleet_registry::FleetLedgerTransferReceipt,
349    pub operation_id: [u8; 32],
350    pub fleet_subnet_root: Principal,
351    pub expected_intent_hash: [u8; 32],
352    pub observed_cycles_after_reclamation: u128,
353    pub cycles_reclaimed_at_ns: u64,
354}
355
356/// Coordinator receipt proving one removed root is ready for an external executor.
357#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
358pub struct FleetSubnetRootDeletionReadinessResponse {
359    pub request: FleetSubnetRootDeletionReadinessRequest,
360    pub coordinator: Principal,
361    pub final_inventory_hash: [u8; 32],
362    pub store_deletion_hash: [u8; 32],
363    pub observed_cycles_before_reclamation: u128,
364    pub retained_cycles_target: u128,
365    pub observed_reserved_cycles: u128,
366    pub observed_idle_cycles_burned_per_day: u128,
367    pub observed_freezing_threshold_seconds: u128,
368    pub prepared_at_ns: u64,
369    pub recorded_at_ns: u64,
370    pub readiness_hash: [u8; 32],
371}
372
373/// Controller command freezing independently observed root authority before stop/delete.
374#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
375pub struct FleetSubnetRootDeletionExecutionRequest {
376    pub operation_id: [u8; 32],
377    pub fleet_subnet_root: Principal,
378    pub expected_readiness_hash: [u8; 32],
379    pub observed_module_hash: [u8; 32],
380    pub observed_controllers: Vec<Principal>,
381    pub observed_cycles_after_reclamation: u128,
382    pub observed_reserved_cycles: u128,
383    pub observed_idle_cycles_burned_per_day: u128,
384    pub observed_freezing_threshold_seconds: u128,
385}
386
387/// Durable Coordinator intent binding one authenticated external root-deletion executor.
388#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
389pub struct FleetSubnetRootDeletionExecutionResponse {
390    pub request: FleetSubnetRootDeletionExecutionRequest,
391    pub executor: Principal,
392    pub prepared_at_ns: u64,
393    pub execution_hash: [u8; 32],
394}
395
396/// Controller request confirming typed root absence under one durable execution intent.
397#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
398pub struct FleetSubnetRootDeletionCompletionRequest {
399    pub operation_id: [u8; 32],
400    pub fleet_subnet_root: Principal,
401    pub expected_execution_hash: [u8; 32],
402    pub observed_absent_at_ns: u64,
403}
404
405/// Read-only lookup key for one durable root-deletion execution intent or receipt.
406#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
407pub struct FleetSubnetRootDeletionStatusRequest {
408    pub operation_id: [u8; 32],
409    pub fleet_subnet_root: Principal,
410}
411
412/// Terminal Coordinator receipt for externally observed Fleet Subnet Root absence.
413#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
414pub struct FleetSubnetRootDeletionResponse {
415    pub operation_id: [u8; 32],
416    pub fleet_subnet_root: Principal,
417    pub coordinator: Principal,
418    pub executor: Principal,
419    pub readiness_hash: [u8; 32],
420    pub execution_hash: [u8; 32],
421    pub observed_module_hash: [u8; 32],
422    pub observed_controllers: Vec<Principal>,
423    pub observed_cycles_after_reclamation: u128,
424    pub observed_absent_at_ns: u64,
425    pub completed_at_ns: u64,
426    pub deletion_hash: [u8; 32],
427}
428
429///
430/// FleetRegistrySnapshotResponse
431///
432/// Complete current Coordinator snapshot supplied only to one registered root.
433///
434
435#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
436pub struct FleetRegistrySnapshotResponse {
437    pub registry: FleetRegistry,
438    pub manifest: FleetRegistryManifest,
439    pub version: FleetRegistryVersion,
440}
441
442///
443/// FleetSubnetRootSnapshotAcknowledgementRequest
444///
445/// Root-authenticated acknowledgement of one exact durably staged snapshot.
446///
447
448#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
449pub struct FleetSubnetRootSnapshotAcknowledgementRequest {
450    pub version: FleetRegistryVersion,
451}
452
453///
454/// FleetSubnetRootSnapshotAcknowledgement
455///
456/// Durable Coordinator receipt proving which root acknowledged which version.
457///
458
459#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
460pub struct FleetSubnetRootSnapshotAcknowledgement {
461    pub fleet_subnet_root: Principal,
462    pub version: FleetRegistryVersion,
463}
464
465/// Controller command asking a Prepared root to synchronize and acknowledge its Registry.
466#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
467pub struct FleetSubnetRootRegistrySyncRequest {
468    pub operation_id: [u8; 32],
469    pub expected_registry: FleetRegistryVersion,
470    pub store_bootstrap: RootStoreBootstrapRequest,
471}
472
473/// Exact root-local candidate and Coordinator acknowledgement evidence.
474#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
475pub struct FleetSubnetRootRegistrySyncResponse {
476    pub fleet_subnet_root: Principal,
477    pub version: FleetRegistryVersion,
478    pub acknowledgement: FleetSubnetRootSnapshotAcknowledgement,
479}
480
481///
482/// FleetDirectoryProvenance
483///
484/// Exact Registry authority and root that published one local Fleet Directory projection.
485///
486
487#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
488pub struct FleetDirectoryProvenance {
489    pub registry: FleetRegistryVersion,
490    pub source_fleet_subnet_root: Principal,
491}
492
493///
494/// FleetSubnetRootDirectoryEntry
495///
496/// One root placement and lifecycle status projected from the complete Fleet Registry.
497///
498
499#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
500pub struct FleetSubnetRootDirectoryEntry {
501    pub placement_subnet: SubnetId,
502    pub fleet_subnet_root: Principal,
503    pub status: FleetSubnetRootStatus,
504}
505
506/// One exact configured Component projected into a Fleet Directory service.
507#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
508#[serde(deny_unknown_fields)]
509pub struct FleetDirectoryServiceComponent {
510    pub member_purpose: FleetServiceMemberPurpose,
511    pub component: ComponentInstanceId,
512    pub fleet_subnet_root: Principal,
513    pub canister_id: Principal,
514    pub group_placement: ComponentGroupPlacementId,
515    pub member_path: ComponentGroupMemberPath,
516}
517
518/// One complete configured service projected from the canonical Fleet Registry.
519///
520/// This is topology discovery only. Applications own health, readiness,
521/// replication progress, promotion, consistency and load-balancer policy.
522#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
523#[serde(deny_unknown_fields)]
524pub struct FleetDirectoryService {
525    pub service: FleetServiceId,
526    pub role: CanisterRole,
527    pub component_spec: ComponentSpecId,
528    pub mode: FleetServiceMode,
529    pub placement: FleetServicePlacementPolicy,
530    pub members: Vec<FleetDirectoryServiceComponent>,
531}
532
533///
534/// FleetDirectorySnapshot
535///
536/// Root-local read-only discovery projection derived from one exact published Registry.
537///
538
539#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
540pub struct FleetDirectorySnapshot {
541    pub provenance: FleetDirectoryProvenance,
542    pub fleet_subnet_roots: Vec<FleetSubnetRootDirectoryEntry>,
543    pub services: Vec<FleetDirectoryService>,
544}
545
546///
547/// FleetSubnetRootRegistryMirrorActivationRequest
548///
549/// Controller command that atomically activates a newer complete Registry mirror and Directory.
550///
551
552#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
553pub struct FleetSubnetRootRegistryMirrorActivationRequest {
554    pub previous_registry: FleetRegistryVersion,
555    pub expected_registry: FleetRegistryVersion,
556    pub expected_directory: FleetDirectorySnapshot,
557    pub store_bootstrap: RootStoreBootstrapRequest,
558}
559
560///
561/// FleetSubnetRootRegistryMirrorActivationResponse
562///
563/// Exact durable evidence for one root's current Registry mirror and Fleet Directory.
564///
565
566#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
567pub struct FleetSubnetRootRegistryMirrorActivationResponse {
568    pub fleet_subnet_root: Principal,
569    pub previous_registry: FleetRegistryVersion,
570    pub version: FleetRegistryVersion,
571    pub directory: FleetDirectorySnapshot,
572}