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