Skip to main content

canic_core/dto/
component_provisioning.rs

1//! Module: dto::component_provisioning
2//!
3//! Responsibility: carry one canonical Fleet Component provisioning plan across boundaries.
4//! Does not own: plan derivation, validation, persistence, root effects, or receipts.
5//! Boundary: the Coordinator retains the complete plan and sends each root only its exact batch.
6
7use crate::{
8    config::{ComponentDeploymentLabel, ComponentDeploymentLimits, ComponentDeploymentPurpose},
9    dto::fleet_registry::FleetRegistryVersion,
10    ids::{
11        ComponentBinding, ComponentDeploymentConfigurationDigest, ComponentGroupDeploymentId,
12        ComponentGroupMemberPath, ComponentGroupPlacementId, ComponentGroupSpecId, ComponentSpecId,
13        FleetBinding, FleetSubnetRootBinding, FleetSubnetRootReleaseSet,
14    },
15};
16use candid::{CandidType, Principal};
17use serde::{Deserialize, Serialize};
18
19/// Complete canonical provisioning authority retained before any root effect.
20#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
21#[serde(deny_unknown_fields)]
22pub struct FleetComponentProvisioningPlan {
23    pub fleet: FleetBinding,
24    pub fleet_registry: FleetRegistryVersion,
25    pub configuration_digest: ComponentDeploymentConfigurationDigest,
26    pub operation: FleetComponentProvisioningOperation,
27    pub directory_confirmation_roots: Vec<Principal>,
28    pub batches: Vec<FleetSubnetRootProvisioningBatch>,
29}
30
31/// Controller-authenticated command that durably freezes one complete plan.
32#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
33#[serde(deny_unknown_fields)]
34pub struct FleetComponentProvisioningPrepareRequest {
35    pub operation_id: [u8; 32],
36    pub plan: FleetComponentProvisioningPlan,
37}
38
39/// Controller-authenticated command advancing one exact Coordinator provisioning step.
40#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
41#[serde(deny_unknown_fields)]
42pub struct FleetComponentProvisioningAdvanceRequest {
43    pub operation_id: [u8; 32],
44    pub plan_hash: [u8; 32],
45    pub expected_phase: FleetComponentProvisioningPhase,
46    pub expected_accepted_root_count: u32,
47    pub expected_provisioned_root_count: u32,
48    pub expected_current_root: Option<FleetComponentProvisioningRootProgress>,
49    pub expected_directory_confirmed_root_count: u32,
50    pub expected_current_synchronization: Option<FleetComponentSynchronizationRootProgress>,
51    pub expected_current_publication: Option<FleetComponentPublicationRootProgress>,
52    pub expected_runtime_activated_root_count: u32,
53    pub expected_current_activation: Option<FleetComponentActivationRootProgress>,
54}
55
56/// Exact root-local cursor copied from passive Coordinator status before one advance.
57#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
58#[serde(deny_unknown_fields)]
59pub struct FleetComponentProvisioningRootProgress {
60    pub fleet_subnet_root: Principal,
61    pub component_count: u32,
62    pub reserved_component_count: u32,
63    pub claimed_component_count: u32,
64    pub installed_component_count: u32,
65    pub registry_committed_component_count: u32,
66}
67
68/// Exact root-local Directory cursor copied from passive Coordinator status.
69#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
70#[serde(deny_unknown_fields)]
71pub struct FleetComponentPublicationRootProgress {
72    pub fleet_subnet_root: Principal,
73    pub component_count: u32,
74    pub published_component_count: u32,
75}
76
77/// Exact affected-service synchronization cursor copied from passive Coordinator status.
78#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
79#[serde(deny_unknown_fields)]
80pub struct FleetComponentSynchronizationRootProgress {
81    pub fleet_subnet_root: Principal,
82    pub affected_component_count: u32,
83    pub synchronized_component_count: u32,
84    pub complete: bool,
85}
86
87/// Exact root-local runtime-activation cursor copied from passive Coordinator status.
88#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
89#[serde(deny_unknown_fields)]
90pub struct FleetComponentActivationRootProgress {
91    pub fleet_subnet_root: Principal,
92    pub component_count: u32,
93    pub activated_component_count: u32,
94    pub root_runtime_active: bool,
95}
96
97/// Exact passive lookup key for one Coordinator-owned provisioning operation.
98#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
99#[serde(deny_unknown_fields)]
100pub struct FleetComponentProvisioningStatusRequest {
101    pub operation_id: [u8; 32],
102    pub plan_hash: [u8; 32],
103}
104
105/// Durable Coordinator progress exposed without returning the complete plan.
106#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
107pub enum FleetComponentProvisioningPhase {
108    Planned,
109    AcceptingRoots,
110    RootsAccepted,
111    ProvisioningRoots,
112    ComponentsProvisioned,
113    ServiceTopologyPublished,
114    ConfirmingDirectories,
115    DirectoriesConfirmed,
116    ActivatingRuntimes,
117    RuntimesActivated,
118}
119
120/// Exact Coordinator step whose current Root call most recently failed.
121#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
122pub enum FleetComponentProvisioningRetryStage {
123    RootAcceptance,
124    RootProvisioning,
125    DirectoryConfirmation,
126    RuntimeActivation,
127}
128
129/// Bounded typed diagnostic retained for the Root call that remains retryable.
130#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
131#[serde(deny_unknown_fields)]
132pub struct FleetComponentProvisioningRootFailure {
133    pub fleet_subnet_root: Principal,
134    pub stage: FleetComponentProvisioningRetryStage,
135    pub diagnostic_code: u16,
136    pub failed_at_ns: u64,
137}
138
139/// Compact exact status for one Coordinator-owned provisioning operation.
140#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
141#[serde(deny_unknown_fields)]
142pub struct FleetComponentProvisioningStatusResponse {
143    pub operation_id: [u8; 32],
144    pub plan_hash: [u8; 32],
145    pub fleet_registry: FleetRegistryVersion,
146    pub configuration_digest: ComponentDeploymentConfigurationDigest,
147    pub operation: FleetComponentProvisioningOperation,
148    pub phase: FleetComponentProvisioningPhase,
149    pub directory_confirmation_root_count: u32,
150    pub root_batch_count: u32,
151    pub accepted_root_count: u32,
152    pub acceptance_in_flight_root: Option<Principal>,
153    pub provisioned_root_count: u32,
154    pub current_root: Option<FleetComponentProvisioningRootProgress>,
155    pub provisioning_in_flight_root: Option<Principal>,
156    pub directory_confirmed_root_count: u32,
157    pub current_synchronization: Option<FleetComponentSynchronizationRootProgress>,
158    pub current_publication: Option<FleetComponentPublicationRootProgress>,
159    pub publication_in_flight_root: Option<Principal>,
160    pub runtime_activated_root_count: u32,
161    pub current_activation: Option<FleetComponentActivationRootProgress>,
162    pub activation_in_flight_root: Option<Principal>,
163    pub pending_root_failure: Option<FleetComponentProvisioningRootFailure>,
164    pub group_placement_count: u32,
165    pub component_count: u32,
166    pub planned_at_ns: u64,
167    pub roots_accepted_at_ns: Option<u64>,
168    pub components_provisioned_at_ns: Option<u64>,
169    pub published_fleet_registry: Option<FleetRegistryVersion>,
170    pub service_topology_published_at_ns: Option<u64>,
171    pub directories_confirmed_at_ns: Option<u64>,
172    pub runtimes_activated_at_ns: Option<u64>,
173}
174
175/// Fresh-install or monotonic scale-out scope covered by one plan.
176#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
177#[serde(deny_unknown_fields)]
178pub enum FleetComponentProvisioningOperation {
179    FreshInstall,
180    ScaleOut {
181        deployment: ComponentGroupDeploymentId,
182        previous_placements: u32,
183        requested_placements: u32,
184    },
185}
186
187/// One selected root's complete canonical provisioning batch.
188#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
189#[serde(deny_unknown_fields)]
190pub struct FleetSubnetRootProvisioningBatch {
191    pub root: FleetSubnetRootBinding,
192    pub active_release_set: FleetSubnetRootReleaseSet,
193    pub placements: Vec<ComponentGroupPlacementPlan>,
194}
195
196/// One materialized copy of a completely flattened Component Group.
197#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
198#[serde(deny_unknown_fields)]
199pub struct ComponentGroupPlacementPlan {
200    pub group_placement: ComponentGroupPlacementId,
201    pub component_group: ComponentGroupSpecId,
202    pub entries: Vec<ComponentGroupPlanEntry>,
203}
204
205/// One exact top-level Component occurrence within a group placement.
206#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
207#[serde(deny_unknown_fields)]
208pub struct ComponentGroupPlanEntry {
209    pub member_path: ComponentGroupMemberPath,
210    pub component_spec: ComponentSpecId,
211    pub spec_hash: [u8; 32],
212    pub purpose: ComponentDeploymentPurpose,
213    pub labels: Vec<ComponentDeploymentLabel>,
214    pub limits: ComponentDeploymentLimits,
215}
216
217/// Coordinator-authenticated command asking one root to retain its exact plan batch.
218#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
219#[serde(deny_unknown_fields)]
220pub struct RootComponentProvisioningAcceptanceRequest {
221    pub fleet_registry: FleetRegistryVersion,
222    pub configuration_digest: ComponentDeploymentConfigurationDigest,
223    pub operation_id: [u8; 32],
224    pub plan_hash: [u8; 32],
225    pub batch: FleetSubnetRootProvisioningBatch,
226}
227
228/// Read-only lookup key for one exact root provisioning operation.
229#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
230#[serde(deny_unknown_fields)]
231pub struct RootComponentProvisioningStatusRequest {
232    pub operation_id: [u8; 32],
233    pub plan_hash: [u8; 32],
234}
235
236/// Coordinator-authenticated command advancing one exact bounded provisioning step.
237#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
238#[serde(deny_unknown_fields)]
239pub struct RootComponentProvisioningAdvanceRequest {
240    pub operation_id: [u8; 32],
241    pub plan_hash: [u8; 32],
242    pub expected_reserved_component_count: u32,
243    pub expected_claimed_component_count: u32,
244    pub expected_installed_component_count: u32,
245    pub expected_registry_committed_component_count: u32,
246}
247
248/// One exact member of a root-derived Component Group Directory.
249#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
250#[serde(deny_unknown_fields)]
251pub struct ComponentGroupDirectoryMember {
252    pub member_path: ComponentGroupMemberPath,
253    pub component_spec: ComponentSpecId,
254    pub purpose: ComponentDeploymentPurpose,
255    pub labels: Vec<ComponentDeploymentLabel>,
256    pub binding: ComponentBinding,
257}
258
259/// Protected origin of one root-derived Component Group Directory.
260#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
261#[serde(deny_unknown_fields)]
262pub struct ComponentGroupDirectoryProvenance {
263    pub authority: crate::ids::FleetRegistryAuthority,
264    pub fleet_subnet_root: Principal,
265    pub group_placement: ComponentGroupPlacementId,
266    pub component_group: ComponentGroupSpecId,
267    pub operation_id: [u8; 32],
268    pub plan_hash: [u8; 32],
269    pub placement_receipt_content_hash: [u8; 32],
270}
271
272/// Complete bounded sibling projection for one materialized Component Group placement.
273#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
274#[serde(deny_unknown_fields)]
275pub struct ComponentGroupDirectory {
276    pub provenance: ComponentGroupDirectoryProvenance,
277    pub members: Vec<ComponentGroupDirectoryMember>,
278}
279
280/// Compact proof of one exact Component Directory delivered during publication.
281#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
282#[serde(deny_unknown_fields)]
283pub struct ComponentDirectoryPublicationEvidence {
284    pub component: crate::ids::ComponentInstanceId,
285    pub content_hash: [u8; 32],
286}
287
288/// Compact proof of one exact Component Group Directory delivered during publication.
289#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
290#[serde(deny_unknown_fields)]
291pub struct ComponentGroupDirectoryPublicationEvidence {
292    pub group_placement: ComponentGroupPlacementId,
293    pub content_hash: [u8; 32],
294}
295
296/// Complete root-local evidence for one published provisioning batch.
297#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
298#[serde(deny_unknown_fields)]
299pub struct RootComponentPublicationEvidence {
300    pub fleet_registry: FleetRegistryVersion,
301    pub fleet_directory_content_hash: [u8; 32],
302    pub component_directories: Vec<ComponentDirectoryPublicationEvidence>,
303    pub component_group_directories: Vec<ComponentGroupDirectoryPublicationEvidence>,
304}
305
306/// Coordinator-authenticated command advancing one bounded root publication step.
307#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
308#[serde(deny_unknown_fields)]
309pub struct RootComponentPublicationRequest {
310    pub operation_id: [u8; 32],
311    pub plan_hash: [u8; 32],
312    pub published_fleet_registry: FleetRegistryVersion,
313    pub expected_published_component_count: u32,
314}
315
316///
317/// RootComponentDirectorySynchronizationRequest
318///
319/// Coordinator-authenticated command advancing one affected-root scale-out Directory step.
320///
321
322#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
323#[serde(deny_unknown_fields)]
324pub struct RootComponentDirectorySynchronizationRequest {
325    pub operation_id: [u8; 32],
326    pub plan_hash: [u8; 32],
327    pub source_fleet_registry: FleetRegistryVersion,
328    pub published_fleet_registry: FleetRegistryVersion,
329    pub expected_synchronized_component_count: u32,
330}
331
332///
333/// RootComponentDirectorySynchronizationResponse
334///
335/// Compact exact progress for one root's affected existing service members.
336///
337
338#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
339#[serde(deny_unknown_fields)]
340pub struct RootComponentDirectorySynchronizationResponse {
341    pub operation_id: [u8; 32],
342    pub plan_hash: [u8; 32],
343    pub source_fleet_registry: FleetRegistryVersion,
344    pub published_fleet_registry: FleetRegistryVersion,
345    pub fleet_subnet_root: Principal,
346    pub affected_component_count: u32,
347    pub synchronized_component_count: u32,
348    pub fleet_directory_content_hash: [u8; 32],
349    pub complete: bool,
350    pub synchronized_at_ns: Option<u64>,
351    pub receipt_content_hash: [u8; 32],
352}
353
354/// Coordinator-authenticated command advancing one bounded root activation step.
355#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
356#[serde(deny_unknown_fields)]
357pub struct RootComponentActivationRequest {
358    pub operation_id: [u8; 32],
359    pub plan_hash: [u8; 32],
360    pub expected_activated_component_count: u32,
361    pub expected_root_runtime_active: bool,
362}
363
364/// Compact terminal evidence binding Component inventory and root runtime activation.
365#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
366#[serde(deny_unknown_fields)]
367pub struct RootComponentActivationEvidence {
368    pub fleet_activation_operation_id: [u8; 32],
369    pub initial_inventory_hash: [u8; 32],
370    pub component_count: u32,
371    pub root_activated_at_ns: u64,
372}
373
374/// One exact provisioned Component occurrence and its committed Registry identity.
375#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
376#[serde(deny_unknown_fields)]
377pub struct RootProvisionedGroupMember {
378    pub member_path: ComponentGroupMemberPath,
379    pub component_spec: ComponentSpecId,
380    pub purpose: ComponentDeploymentPurpose,
381    pub limits: ComponentDeploymentLimits,
382    pub binding: ComponentBinding,
383    pub component_registry_revision: u64,
384    pub component_registry_content_hash: [u8; 32],
385}
386
387/// Complete provisioned result for one exact group placement on this root.
388#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
389#[serde(deny_unknown_fields)]
390pub struct RootProvisionedGroupPlacement {
391    pub group_placement: ComponentGroupPlacementId,
392    pub component_group: ComponentGroupSpecId,
393    pub members: Vec<RootProvisionedGroupMember>,
394}
395
396/// Complete group-partitioned result of one root provisioning operation.
397#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
398#[serde(deny_unknown_fields)]
399pub struct RootComponentProvisioningResult {
400    pub placements: Vec<RootProvisionedGroupPlacement>,
401}
402
403/// Durable aggregate progress of one root provisioning batch.
404#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
405pub enum RootComponentProvisioningPhase {
406    Accepted,
407    Provisioned,
408    Published,
409    RuntimesActive,
410}
411
412/// Durable progress or complete terminal result for one exact root provisioning operation.
413#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
414#[serde(deny_unknown_fields)]
415pub struct RootComponentProvisioningStatusResponse {
416    pub operation_id: [u8; 32],
417    pub plan_hash: [u8; 32],
418    pub fleet_registry: FleetRegistryVersion,
419    pub configuration_digest: ComponentDeploymentConfigurationDigest,
420    pub fleet_subnet_root: Principal,
421    pub phase: RootComponentProvisioningPhase,
422    pub placement_count: u32,
423    pub component_count: u32,
424    pub reserved_component_count: u32,
425    pub claimed_component_count: u32,
426    pub installed_component_count: u32,
427    pub registry_committed_component_count: u32,
428    pub published_component_count: u32,
429    pub activated_component_count: u32,
430    pub root_runtime_active: bool,
431    pub result: Option<RootComponentProvisioningResult>,
432    pub publication: Option<RootComponentPublicationEvidence>,
433    pub activation: Option<RootComponentActivationEvidence>,
434    pub accepted_at_ns: u64,
435    pub provisioned_at_ns: Option<u64>,
436    pub published_at_ns: Option<u64>,
437    pub activation_started_at_ns: Option<u64>,
438    pub runtimes_activated_at_ns: Option<u64>,
439    pub receipt_content_hash: [u8; 32],
440}