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/// Compact exact status for one Coordinator-owned provisioning operation.
121#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
122#[serde(deny_unknown_fields)]
123pub struct FleetComponentProvisioningStatusResponse {
124    pub operation_id: [u8; 32],
125    pub plan_hash: [u8; 32],
126    pub fleet_registry: FleetRegistryVersion,
127    pub configuration_digest: ComponentDeploymentConfigurationDigest,
128    pub operation: FleetComponentProvisioningOperation,
129    pub phase: FleetComponentProvisioningPhase,
130    pub directory_confirmation_root_count: u32,
131    pub root_batch_count: u32,
132    pub accepted_root_count: u32,
133    pub acceptance_in_flight_root: Option<Principal>,
134    pub provisioned_root_count: u32,
135    pub current_root: Option<FleetComponentProvisioningRootProgress>,
136    pub provisioning_in_flight_root: Option<Principal>,
137    pub directory_confirmed_root_count: u32,
138    pub current_synchronization: Option<FleetComponentSynchronizationRootProgress>,
139    pub current_publication: Option<FleetComponentPublicationRootProgress>,
140    pub publication_in_flight_root: Option<Principal>,
141    pub runtime_activated_root_count: u32,
142    pub current_activation: Option<FleetComponentActivationRootProgress>,
143    pub activation_in_flight_root: Option<Principal>,
144    pub group_placement_count: u32,
145    pub component_count: u32,
146    pub planned_at_ns: u64,
147    pub roots_accepted_at_ns: Option<u64>,
148    pub components_provisioned_at_ns: Option<u64>,
149    pub published_fleet_registry: Option<FleetRegistryVersion>,
150    pub service_topology_published_at_ns: Option<u64>,
151    pub directories_confirmed_at_ns: Option<u64>,
152    pub runtimes_activated_at_ns: Option<u64>,
153}
154
155/// Fresh-install or monotonic scale-out scope covered by one plan.
156#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
157#[serde(deny_unknown_fields)]
158pub enum FleetComponentProvisioningOperation {
159    FreshInstall,
160    ScaleOut {
161        deployment: ComponentGroupDeploymentId,
162        previous_placements: u32,
163        requested_placements: u32,
164    },
165}
166
167/// One selected root's complete canonical provisioning batch.
168#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
169#[serde(deny_unknown_fields)]
170pub struct FleetSubnetRootProvisioningBatch {
171    pub root: FleetSubnetRootBinding,
172    pub active_release_set: FleetSubnetRootReleaseSet,
173    pub placements: Vec<ComponentGroupPlacementPlan>,
174}
175
176/// One materialized copy of a completely flattened Component Group.
177#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
178#[serde(deny_unknown_fields)]
179pub struct ComponentGroupPlacementPlan {
180    pub group_placement: ComponentGroupPlacementId,
181    pub component_group: ComponentGroupSpecId,
182    pub entries: Vec<ComponentGroupPlanEntry>,
183}
184
185/// One exact top-level Component occurrence within a group placement.
186#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
187#[serde(deny_unknown_fields)]
188pub struct ComponentGroupPlanEntry {
189    pub member_path: ComponentGroupMemberPath,
190    pub component_spec: ComponentSpecId,
191    pub spec_hash: [u8; 32],
192    pub purpose: ComponentDeploymentPurpose,
193    pub labels: Vec<ComponentDeploymentLabel>,
194    pub limits: ComponentDeploymentLimits,
195}
196
197/// Coordinator-authenticated command asking one root to retain its exact plan batch.
198#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
199#[serde(deny_unknown_fields)]
200pub struct RootComponentProvisioningAcceptanceRequest {
201    pub fleet_registry: FleetRegistryVersion,
202    pub configuration_digest: ComponentDeploymentConfigurationDigest,
203    pub operation_id: [u8; 32],
204    pub plan_hash: [u8; 32],
205    pub batch: FleetSubnetRootProvisioningBatch,
206}
207
208/// Read-only lookup key for one exact root provisioning operation.
209#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
210#[serde(deny_unknown_fields)]
211pub struct RootComponentProvisioningStatusRequest {
212    pub operation_id: [u8; 32],
213    pub plan_hash: [u8; 32],
214}
215
216/// Coordinator-authenticated command advancing one exact bounded provisioning step.
217#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
218#[serde(deny_unknown_fields)]
219pub struct RootComponentProvisioningAdvanceRequest {
220    pub operation_id: [u8; 32],
221    pub plan_hash: [u8; 32],
222    pub expected_reserved_component_count: u32,
223    pub expected_claimed_component_count: u32,
224    pub expected_installed_component_count: u32,
225    pub expected_registry_committed_component_count: u32,
226}
227
228/// One exact member of a root-derived Component Group Directory.
229#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
230#[serde(deny_unknown_fields)]
231pub struct ComponentGroupDirectoryMember {
232    pub member_path: ComponentGroupMemberPath,
233    pub component_spec: ComponentSpecId,
234    pub purpose: ComponentDeploymentPurpose,
235    pub labels: Vec<ComponentDeploymentLabel>,
236    pub binding: ComponentBinding,
237}
238
239/// Protected origin of one root-derived Component Group Directory.
240#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
241#[serde(deny_unknown_fields)]
242pub struct ComponentGroupDirectoryProvenance {
243    pub authority: crate::ids::FleetRegistryAuthority,
244    pub fleet_subnet_root: Principal,
245    pub group_placement: ComponentGroupPlacementId,
246    pub component_group: ComponentGroupSpecId,
247    pub operation_id: [u8; 32],
248    pub plan_hash: [u8; 32],
249    pub placement_receipt_content_hash: [u8; 32],
250}
251
252/// Complete bounded sibling projection for one materialized Component Group placement.
253#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
254#[serde(deny_unknown_fields)]
255pub struct ComponentGroupDirectory {
256    pub provenance: ComponentGroupDirectoryProvenance,
257    pub members: Vec<ComponentGroupDirectoryMember>,
258}
259
260/// Compact proof of one exact Component Directory delivered during publication.
261#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
262#[serde(deny_unknown_fields)]
263pub struct ComponentDirectoryPublicationEvidence {
264    pub component: crate::ids::ComponentInstanceId,
265    pub content_hash: [u8; 32],
266}
267
268/// Compact proof of one exact Component Group Directory delivered during publication.
269#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
270#[serde(deny_unknown_fields)]
271pub struct ComponentGroupDirectoryPublicationEvidence {
272    pub group_placement: ComponentGroupPlacementId,
273    pub content_hash: [u8; 32],
274}
275
276/// Complete root-local evidence for one published provisioning batch.
277#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
278#[serde(deny_unknown_fields)]
279pub struct RootComponentPublicationEvidence {
280    pub fleet_registry: FleetRegistryVersion,
281    pub fleet_directory_content_hash: [u8; 32],
282    pub component_directories: Vec<ComponentDirectoryPublicationEvidence>,
283    pub component_group_directories: Vec<ComponentGroupDirectoryPublicationEvidence>,
284}
285
286/// Coordinator-authenticated command advancing one bounded root publication step.
287#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
288#[serde(deny_unknown_fields)]
289pub struct RootComponentPublicationRequest {
290    pub operation_id: [u8; 32],
291    pub plan_hash: [u8; 32],
292    pub published_fleet_registry: FleetRegistryVersion,
293    pub expected_published_component_count: u32,
294}
295
296///
297/// RootComponentDirectorySynchronizationRequest
298///
299/// Coordinator-authenticated command advancing one affected-root scale-out Directory step.
300///
301
302#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
303#[serde(deny_unknown_fields)]
304pub struct RootComponentDirectorySynchronizationRequest {
305    pub operation_id: [u8; 32],
306    pub plan_hash: [u8; 32],
307    pub source_fleet_registry: FleetRegistryVersion,
308    pub published_fleet_registry: FleetRegistryVersion,
309    pub expected_synchronized_component_count: u32,
310}
311
312///
313/// RootComponentDirectorySynchronizationResponse
314///
315/// Compact exact progress for one root's affected existing service members.
316///
317
318#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
319#[serde(deny_unknown_fields)]
320pub struct RootComponentDirectorySynchronizationResponse {
321    pub operation_id: [u8; 32],
322    pub plan_hash: [u8; 32],
323    pub source_fleet_registry: FleetRegistryVersion,
324    pub published_fleet_registry: FleetRegistryVersion,
325    pub fleet_subnet_root: Principal,
326    pub affected_component_count: u32,
327    pub synchronized_component_count: u32,
328    pub fleet_directory_content_hash: [u8; 32],
329    pub complete: bool,
330    pub synchronized_at_ns: Option<u64>,
331    pub receipt_content_hash: [u8; 32],
332}
333
334/// Coordinator-authenticated command advancing one bounded root activation step.
335#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
336#[serde(deny_unknown_fields)]
337pub struct RootComponentActivationRequest {
338    pub operation_id: [u8; 32],
339    pub plan_hash: [u8; 32],
340    pub expected_activated_component_count: u32,
341    pub expected_root_runtime_active: bool,
342}
343
344/// Compact terminal evidence binding Component inventory and root runtime activation.
345#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
346#[serde(deny_unknown_fields)]
347pub struct RootComponentActivationEvidence {
348    pub fleet_activation_operation_id: [u8; 32],
349    pub initial_inventory_hash: [u8; 32],
350    pub component_count: u32,
351    pub root_activated_at_ns: u64,
352}
353
354/// One exact provisioned Component occurrence and its committed Registry identity.
355#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
356#[serde(deny_unknown_fields)]
357pub struct RootProvisionedGroupMember {
358    pub member_path: ComponentGroupMemberPath,
359    pub component_spec: ComponentSpecId,
360    pub purpose: ComponentDeploymentPurpose,
361    pub limits: ComponentDeploymentLimits,
362    pub binding: ComponentBinding,
363    pub component_registry_revision: u64,
364    pub component_registry_content_hash: [u8; 32],
365}
366
367/// Complete provisioned result for one exact group placement on this root.
368#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
369#[serde(deny_unknown_fields)]
370pub struct RootProvisionedGroupPlacement {
371    pub group_placement: ComponentGroupPlacementId,
372    pub component_group: ComponentGroupSpecId,
373    pub members: Vec<RootProvisionedGroupMember>,
374}
375
376/// Complete group-partitioned result of one root provisioning operation.
377#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
378#[serde(deny_unknown_fields)]
379pub struct RootComponentProvisioningResult {
380    pub placements: Vec<RootProvisionedGroupPlacement>,
381}
382
383/// Durable aggregate progress of one root provisioning batch.
384#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
385pub enum RootComponentProvisioningPhase {
386    Accepted,
387    Provisioned,
388    Published,
389    RuntimesActive,
390}
391
392/// Durable progress or complete terminal result for one exact root provisioning operation.
393#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
394#[serde(deny_unknown_fields)]
395pub struct RootComponentProvisioningStatusResponse {
396    pub operation_id: [u8; 32],
397    pub plan_hash: [u8; 32],
398    pub fleet_registry: FleetRegistryVersion,
399    pub configuration_digest: ComponentDeploymentConfigurationDigest,
400    pub fleet_subnet_root: Principal,
401    pub phase: RootComponentProvisioningPhase,
402    pub placement_count: u32,
403    pub component_count: u32,
404    pub reserved_component_count: u32,
405    pub claimed_component_count: u32,
406    pub installed_component_count: u32,
407    pub registry_committed_component_count: u32,
408    pub published_component_count: u32,
409    pub activated_component_count: u32,
410    pub root_runtime_active: bool,
411    pub result: Option<RootComponentProvisioningResult>,
412    pub publication: Option<RootComponentPublicationEvidence>,
413    pub activation: Option<RootComponentActivationEvidence>,
414    pub accepted_at_ns: u64,
415    pub provisioned_at_ns: Option<u64>,
416    pub published_at_ns: Option<u64>,
417    pub activation_started_at_ns: Option<u64>,
418    pub runtimes_activated_at_ns: Option<u64>,
419    pub receipt_content_hash: [u8; 32],
420}