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