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 canister;
11pub mod config;
12pub mod icrc;
13pub mod lifecycle;
14pub mod model;
15pub mod request;
16pub mod root;
17pub mod signature;
18pub mod sync;
19pub mod types;
20pub mod wasm;
21
22pub use types::*;
23
24/// Common imports for ops submodules and consumers.
25pub mod prelude {
26    pub use crate::{
27        cdk::{
28            api::{canister_self, msg_caller},
29            call::Call,
30            candid::CandidType,
31        },
32        ids::CanisterRole,
33        interface::{InterfaceError, ic::call_and_decode},
34        log,
35        log::Level,
36        ops::OpsError,
37        types::{Cycles, Int, Nat, Principal, Subaccount},
38    };
39    pub use serde::{Deserialize, Serialize};
40}
41
42use crate::{ThisError, ops::model::memory::EnvOps};
43
44///
45/// OpsError
46/// Error envelope shared across operations submodules
47///
48
49#[derive(Debug, ThisError)]
50pub enum OpsError {
51    /// Raised when a function requires root context, but was called from a child.
52    #[error("operation must be called from the root canister")]
53    NotRoot,
54
55    /// Raised when a function must not be called from root.
56    #[error("operation cannot be called from the root canister")]
57    IsRoot,
58
59    #[error(transparent)]
60    ConfigOpsError(#[from] config::ConfigOpsError),
61
62    #[error(transparent)]
63    ModelOpsError(#[from] model::ModelOpsError),
64
65    #[error(transparent)]
66    RequestOpsError(#[from] request::RequestOpsError),
67
68    #[error(transparent)]
69    SignatureOpsError(#[from] signature::SignatureOpsError),
70
71    #[error(transparent)]
72    SyncOpsError(#[from] sync::SyncOpsError),
73}
74
75impl OpsError {
76    /// Ensure the caller is the root canister.
77    pub fn require_root() -> Result<(), Self> {
78        if EnvOps::is_root() {
79            Ok(())
80        } else {
81            Err(Self::NotRoot)
82        }
83    }
84
85    /// Ensure the caller is not the root canister.
86    pub fn deny_root() -> Result<(), Self> {
87        if EnvOps::is_root() {
88            Err(Self::IsRoot)
89        } else {
90            Ok(())
91        }
92    }
93}