Skip to main content

canic_core/ids/fleet_topology/
mod.rs

1//! Module: ids::fleet_topology
2//!
3//! Responsibility: define protected Fleet topology, admission, limit, and binding facts.
4//! Does not own: configuration compilation, placement decisions, Registry mutation, or storage.
5//! Boundary: these passive cross-layer contracts are validated before authoritative use.
6
7use crate::{
8    cdk::types::Cycles,
9    ids::{
10        CanisterRole, ComponentInstanceId, ComponentSpecId, FleetBinding, ReleaseBuildId, SubnetId,
11    },
12};
13use candid::{CandidType, Principal};
14use serde::{Deserialize, Serialize};
15use std::fmt;
16
17///
18/// ComponentTopologyDigest
19///
20/// SHA-256 identity of one canonical root-local Component Topology projection.
21///
22
23#[derive(
24    CandidType, Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
25)]
26#[serde(transparent)]
27pub struct ComponentTopologyDigest([u8; 32]);
28
29impl ComponentTopologyDigest {
30    #[must_use]
31    pub const fn from_bytes(bytes: [u8; 32]) -> Self {
32        Self(bytes)
33    }
34
35    #[must_use]
36    pub const fn as_bytes(&self) -> &[u8; 32] {
37        &self.0
38    }
39
40    #[must_use]
41    pub const fn into_bytes(self) -> [u8; 32] {
42        self.0
43    }
44}
45
46impl fmt::Display for ComponentTopologyDigest {
47    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48        for byte in self.0 {
49            write!(formatter, "{byte:02x}")?;
50        }
51        Ok(())
52    }
53}
54
55///
56/// CyclesFundingBudget
57///
58/// Positive aggregate cycles-funding ceiling applied over one bounded window.
59///
60
61#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
62#[serde(deny_unknown_fields)]
63pub struct CyclesFundingBudget {
64    pub window_secs: u64,
65    pub maximum_cycles: Cycles,
66}
67
68///
69/// FleetSubnetCanisterPoolConfig
70///
71/// Immutable prepaid empty-Canister inventory policy for one Fleet Subnet Root.
72///
73
74#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
75#[serde(deny_unknown_fields)]
76pub struct FleetSubnetCanisterPoolConfig {
77    /// Ready empty Canisters automatically maintained for the root.
78    pub minimum_size: u32,
79    /// Ceiling for standby and operator-imported pool assets.
80    ///
81    /// Recycled assets remain tracked even when their return temporarily exceeds this target.
82    pub maximum_size: u32,
83    /// Minimum retained balance required before a pool asset becomes Ready.
84    pub canister_cycles: Cycles,
85}
86
87///
88/// ComponentSpecAdmission
89///
90/// Immutable permission and concrete-instance ceiling for one Spec on one Fleet Subnet Root.
91///
92
93#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94#[serde(deny_unknown_fields)]
95pub struct ComponentSpecAdmission {
96    pub component_spec: ComponentSpecId,
97    pub spec_hash: [u8; 32],
98    pub maximum_root_instances: u32,
99}
100
101///
102/// FleetSubnetRootLimits
103///
104/// Immutable aggregate policy ceilings for one Fleet Subnet Root.
105///
106
107#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
108#[serde(deny_unknown_fields)]
109pub struct FleetSubnetRootLimits {
110    pub maximum_component_instances: u32,
111    pub maximum_registry_bytes: u64,
112    pub maximum_wasm_store_bytes: u64,
113    pub canister_pool: FleetSubnetCanisterPoolConfig,
114    pub cycles_funding: CyclesFundingBudget,
115    /// Maximum accepted or committed Component Group placements on this root.
116    pub maximum_group_placements: u32,
117}
118
119///
120/// FleetCoordinatorBinding
121///
122/// Immutable identity and exact physical placement of one Fleet Coordinator.
123///
124
125#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
126#[serde(deny_unknown_fields)]
127pub struct FleetCoordinatorBinding {
128    pub fleet: FleetBinding,
129    pub coordinator_subnet: SubnetId,
130    pub coordinator: Principal,
131}
132
133///
134/// FleetRegistryAuthority
135///
136/// Exact Coordinator binding and reinstall-local authority epoch for one Fleet Registry.
137///
138
139#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
140#[serde(deny_unknown_fields)]
141pub struct FleetRegistryAuthority {
142    pub binding: FleetCoordinatorBinding,
143    pub epoch: u64,
144}
145
146///
147/// FleetSubnetRootBinding
148///
149/// Complete immutable identity, placement, admissions, and limits of one Fleet Subnet Root.
150///
151
152#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
153#[serde(deny_unknown_fields)]
154pub struct FleetSubnetRootBinding {
155    pub authority: FleetRegistryAuthority,
156    pub placement_subnet: SubnetId,
157    pub fleet_subnet_root: Principal,
158    pub component_admissions: Vec<ComponentSpecAdmission>,
159    pub component_topology_digest: ComponentTopologyDigest,
160    pub limits: FleetSubnetRootLimits,
161}
162
163///
164/// FleetSubnetWasmStoreAuthority
165///
166/// Exact reciprocal authority retained by one root and its host-installed sibling Store.
167///
168
169#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
170#[serde(deny_unknown_fields)]
171pub struct FleetSubnetWasmStoreAuthority {
172    pub authority: FleetRegistryAuthority,
173    pub placement_subnet: SubnetId,
174    pub fleet_subnet_root: Principal,
175    pub wasm_store: Principal,
176    pub installation_controller: Principal,
177    pub release_build_id: ReleaseBuildId,
178    pub wasm_module_hash: [u8; 32],
179}
180
181///
182/// ComponentBinding
183///
184/// Complete immutable identity and placement of one concrete Component.
185///
186
187#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
188#[serde(deny_unknown_fields)]
189pub struct ComponentBinding {
190    pub authority: FleetRegistryAuthority,
191    pub component: ComponentInstanceId,
192    pub component_spec: ComponentSpecId,
193    pub spec_hash: [u8; 32],
194    pub role: CanisterRole,
195    pub placement_subnet: SubnetId,
196    pub fleet_subnet_root: Principal,
197    pub canister_id: Principal,
198}
199
200///
201/// ComponentChildBinding
202///
203/// Complete immutable identity of one child at any depth in one exact Component tree.
204///
205
206#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
207#[serde(deny_unknown_fields)]
208pub struct ComponentChildBinding {
209    pub component: ComponentBinding,
210    pub parent_canister_id: Principal,
211    pub role: CanisterRole,
212    pub canister_id: Principal,
213}
214
215///
216/// ManagedCanisterBinding
217///
218/// Immutable Registry-issued identity retained by one managed application Canister.
219///
220
221#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
222#[serde(deny_unknown_fields)]
223pub enum ManagedCanisterBinding {
224    Component(ComponentBinding),
225    ComponentChild(ComponentChildBinding),
226}