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_accepted_root_count: u32,
46    pub expected_provisioned_root_count: u32,
47    pub expected_current_root: Option<FleetComponentProvisioningRootProgress>,
48}
49
50/// Exact root-local cursor copied from passive Coordinator status before one advance.
51#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
52#[serde(deny_unknown_fields)]
53pub struct FleetComponentProvisioningRootProgress {
54    pub fleet_subnet_root: Principal,
55    pub component_count: u32,
56    pub reserved_component_count: u32,
57    pub claimed_component_count: u32,
58    pub installed_component_count: u32,
59    pub registry_committed_component_count: u32,
60}
61
62/// Exact passive lookup key for one Coordinator-owned provisioning operation.
63#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
64#[serde(deny_unknown_fields)]
65pub struct FleetComponentProvisioningStatusRequest {
66    pub operation_id: [u8; 32],
67    pub plan_hash: [u8; 32],
68}
69
70/// Durable Coordinator progress exposed without returning the complete plan.
71#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
72pub enum FleetComponentProvisioningPhase {
73    Planned,
74    AcceptingRoots,
75    RootsAccepted,
76    ProvisioningRoots,
77    ComponentsProvisioned,
78}
79
80/// Compact exact status for one Coordinator-owned provisioning operation.
81#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
82#[serde(deny_unknown_fields)]
83pub struct FleetComponentProvisioningStatusResponse {
84    pub operation_id: [u8; 32],
85    pub plan_hash: [u8; 32],
86    pub fleet_registry: FleetRegistryVersion,
87    pub configuration_digest: ComponentDeploymentConfigurationDigest,
88    pub operation: FleetComponentProvisioningOperation,
89    pub phase: FleetComponentProvisioningPhase,
90    pub directory_confirmation_root_count: u32,
91    pub root_batch_count: u32,
92    pub accepted_root_count: u32,
93    pub acceptance_in_flight_root: Option<Principal>,
94    pub provisioned_root_count: u32,
95    pub current_root: Option<FleetComponentProvisioningRootProgress>,
96    pub provisioning_in_flight_root: Option<Principal>,
97    pub group_placement_count: u32,
98    pub component_count: u32,
99    pub planned_at_ns: u64,
100    pub roots_accepted_at_ns: Option<u64>,
101    pub components_provisioned_at_ns: Option<u64>,
102}
103
104/// Fresh-install or monotonic scale-out scope covered by one plan.
105#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
106#[serde(deny_unknown_fields)]
107pub enum FleetComponentProvisioningOperation {
108    FreshInstall,
109    ScaleOut {
110        deployment: ComponentGroupDeploymentId,
111        previous_placements: u32,
112        requested_placements: u32,
113    },
114}
115
116/// One selected root's complete canonical provisioning batch.
117#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
118#[serde(deny_unknown_fields)]
119pub struct FleetSubnetRootProvisioningBatch {
120    pub root: FleetSubnetRootBinding,
121    pub active_release_set: FleetSubnetRootReleaseSet,
122    pub placements: Vec<ComponentGroupPlacementPlan>,
123}
124
125/// One materialized copy of a completely flattened Component Group.
126#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
127#[serde(deny_unknown_fields)]
128pub struct ComponentGroupPlacementPlan {
129    pub group_placement: ComponentGroupPlacementId,
130    pub component_group: ComponentGroupSpecId,
131    pub entries: Vec<ComponentGroupPlanEntry>,
132}
133
134/// One exact top-level Component occurrence within a group placement.
135#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
136#[serde(deny_unknown_fields)]
137pub struct ComponentGroupPlanEntry {
138    pub member_path: ComponentGroupMemberPath,
139    pub component_spec: ComponentSpecId,
140    pub spec_hash: [u8; 32],
141    pub purpose: ComponentDeploymentPurpose,
142    pub labels: Vec<ComponentDeploymentLabel>,
143    pub limits: ComponentDeploymentLimits,
144}
145
146/// Coordinator-authenticated command asking one root to retain its exact plan batch.
147#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
148#[serde(deny_unknown_fields)]
149pub struct RootComponentProvisioningAcceptanceRequest {
150    pub fleet_registry: FleetRegistryVersion,
151    pub configuration_digest: ComponentDeploymentConfigurationDigest,
152    pub operation_id: [u8; 32],
153    pub plan_hash: [u8; 32],
154    pub batch: FleetSubnetRootProvisioningBatch,
155}
156
157/// Read-only lookup key for one exact root provisioning operation.
158#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
159#[serde(deny_unknown_fields)]
160pub struct RootComponentProvisioningStatusRequest {
161    pub operation_id: [u8; 32],
162    pub plan_hash: [u8; 32],
163}
164
165/// Coordinator-authenticated command advancing one exact bounded provisioning step.
166#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
167#[serde(deny_unknown_fields)]
168pub struct RootComponentProvisioningAdvanceRequest {
169    pub operation_id: [u8; 32],
170    pub plan_hash: [u8; 32],
171    pub expected_reserved_component_count: u32,
172    pub expected_claimed_component_count: u32,
173    pub expected_installed_component_count: u32,
174    pub expected_registry_committed_component_count: u32,
175}
176
177/// One exact provisioned Component occurrence and its committed Registry identity.
178#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
179#[serde(deny_unknown_fields)]
180pub struct RootProvisionedGroupMember {
181    pub member_path: ComponentGroupMemberPath,
182    pub component_spec: ComponentSpecId,
183    pub purpose: ComponentDeploymentPurpose,
184    pub limits: ComponentDeploymentLimits,
185    pub binding: ComponentBinding,
186    pub component_registry_revision: u64,
187    pub component_registry_content_hash: [u8; 32],
188}
189
190/// Complete provisioned result for one exact group placement on this root.
191#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
192#[serde(deny_unknown_fields)]
193pub struct RootProvisionedGroupPlacement {
194    pub group_placement: ComponentGroupPlacementId,
195    pub component_group: ComponentGroupSpecId,
196    pub members: Vec<RootProvisionedGroupMember>,
197}
198
199/// Complete group-partitioned result of one root provisioning operation.
200#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
201#[serde(deny_unknown_fields)]
202pub struct RootComponentProvisioningResult {
203    pub placements: Vec<RootProvisionedGroupPlacement>,
204}
205
206/// Durable aggregate progress of one root provisioning batch.
207#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
208pub enum RootComponentProvisioningPhase {
209    Accepted,
210    Provisioned,
211    Published,
212    RuntimesActive,
213}
214
215/// Durable progress or complete terminal result for one exact root provisioning operation.
216#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
217#[serde(deny_unknown_fields)]
218pub struct RootComponentProvisioningStatusResponse {
219    pub operation_id: [u8; 32],
220    pub plan_hash: [u8; 32],
221    pub fleet_registry: FleetRegistryVersion,
222    pub configuration_digest: ComponentDeploymentConfigurationDigest,
223    pub fleet_subnet_root: Principal,
224    pub phase: RootComponentProvisioningPhase,
225    pub placement_count: u32,
226    pub component_count: u32,
227    pub reserved_component_count: u32,
228    pub claimed_component_count: u32,
229    pub installed_component_count: u32,
230    pub registry_committed_component_count: u32,
231    pub result: Option<RootComponentProvisioningResult>,
232    pub accepted_at_ns: u64,
233    pub provisioned_at_ns: Option<u64>,
234    pub receipt_content_hash: [u8; 32],
235}