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    RootDelegation,
36    Runtime,
37    Scaling,
38    Sharding,
39    WasmStore,
40}
41
42/// Immutable role, capability, release, and bootstrap profile-verification response.
43#[derive(CandidType, Clone, Debug, Deserialize)]
44pub struct RoleOverviewResponse {
45    pub role: CanisterRole,
46    pub capabilities: Vec<RoleCapability>,
47    pub protocol_profile_digest: [u8; 32],
48    pub metadata: CanicMetadataResponse,
49    pub bootstrap: BootstrapStatusResponse,
50}
51
52/// Lookup key shared by each role's local durable-operation status variant.
53#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
54pub struct OperationStatusRequest {
55    pub operation_id: [u8; 32],
56}
57
58/// Durable identity returned when one role-owned asynchronous command is accepted.
59#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
60pub struct OperationReceipt {
61    pub operation_id: [u8; 32],
62}
63
64/// Exact Coordinator reservation delivered with one accepted Root-removal intent.
65#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
66pub struct RootRemovalRequest {
67    pub reservation: FleetSubnetRootDrainingReservationResponse,
68}
69
70/// Named response for the protected compiled configuration source.
71#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
72pub struct ConfigStatusResponse {
73    pub toml: String,
74}
75
76/// Named response for the canister's current cycle balance.
77#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
78pub struct CycleBalanceStatusResponse {
79    pub cycles: u128,
80}
81
82/// Bounded log observation selector used by each role status surface.
83#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
84pub struct LogStatusRequest {
85    pub crate_name: Option<String>,
86    pub topic: Option<String>,
87    pub min_level: Option<Level>,
88    pub page: PageRequest,
89}
90
91/// Bounded metrics observation selector used by each role status surface.
92#[derive(CandidType, Clone, Copy, Debug, Deserialize)]
93pub struct MetricsStatusRequest {
94    pub kind: MetricsKind,
95    pub page: PageRequest,
96}
97
98/// Managed runtime configuration detail projected through the operation lane.
99#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
100pub struct ComponentRuntimeOperationStatus {
101    pub operation_id: [u8; 32],
102    pub fleet_activation: FleetActivationStatusResponse,
103    pub runtime: ComponentRuntimeStatusResponse,
104}
105
106pub use crate::dto::state::BootstrapStatusResponse;
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111    use candid::{Decode, Encode};
112
113    #[test]
114    fn shared_role_status_requests_round_trip_through_candid() {
115        let operation = OperationStatusRequest {
116            operation_id: [7; 32],
117        };
118        let bytes = Encode!(&operation).expect("encode operation status request");
119        assert_eq!(
120            Decode!(&bytes, OperationStatusRequest).expect("decode operation status request"),
121            operation
122        );
123
124        let receipt = OperationReceipt {
125            operation_id: operation.operation_id,
126        };
127        let bytes = Encode!(&receipt).expect("encode operation receipt");
128        assert_eq!(
129            Decode!(&bytes, OperationReceipt).expect("decode operation receipt"),
130            receipt
131        );
132
133        let logs = LogStatusRequest {
134            crate_name: Some("canic-core".to_string()),
135            topic: Some("Cycles".to_string()),
136            min_level: Some(Level::Warn),
137            page: PageRequest {
138                limit: 25,
139                offset: 50,
140            },
141        };
142        let bytes = Encode!(&logs).expect("encode log status request");
143        assert_eq!(
144            Decode!(&bytes, LogStatusRequest).expect("decode log status request"),
145            logs
146        );
147    }
148}