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