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