canic_core/ops/
mod.rs

1//! Business-logic helpers that sit between endpoint handlers and the state
2//! layer.
3//!
4//! The ops layer orchestrates multi-step workflows such as provisioning new
5//! canisters,  running scaling/sharding policies, and
6//! synchronizing topology snapshots. Endpoint macros call into these modules so
7//! the public surface remains thin while policy, logging, and validation live
8//! here.
9
10pub mod config;
11pub mod http;
12pub mod icrc;
13pub mod metrics;
14pub mod mgmt;
15pub mod model;
16pub mod orchestration;
17pub mod perf;
18pub mod request;
19pub mod root;
20pub mod runtime;
21pub mod service;
22pub mod signature;
23pub mod sync;
24pub mod timer;
25pub mod types;
26pub mod wasm;
27
28pub use types::*;
29
30/// Common imports for ops submodules and consumers.
31pub mod prelude {
32    pub use crate::{
33        cdk::{
34            api::{canister_self, msg_caller},
35            candid::CandidType,
36            types::{Int, Nat, Principal, Subaccount},
37        },
38        ids::CanisterRole,
39        interface::{
40            InterfaceError,
41            ic::{call::Call, call_and_decode},
42        },
43        log,
44        log::Level,
45        ops::OpsError,
46        types::Cycles,
47    };
48    pub use serde::{Deserialize, Serialize};
49}
50
51use crate::{ThisError, ops::model::memory::EnvOps};
52
53///
54/// OpsError
55/// Error envelope shared across operations submodules
56///
57
58#[derive(Debug, ThisError)]
59pub enum OpsError {
60    /// Raised when a function requires root context, but was called from a child.
61    #[error("operation must be called from the root canister")]
62    NotRoot,
63
64    /// Raised when a function must not be called from root.
65    #[error("operation cannot be called from the root canister")]
66    IsRoot,
67
68    #[error(transparent)]
69    ConfigOpsError(#[from] config::ConfigOpsError),
70
71    #[error(transparent)]
72    ModelOpsError(#[from] model::ModelOpsError),
73
74    #[error(transparent)]
75    RequestOpsError(#[from] request::RequestOpsError),
76
77    #[error(transparent)]
78    SignatureOpsError(#[from] signature::SignatureOpsError),
79
80    #[error(transparent)]
81    SyncOpsError(#[from] sync::SyncOpsError),
82}
83
84impl OpsError {
85    /// Ensure the caller is the root canister.
86    pub fn require_root() -> Result<(), Self> {
87        if EnvOps::is_root() {
88            Ok(())
89        } else {
90            Err(Self::NotRoot)
91        }
92    }
93
94    /// Ensure the caller is not the root canister.
95    pub fn deny_root() -> Result<(), Self> {
96        if EnvOps::is_root() {
97            Err(Self::IsRoot)
98        } else {
99            Ok(())
100        }
101    }
102}