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}
116
117///
118/// FleetCoordinatorBinding
119///
120/// Immutable identity and exact physical placement of one Fleet Coordinator.
121///
122
123#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
124#[serde(deny_unknown_fields)]
125pub struct FleetCoordinatorBinding {
126    pub fleet: FleetBinding,
127    pub coordinator_subnet: SubnetId,
128    pub coordinator: Principal,
129}
130
131///
132/// FleetRegistryAuthority
133///
134/// Exact Coordinator binding and reinstall-local authority epoch for one Fleet Registry.
135///
136
137#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
138#[serde(deny_unknown_fields)]
139pub struct FleetRegistryAuthority {
140    pub binding: FleetCoordinatorBinding,
141    pub epoch: u64,
142}
143
144///
145/// FleetSubnetRootBinding
146///
147/// Complete immutable identity, placement, admissions, and limits of one Fleet Subnet Root.
148///
149
150#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
151#[serde(deny_unknown_fields)]
152pub struct FleetSubnetRootBinding {
153    pub authority: FleetRegistryAuthority,
154    pub placement_subnet: SubnetId,
155    pub fleet_subnet_root: Principal,
156    pub component_admissions: Vec<ComponentSpecAdmission>,
157    pub component_topology_digest: ComponentTopologyDigest,
158    pub limits: FleetSubnetRootLimits,
159}
160
161///
162/// FleetSubnetWasmStoreAuthority
163///
164/// Exact reciprocal authority retained by one root and its host-installed sibling Store.
165///
166
167#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
168#[serde(deny_unknown_fields)]
169pub struct FleetSubnetWasmStoreAuthority {
170    pub authority: FleetRegistryAuthority,
171    pub placement_subnet: SubnetId,
172    pub fleet_subnet_root: Principal,
173    pub wasm_store: Principal,
174    pub installation_controller: Principal,
175    pub release_build_id: ReleaseBuildId,
176    pub wasm_module_hash: [u8; 32],
177}
178
179///
180/// ComponentBinding
181///
182/// Complete immutable identity and placement of one concrete Component.
183///
184
185#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
186#[serde(deny_unknown_fields)]
187pub struct ComponentBinding {
188    pub authority: FleetRegistryAuthority,
189    pub component: ComponentInstanceId,
190    pub component_spec: ComponentSpecId,
191    pub spec_hash: [u8; 32],
192    pub role: CanisterRole,
193    pub placement_subnet: SubnetId,
194    pub fleet_subnet_root: Principal,
195    pub canister_id: Principal,
196}
197
198///
199/// ComponentChildBinding
200///
201/// Complete immutable identity of one child at any depth in one exact Component tree.
202///
203
204#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
205#[serde(deny_unknown_fields)]
206pub struct ComponentChildBinding {
207    pub component: ComponentBinding,
208    pub parent_canister_id: Principal,
209    pub role: CanisterRole,
210    pub canister_id: Principal,
211}
212
213///
214/// ManagedCanisterBinding
215///
216/// Immutable Registry-issued identity retained by one managed application Canister.
217///
218
219#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
220#[serde(deny_unknown_fields)]
221pub enum ManagedCanisterBinding {
222    Component(ComponentBinding),
223    ComponentChild(ComponentChildBinding),
224}