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