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