canic 0.4.12

Canic β€” a canister orchestration and management toolkit for the Internet Computer
Documentation

πŸ§‘β€πŸ”§ Canic πŸ§‘β€πŸ”§ – Internet Computer Orchestration

Crates.io Docs.rs License

Canic is a Rust toolkit for orchestrating Internet Computer (IC) canisters at scale. It packages the battle-tested patterns from large multi-canister deployments into a reusable crate: lifecycle macros, stable-memory helpers, orchestration ops, and endpoint bundles that keep your boundary layer thin while enforcing clean layering inside the canister graph.

The crate was historically known as ICU (Internet Computer Utilities). All core APIs have been renamed to Canic for the crates.io release.

Highlights

  • 🧩 Bootstrap macros – canic::start!, canic::start_root!, canic_build!, and canic_build_root! wire init/upgrade hooks, export endpoints, and validate config at compile time.
  • 🧠 State layers – opinionated separation for stable memory, volatile state, ops/business logic, and public endpoints.
  • πŸ—ΊοΈ Topology-aware config – typed subnet blocks, app directories, and reserve policies validated straight from canic.toml.
  • πŸ” Auth utilities – composable guards (auth_require_any!, auth_require_all!) for controllers, parents, whitelist principals, and more.
  • πŸ—ƒοΈ Stable memory ergonomics – ic_memory!, ic_memory_range!, and eager_static! manage IC stable structures safely across upgrades.
  • πŸ“¦ WASM registry – consistently ship/lookup child canister WASMs with hash tracking.
  • πŸͺ΅ Configurable logging – ring/age retention with second-level timestamps and paged log/query helpers.
  • ♻️ Lifecycle helpers – shard policies, reserve pools, scaling helpers, and sync cascades keep fleets healthy.
  • πŸ§ͺ Ready for CI – Rust 2024 edition, MSRV 1.90, with cargo fmt, cargo clippy -- -D warnings, and cargo test wired via make targets.

For canister signatures, use the ops faΓ§ade (ops::signature::prepare/get/verify) instead of feeding raw principals into ic-signature-verification; verify builds the proper DER canister-sig public key and domain-prefixed message to avoid slice panics on short (10-byte) canister IDs. Pass the signing domain and seed from the caller rather than hardcoding them.

πŸ“ Repository Layout

  • assets/ – documentation media (logo and shared imagery).
  • crates/ – workspace crates.
    • canic/ – core library crate with orchestration primitives and macros.
      • src/auth.rs & src/guard.rs – reusable authorization helpers.
      • src/cdk/ – IC CDK shims and patched utilities used by the macros.
      • src/config/ – configuration loaders, validators, and schema helpers.
      • src/env/ – curated canister ID constants (ck, NNS, SNS) and helpers.
      • src/interface/ – typed wrappers for IC management calls, ck-ledgers, and ICRC ledgers.
      • src/log.rs – logging macros.
      • src/macros/ – public macro entrypoints (canic::start!, canic_endpoints_*, memory helpers).
      • src/memory/ – stable storage abstractions and registries built on ic-stable-structures.
      • src/ops/ – orchestration/business logic bridging memory and state layers.
      • src/runtime.rs – runtime glue shared by macros.
      • src/serialize.rs – deterministic codecs.
      • src/spec/ – representations of external IC specs (ICRC, NNS, SNS, etc.).
      • src/state/ – volatile runtime state caches and registries.
      • src/types/ – shared domain types.
      • src/utils/ – time helpers, wasm utilities, etc.
      • examples/ – runnable demos for guards, shard lifecycle, and canister ops.
    • canisters/ – reference canisters that exercise the library end to end:
      • root/ orchestrator tying together shards, scaling, and reserve flows.
      • app/ – sample application canister used in integration flows.
      • auth/ – auxiliary canister covering authorization patterns.
      • shard/, shard_hub/ – shard lifecycle pair for pool management.
      • scale/, scale_hub/ – reserve scaling agents demonstrating capacity workflows.
      • blank/ – minimal canister template.
  • scripts/ – build, release, and environment helpers.
    • app/ – dfx bootstrap scripts for the demo topology.
    • ci/ – version bumping and security checks used by CI.
    • env/ – local environment utilities (e.g., shared env updates).
  • .github/workflows/ – CI pipelines (fmt, clippy, tests, release).
  • .githooks/ – optional git hooks; pre-commit formats and runs cargo sort before committing.
  • .cargo/ – workspace Cargo config that pins the tmp dir to avoid cross-device link errors when sandboxed.

Getting Started

1. Install

Inside your workspace:

cargo add canic

Or reference the workspace path if you pulled the repository directly.

2. Configure build.rs

Every canister crate should declare a config file (default name: canic.toml). Use one of the provided build macros:

// Root canister build.rs
fn main() {
    canic::canic_build_root!("../canic.toml");
}
// Non-root canister build.rs
fn main() {
    canic::build!("../canic.toml");
}

The macro validates the TOML during compilation, emits the right cfg flags (such as canic and canic_root), and exposes the canonical config path via CANIC_CONFIG_PATH.

3. Bootstrap your canister

In lib.rs:

use canic::prelude::*;
use canic::canister::EXAMPLE;

canic::start!(EXAMPLE); // or canic::start_root!() for the orchestrator canister

async fn canic_setup() {}
async fn canic_install(_: Option<Vec<u8>>) {}
async fn canic_upgrade() {}

See crates/canisters/root and the hub/shard reference canisters under crates/canisters/* for end-to-end patterns, including WASM registries and endpoint exports.

4. Define your topology

Populate canic.toml with subnet definitions, directory membership, and per-canister policies. Each [subnets.<name>] block lists auto_create and subnet_directory canister types, then nests [subnets.<name>.canisters.<type>] tables for top-up settings plus optional sharding and scaling pools. Global tables such as controllers, app_directory, reserve, log, and standards shape the overall cluster. The [log] block controls ring/age retention in seconds. The full schema lives in CONFIG.md.

Layered Architecture

Canic enforces clear separation between storage, transient state, orchestration logic, and public endpoints:

  • memory/ – stable data backed by ic-stable-structures (e.g. shard registries, reserve pools).
  • state/ – volatile caches and session stores that reset on upgrade.
  • ops/ – business logic tying state + memory together (sharding policies, scaling flows, reserve management).
  • endpoints/ – macro-generated IC entrypoints that delegate to ops/ and keep boundary code minimal.
  • Temporary exception (target revisit in ~2 weeks): when no ops faΓ§ade exists yet, read-only queries may pull directly from memory/ or state/; mutations should still flow through ops/.

Capabilities & Endpoints

Sharding πŸ“¦

canic::ops::ext::sharding assigns tenants to shard canisters according to a ShardingPolicy (initial capacity, max shards, growth thresholds). Admin work flows through a single controller-only endpoint:

canic_sharding_admin(cmd: canic::ops::ext::sharding::AdminCommand)
    -> Result<canic::ops::ext::sharding::AdminResult, canic::Error>

Command variants cover register, audit, drain, rebalance, and decommission flows. Your application is responsible for data migration around these moves.

Scaling & Reserve Pools βš–οΈ

  • canic_scaling_registry() provides controller insight into scaling pools via the shared endpoint bundle.
  • Root canisters manage spare capacity through canic::ops::root::reserve and the canic_reserve_* endpoints.

Directory Views πŸ“‡

  • canic_app_directory() returns the prime root directory view for operator dashboards.
  • canic_subnet_directory() exposes the per-subnet directory so children can discover peers.

ICRC Support πŸ“š

The base endpoint bundle includes:

  • icrc10_supported_standards()
  • icrc21_canister_call_consent_message(request)

Register consent messages via state::icrc::Icrc21Registry for rich UX flows.

Tooling & DX

  • Format: cargo fmt --all (or make fmt)
  • Fmt check: make fmt-check
  • Check (type-check only): make check
  • Lint: make clippy
  • Test: make test
  • Build release WASMs: make build
  • Run the example suite: make examples or cargo build -p canic --examples

The make targets pin CARGO_TARGET_DIR/TMPDIR to target/tmp to dodge Invalid cross-device link errors in sandboxed environments. If you prefer raw cargo invocations, mirror the same env:

CARGO_TARGET_DIR=$PWD/target TMPDIR=$PWD/target/tmp cargo build -p canic --examples

rust-toolchain.toml pins the toolchain so CI and local builds stay in sync.

Examples

Explore the runnable examples under crates/canic/examples/:

  • auth_rules.rs – compose guard policies.
  • minimal_root.rs – bootstrap a bare-bones orchestrator.
  • ops_create_canister.rs – walk through the create-canister flow.
  • shard_lifecycle.rs – simulate register/assign/drain/rebalance operations.
cargo run -p canic --example auth_rules

Project Status & Contributing

Canic is the successor to the internal ICU toolkit. The repository is in the process of being opened for wider use; issues and PRs are currently limited to the core team. Follow AGENTS.md, VERSIONING.md, and RELEASE_GUIDE.md for workflow expectations.

License

MIT. See LICENSE for details.