Skip to main content

canic_core/dto/
role.rs

1//! Module: dto::role
2//!
3//! Responsibility: carry the shared role-owned status boundary values.
4//! Does not own: capability derivation, authorization, status lookup, or workflow policy.
5//! Boundary: role-specific status enums compose these passive bounded values.
6
7use crate::{
8    dto::{
9        component_registry::ComponentRuntimeStatusResponse,
10        fleet_activation::FleetActivationStatusResponse,
11        fleet_registry::FleetSubnetRootDrainingReservationResponse,
12        metadata::CanicMetadataResponse, metrics::MetricsKind, page::PageRequest, prelude::*,
13    },
14    log::Level,
15};
16
17/// Closed compiled capability identity exposed by the immutable role overview.
18#[derive(
19    CandidType, Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
20)]
21#[remain::sorted]
22pub enum RoleCapability {
23    AutomaticTopup,
24    ChildProvisioning,
25    DelegatedTokenIssuer,
26    DelegatedTokenVerifier,
27    FleetAdmissionProjection,
28    FleetCoordinator,
29    Icrc21,
30    Index,
31    RoleAttestationSigner,
32    RoleAttestationVerifier,
33    Root,
34    RootControlPlane,
35    Runtime,
36    Scaling,
37    Sharding,
38    WasmStore,
39}
40
41/// Immutable role, capability, release, and bootstrap profile-verification response.
42#[derive(CandidType, Clone, Debug, Deserialize)]
43pub struct RoleOverviewResponse {
44    pub role: CanisterRole,
45    pub capabilities: Vec<RoleCapability>,
46    pub protocol_profile_digest: [u8; 32],
47    pub metadata: CanicMetadataResponse,
48    pub bootstrap: BootstrapStatusResponse,
49}
50
51/// Lookup key shared by each role's local durable-operation status variant.
52#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
53pub struct OperationStatusRequest {
54    pub operation_id: [u8; 32],
55}
56
57/// Durable identity returned when one role-owned asynchronous command is accepted.
58#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
59pub struct OperationReceipt {
60    pub operation_id: [u8; 32],
61}
62
63/// Exact Coordinator reservation delivered with one accepted Root-removal intent.
64#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
65pub struct RootRemovalRequest {
66    pub reservation: FleetSubnetRootDrainingReservationResponse,
67}
68
69/// Named response for the protected compiled configuration source.
70#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
71pub struct ConfigStatusResponse {
72    pub toml: String,
73}
74
75/// Named response for the canister's current cycle balance.
76#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
77pub struct CycleBalanceStatusResponse {
78    pub cycles: u128,
79}
80
81/// Bounded log observation selector used by each role status surface.
82#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
83pub struct LogStatusRequest {
84    pub crate_name: Option<String>,
85    pub topic: Option<String>,
86    pub min_level: Option<Level>,
87    pub page: PageRequest,
88}
89
90/// Bounded metrics observation selector used by each role status surface.
91#[derive(CandidType, Clone, Copy, Debug, Deserialize)]
92pub struct MetricsStatusRequest {
93    pub kind: MetricsKind,
94    pub page: PageRequest,
95}
96
97/// Managed runtime configuration detail projected through the operation lane.
98#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
99pub struct ComponentRuntimeOperationStatus {
100    pub operation_id: [u8; 32],
101    pub fleet_activation: FleetActivationStatusResponse,
102    pub runtime: ComponentRuntimeStatusResponse,
103}
104
105pub use crate::dto::state::BootstrapStatusResponse;
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    use candid::{Decode, Encode};
111
112    #[test]
113    fn shared_role_status_requests_round_trip_through_candid() {
114        let operation = OperationStatusRequest {
115            operation_id: [7; 32],
116        };
117        let bytes = Encode!(&operation).expect("encode operation status request");
118        assert_eq!(
119            Decode!(&bytes, OperationStatusRequest).expect("decode operation status request"),
120            operation
121        );
122
123        let receipt = OperationReceipt {
124            operation_id: operation.operation_id,
125        };
126        let bytes = Encode!(&receipt).expect("encode operation receipt");
127        assert_eq!(
128            Decode!(&bytes, OperationReceipt).expect("decode operation receipt"),
129            receipt
130        );
131
132        let logs = LogStatusRequest {
133            crate_name: Some("canic-core".to_string()),
134            topic: Some("Cycles".to_string()),
135            min_level: Some(Level::Warn),
136            page: PageRequest {
137                limit: 25,
138                offset: 50,
139            },
140        };
141        let bytes = Encode!(&logs).expect("encode log status request");
142        assert_eq!(
143            Decode!(&bytes, LogStatusRequest).expect("decode log status request"),
144            logs
145        );
146    }
147}