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_publication: Option<FleetComponentPublicationRootProgress>,
51    pub expected_runtime_activated_root_count: u32,
52    pub expected_current_activation: Option<FleetComponentActivationRootProgress>,
53}
54
55/// Exact root-local cursor copied from passive Coordinator status before one advance.
56#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
57#[serde(deny_unknown_fields)]
58pub struct FleetComponentProvisioningRootProgress {
59    pub fleet_subnet_root: Principal,
60    pub component_count: u32,
61    pub reserved_component_count: u32,
62    pub claimed_component_count: u32,
63    pub installed_component_count: u32,
64    pub registry_committed_component_count: u32,
65}
66
67/// Exact root-local Directory cursor copied from passive Coordinator status.
68#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
69#[serde(deny_unknown_fields)]
70pub struct FleetComponentPublicationRootProgress {
71    pub fleet_subnet_root: Principal,
72    pub component_count: u32,
73    pub published_component_count: u32,
74}
75
76/// Exact root-local runtime-activation cursor copied from passive Coordinator status.
77#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
78#[serde(deny_unknown_fields)]
79pub struct FleetComponentActivationRootProgress {
80    pub fleet_subnet_root: Principal,
81    pub component_count: u32,
82    pub activated_component_count: u32,
83    pub root_runtime_active: bool,
84}
85
86/// Exact passive lookup key for one Coordinator-owned provisioning operation.
87#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
88#[serde(deny_unknown_fields)]
89pub struct FleetComponentProvisioningStatusRequest {
90    pub operation_id: [u8; 32],
91    pub plan_hash: [u8; 32],
92}
93
94/// Durable Coordinator progress exposed without returning the complete plan.
95#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
96pub enum FleetComponentProvisioningPhase {
97    Planned,
98    AcceptingRoots,
99    RootsAccepted,
100    ProvisioningRoots,
101    ComponentsProvisioned,
102    ServiceTopologyPublished,
103    ConfirmingDirectories,
104    DirectoriesConfirmed,
105    ActivatingRuntimes,
106    RuntimesActivated,
107}
108
109/// Compact exact status for one Coordinator-owned provisioning operation.
110#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
111#[serde(deny_unknown_fields)]
112pub struct FleetComponentProvisioningStatusResponse {
113    pub operation_id: [u8; 32],
114    pub plan_hash: [u8; 32],
115    pub fleet_registry: FleetRegistryVersion,
116    pub configuration_digest: ComponentDeploymentConfigurationDigest,
117    pub operation: FleetComponentProvisioningOperation,
118    pub phase: FleetComponentProvisioningPhase,
119    pub directory_confirmation_root_count: u32,
120    pub root_batch_count: u32,
121    pub accepted_root_count: u32,
122    pub acceptance_in_flight_root: Option<Principal>,
123    pub provisioned_root_count: u32,
124    pub current_root: Option<FleetComponentProvisioningRootProgress>,
125    pub provisioning_in_flight_root: Option<Principal>,
126    pub directory_confirmed_root_count: u32,
127    pub current_publication: Option<FleetComponentPublicationRootProgress>,
128    pub publication_in_flight_root: Option<Principal>,
129    pub runtime_activated_root_count: u32,
130    pub current_activation: Option<FleetComponentActivationRootProgress>,
131    pub activation_in_flight_root: Option<Principal>,
132    pub group_placement_count: u32,
133    pub component_count: u32,
134    pub planned_at_ns: u64,
135    pub roots_accepted_at_ns: Option<u64>,
136    pub components_provisioned_at_ns: Option<u64>,
137    pub published_fleet_registry: Option<FleetRegistryVersion>,
138    pub service_topology_published_at_ns: Option<u64>,
139    pub directories_confirmed_at_ns: Option<u64>,
140    pub runtimes_activated_at_ns: Option<u64>,
141}
142
143/// Fresh-install or monotonic scale-out scope covered by one plan.
144#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
145#[serde(deny_unknown_fields)]
146pub enum FleetComponentProvisioningOperation {
147    FreshInstall,
148    ScaleOut {
149        deployment: ComponentGroupDeploymentId,
150        previous_placements: u32,
151        requested_placements: u32,
152    },
153}
154
155/// One selected root's complete canonical provisioning batch.
156#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
157#[serde(deny_unknown_fields)]
158pub struct FleetSubnetRootProvisioningBatch {
159    pub root: FleetSubnetRootBinding,
160    pub active_release_set: FleetSubnetRootReleaseSet,
161    pub placements: Vec<ComponentGroupPlacementPlan>,
162}
163
164/// One materialized copy of a completely flattened Component Group.
165#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
166#[serde(deny_unknown_fields)]
167pub struct ComponentGroupPlacementPlan {
168    pub group_placement: ComponentGroupPlacementId,
169    pub component_group: ComponentGroupSpecId,
170    pub entries: Vec<ComponentGroupPlanEntry>,
171}
172
173/// One exact top-level Component occurrence within a group placement.
174#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
175#[serde(deny_unknown_fields)]
176pub struct ComponentGroupPlanEntry {
177    pub member_path: ComponentGroupMemberPath,
178    pub component_spec: ComponentSpecId,
179    pub spec_hash: [u8; 32],
180    pub purpose: ComponentDeploymentPurpose,
181    pub labels: Vec<ComponentDeploymentLabel>,
182    pub limits: ComponentDeploymentLimits,
183}
184
185/// Coordinator-authenticated command asking one root to retain its exact plan batch.
186#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
187#[serde(deny_unknown_fields)]
188pub struct RootComponentProvisioningAcceptanceRequest {
189    pub fleet_registry: FleetRegistryVersion,
190    pub configuration_digest: ComponentDeploymentConfigurationDigest,
191    pub operation_id: [u8; 32],
192    pub plan_hash: [u8; 32],
193    pub batch: FleetSubnetRootProvisioningBatch,
194}
195
196/// Read-only lookup key for one exact root provisioning operation.
197#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
198#[serde(deny_unknown_fields)]
199pub struct RootComponentProvisioningStatusRequest {
200    pub operation_id: [u8; 32],
201    pub plan_hash: [u8; 32],
202}
203
204/// Coordinator-authenticated command advancing one exact bounded provisioning step.
205#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
206#[serde(deny_unknown_fields)]
207pub struct RootComponentProvisioningAdvanceRequest {
208    pub operation_id: [u8; 32],
209    pub plan_hash: [u8; 32],
210    pub expected_reserved_component_count: u32,
211    pub expected_claimed_component_count: u32,
212    pub expected_installed_component_count: u32,
213    pub expected_registry_committed_component_count: u32,
214}
215
216/// One exact member of a root-derived Component Group Directory.
217#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
218#[serde(deny_unknown_fields)]
219pub struct ComponentGroupDirectoryMember {
220    pub member_path: ComponentGroupMemberPath,
221    pub component_spec: ComponentSpecId,
222    pub purpose: ComponentDeploymentPurpose,
223    pub labels: Vec<ComponentDeploymentLabel>,
224    pub binding: ComponentBinding,
225}
226
227/// Protected origin of one root-derived Component Group Directory.
228#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
229#[serde(deny_unknown_fields)]
230pub struct ComponentGroupDirectoryProvenance {
231    pub authority: crate::ids::FleetRegistryAuthority,
232    pub fleet_subnet_root: Principal,
233    pub group_placement: ComponentGroupPlacementId,
234    pub component_group: ComponentGroupSpecId,
235    pub operation_id: [u8; 32],
236    pub plan_hash: [u8; 32],
237    pub placement_receipt_content_hash: [u8; 32],
238}
239
240/// Complete bounded sibling projection for one materialized Component Group placement.
241#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
242#[serde(deny_unknown_fields)]
243pub struct ComponentGroupDirectory {
244    pub provenance: ComponentGroupDirectoryProvenance,
245    pub members: Vec<ComponentGroupDirectoryMember>,
246}
247
248/// Compact proof of one exact Component Directory delivered during publication.
249#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
250#[serde(deny_unknown_fields)]
251pub struct ComponentDirectoryPublicationEvidence {
252    pub component: crate::ids::ComponentInstanceId,
253    pub content_hash: [u8; 32],
254}
255
256/// Compact proof of one exact Component Group Directory delivered during publication.
257#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
258#[serde(deny_unknown_fields)]
259pub struct ComponentGroupDirectoryPublicationEvidence {
260    pub group_placement: ComponentGroupPlacementId,
261    pub content_hash: [u8; 32],
262}
263
264/// Complete root-local evidence for one published provisioning batch.
265#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
266#[serde(deny_unknown_fields)]
267pub struct RootComponentPublicationEvidence {
268    pub fleet_registry: FleetRegistryVersion,
269    pub fleet_directory_content_hash: [u8; 32],
270    pub component_directories: Vec<ComponentDirectoryPublicationEvidence>,
271    pub component_group_directories: Vec<ComponentGroupDirectoryPublicationEvidence>,
272}
273
274/// Coordinator-authenticated command advancing one bounded root publication step.
275#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
276#[serde(deny_unknown_fields)]
277pub struct RootComponentPublicationRequest {
278    pub operation_id: [u8; 32],
279    pub plan_hash: [u8; 32],
280    pub published_fleet_registry: FleetRegistryVersion,
281    pub expected_published_component_count: u32,
282}
283
284/// Coordinator-authenticated command advancing one bounded root activation step.
285#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
286#[serde(deny_unknown_fields)]
287pub struct RootComponentActivationRequest {
288    pub operation_id: [u8; 32],
289    pub plan_hash: [u8; 32],
290    pub expected_activated_component_count: u32,
291    pub expected_root_runtime_active: bool,
292}
293
294/// Compact terminal evidence binding Component inventory and root runtime activation.
295#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
296#[serde(deny_unknown_fields)]
297pub struct RootComponentActivationEvidence {
298    pub fleet_activation_operation_id: [u8; 32],
299    pub initial_inventory_hash: [u8; 32],
300    pub component_count: u32,
301    pub root_activated_at_ns: u64,
302}
303
304/// One exact provisioned Component occurrence and its committed Registry identity.
305#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
306#[serde(deny_unknown_fields)]
307pub struct RootProvisionedGroupMember {
308    pub member_path: ComponentGroupMemberPath,
309    pub component_spec: ComponentSpecId,
310    pub purpose: ComponentDeploymentPurpose,
311    pub limits: ComponentDeploymentLimits,
312    pub binding: ComponentBinding,
313    pub component_registry_revision: u64,
314    pub component_registry_content_hash: [u8; 32],
315}
316
317/// Complete provisioned result for one exact group placement on this root.
318#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
319#[serde(deny_unknown_fields)]
320pub struct RootProvisionedGroupPlacement {
321    pub group_placement: ComponentGroupPlacementId,
322    pub component_group: ComponentGroupSpecId,
323    pub members: Vec<RootProvisionedGroupMember>,
324}
325
326/// Complete group-partitioned result of one root provisioning operation.
327#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
328#[serde(deny_unknown_fields)]
329pub struct RootComponentProvisioningResult {
330    pub placements: Vec<RootProvisionedGroupPlacement>,
331}
332
333/// Durable aggregate progress of one root provisioning batch.
334#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
335pub enum RootComponentProvisioningPhase {
336    Accepted,
337    Provisioned,
338    Published,
339    RuntimesActive,
340}
341
342/// Durable progress or complete terminal result for one exact root provisioning operation.
343#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
344#[serde(deny_unknown_fields)]
345pub struct RootComponentProvisioningStatusResponse {
346    pub operation_id: [u8; 32],
347    pub plan_hash: [u8; 32],
348    pub fleet_registry: FleetRegistryVersion,
349    pub configuration_digest: ComponentDeploymentConfigurationDigest,
350    pub fleet_subnet_root: Principal,
351    pub phase: RootComponentProvisioningPhase,
352    pub placement_count: u32,
353    pub component_count: u32,
354    pub reserved_component_count: u32,
355    pub claimed_component_count: u32,
356    pub installed_component_count: u32,
357    pub registry_committed_component_count: u32,
358    pub published_component_count: u32,
359    pub activated_component_count: u32,
360    pub root_runtime_active: bool,
361    pub result: Option<RootComponentProvisioningResult>,
362    pub publication: Option<RootComponentPublicationEvidence>,
363    pub activation: Option<RootComponentActivationEvidence>,
364    pub accepted_at_ns: u64,
365    pub provisioned_at_ns: Option<u64>,
366    pub published_at_ns: Option<u64>,
367    pub activation_started_at_ns: Option<u64>,
368    pub runtimes_activated_at_ns: Option<u64>,
369    pub receipt_content_hash: [u8; 32],
370}