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