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::{CanisterRole, ComponentInstanceId, ComponentSpecId, FleetBinding, SubnetId},
10};
11use candid::{CandidType, Principal};
12use serde::{Deserialize, Serialize};
13use std::fmt;
14
15///
16/// ComponentTopologyDigest
17///
18/// SHA-256 identity of one canonical root-local Component Topology projection.
19///
20
21#[derive(
22    CandidType, Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
23)]
24#[serde(transparent)]
25pub struct ComponentTopologyDigest([u8; 32]);
26
27impl ComponentTopologyDigest {
28    #[must_use]
29    pub const fn from_bytes(bytes: [u8; 32]) -> Self {
30        Self(bytes)
31    }
32
33    #[must_use]
34    pub const fn as_bytes(&self) -> &[u8; 32] {
35        &self.0
36    }
37
38    #[must_use]
39    pub const fn into_bytes(self) -> [u8; 32] {
40        self.0
41    }
42}
43
44impl fmt::Display for ComponentTopologyDigest {
45    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
46        for byte in self.0 {
47            write!(formatter, "{byte:02x}")?;
48        }
49        Ok(())
50    }
51}
52
53///
54/// CyclesFundingBudget
55///
56/// Positive aggregate cycles-funding ceiling applied over one bounded window.
57///
58
59#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
60#[serde(deny_unknown_fields)]
61pub struct CyclesFundingBudget {
62    pub window_secs: u64,
63    pub maximum_cycles: Cycles,
64}
65
66///
67/// FleetSubnetCanisterPoolConfig
68///
69/// Immutable prepaid empty-Canister inventory policy for one Fleet Subnet Root.
70///
71
72#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
73#[serde(deny_unknown_fields)]
74pub struct FleetSubnetCanisterPoolConfig {
75    /// Ready empty Canisters the root continuously attempts to retain.
76    pub minimum_size: u32,
77    /// Ceiling for configured imports and proactive refill inventory.
78    ///
79    /// Recycled assets remain tracked even when their return temporarily exceeds this target.
80    pub maximum_size: u32,
81    /// Cycles placed on each Canister created by the root for this pool.
82    pub canister_cycles: Cycles,
83}
84
85///
86/// ComponentSpecAdmission
87///
88/// Immutable permission and concrete-instance ceiling for one Spec on one Fleet Subnet Root.
89///
90
91#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
92#[serde(deny_unknown_fields)]
93pub struct ComponentSpecAdmission {
94    pub component_spec: ComponentSpecId,
95    pub spec_hash: [u8; 32],
96    pub maximum_root_instances: u32,
97}
98
99///
100/// FleetSubnetRootLimits
101///
102/// Immutable aggregate policy ceilings for one Fleet Subnet Root.
103///
104
105#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
106#[serde(deny_unknown_fields)]
107pub struct FleetSubnetRootLimits {
108    pub maximum_component_instances: u32,
109    pub maximum_managed_canisters: u32,
110    pub maximum_registry_bytes: u64,
111    pub maximum_wasm_store_bytes: u64,
112    pub canister_pool: FleetSubnetCanisterPoolConfig,
113    pub cycles_funding: CyclesFundingBudget,
114}
115
116///
117/// FleetCoordinatorBinding
118///
119/// Immutable identity and exact physical placement of one Fleet Coordinator.
120///
121
122#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
123#[serde(deny_unknown_fields)]
124pub struct FleetCoordinatorBinding {
125    pub fleet: FleetBinding,
126    pub coordinator_subnet: SubnetId,
127    pub coordinator: Principal,
128}
129
130///
131/// FleetRegistryAuthority
132///
133/// Exact Coordinator binding and reinstall-local authority epoch for one Fleet Registry.
134///
135
136#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
137#[serde(deny_unknown_fields)]
138pub struct FleetRegistryAuthority {
139    pub binding: FleetCoordinatorBinding,
140    pub epoch: u64,
141}
142
143///
144/// FleetSubnetRootBinding
145///
146/// Complete immutable identity, placement, admissions, and limits of one Fleet Subnet Root.
147///
148
149#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
150#[serde(deny_unknown_fields)]
151pub struct FleetSubnetRootBinding {
152    pub authority: FleetRegistryAuthority,
153    pub placement_subnet: SubnetId,
154    pub fleet_subnet_root: Principal,
155    pub component_admissions: Vec<ComponentSpecAdmission>,
156    pub component_topology_digest: ComponentTopologyDigest,
157    pub limits: FleetSubnetRootLimits,
158}
159
160///
161/// ComponentBinding
162///
163/// Complete immutable identity and placement of one concrete Component.
164///
165
166#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
167#[serde(deny_unknown_fields)]
168pub struct ComponentBinding {
169    pub authority: FleetRegistryAuthority,
170    pub component: ComponentInstanceId,
171    pub component_spec: ComponentSpecId,
172    pub spec_hash: [u8; 32],
173    pub role: CanisterRole,
174    pub placement_subnet: SubnetId,
175    pub fleet_subnet_root: Principal,
176    pub canister_id: Principal,
177}
178
179///
180/// ComponentChildBinding
181///
182/// Complete immutable identity of one child at any depth in one exact Component tree.
183///
184
185#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
186#[serde(deny_unknown_fields)]
187pub struct ComponentChildBinding {
188    pub component: ComponentBinding,
189    pub parent_canister_id: Principal,
190    pub role: CanisterRole,
191    pub canister_id: Principal,
192}
193
194///
195/// ManagedCanisterBinding
196///
197/// Immutable Registry-issued identity retained by one managed application Canister.
198///
199
200#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
201#[serde(deny_unknown_fields)]
202pub enum ManagedCanisterBinding {
203    Component(ComponentBinding),
204    ComponentChild(ComponentChildBinding),
205}