We are exploring whether Motoko canisters could participate as fully managed Components inside a Canic Fleet.
The short answer appears to be: yes, this is technically feasible.
However, this would be an interoperability feature—not a rewrite programme.
What We Are Considering
A Motoko application canister would be able to:
- be built and qualified through Canic;
- be installed from the Fleet Subnet Root’s Wasm Store;
- participate in Canic’s managed Directory and activation lifecycle;
- report its protected identity and runtime status;
- request admitted child canisters through its Fleet Subnet Root; and
- call separately deployed Rust services over Candid.
The intended topology looks roughly like this:
Canic host
|
| Cargo or qualified Mops build
v
Fleet Subnet Root + Wasm Store
|
+-- Rust Component
|
+-- Motoko Component
|
| typed Candid calls
v
Rust IcyDB service
The Fleet Subnet Root remains the Canic deployment and Registry authority.
What This Does Not Mean
To be completely explicit:
We do not intend to rewrite Canic, IcyDB, or any of our existing Rust products in Motoko.
The following remain Rust:
- Canic’s host, CLI, runtime, core, macros, backup system, and control plane;
- Fleet Coordinator, Fleet Subnet Root, and Wasm Store;
- IcyDB’s schema, planner, indexes, execution engine, storage, recovery, and migrations; and
- all existing Rust application and service products.
The only Motoko code Canic might maintain would be a small interoperability layer:
- bounded Candid wire types;
- managed lifecycle helpers;
- a root-capability client;
- explicit actor-scaffold support; and
- conformance fixtures and examples.
That SDK would be a protocol adapter, not a Motoko implementation of Canic.
Why It Appears Feasible
Much of Canic is already language-neutral.
The Wasm Store, release sets, module hashes, installation machinery, Component Registry, Directories, snapshots, backup, and restore operate on Wasm bytes, hashes, principals, and Candid—not Rust source.
The Rust-specific boundaries are primarily:
- Cargo-based role declarations and qualification;
- Cargo build execution;
- Rust build-time identity injection;
- the current Rust-owned initialization payload;
- macro-generated lifecycle endpoints; and
- Rust client bindings for root capabilities.
Those boundaries could potentially be replaced with:
- one compact, language-neutral managed-guest ABI;
- a qualified and pinned Mops builder;
- an explicit Motoko actor scaffold; and
- shared Rust/Motoko conformance tests.
One Important Wire Rule
Motoko’s documentation correctly warns that different valid Candid byte encodings can represent the same value.
A guest must therefore not decode a value, call to_candid, and hash the result as deployment evidence.
Instead:
- the root encodes and freezes an authority payload once;
- the root hashes those exact bytes;
- the guest validates the supplied bytes and digest;
- the guest stores the original bytes unchanged; and
- the guest may decode them for use, but must never re-encode them to establish identity.
This gives Rust and Motoko one exact evidence boundary without requiring both languages to produce byte-identical Candid encodings independently.
Mops Build Requirements
We do not want an arbitrary external build command or shell hook.
A qualified Mops build would need to bind and preserve:
- an exact Mops CLI version;
- an exact
mocversion; mops.tomlandmops.lock;- contained source and dependency paths;
- the selected canister;
- the generated Canic build identity;
- emitted Wasm, DID, and MOST files;
- source-tree non-mutation; and
- reproducible artifact hashes.
Builds should run in isolated staging and output directories. Canic should remain the sole owner of any post-build Wasm transformations.
The IcyDB Path
We do not propose porting IcyDB to Motoko.
Instead, a Motoko application could request a schema-specific Rust IcyDB child from its Fleet Subnet Root and call an application-facing Candid API.
The Motoko parent would not control the database canister. Canic would retain controller and deployment authority, while the IcyDB service would authorize its exact registered parent for application operations.
The first service style would probably be typed and schema-specific:
Motoko application
|
| ensure admitted database child exists
v
Fleet Subnet Root
|
| installs and activates
v
Rust IcyDB service
|
| typed, bounded, parent-authorized Candid API
v
Application data
Cross-canister writes are not same-process transactions, so mutations would require durable operation IDs and exact retry receipts.
First Step: A Feasibility Proof
Before changing any production API, we want to run a bounded investigation that proves:
- one candidate managed-guest Candid contract;
- identical golden decoding and hashing in Rust and Motoko;
- a real persistent Motoko actor with explicit managed endpoints;
- an isolated, pinned, source-non-mutating Mops build;
- lifecycle preparation, synchronization, activation, and status;
- exact retry and conflicting-operation rejection;
- recovery after response loss and restart;
- same-contract upgrade behaviour; and
- a clear distinction between Canic activation and application readiness.
No public SDK, configuration change, or managed-Motoko support claim would be made until that proof succeeds.
Questions for Motoko and Mops Developers
We would especially appreciate feedback on the following:
- Would you use managed Motoko Components inside a Rust-operated Canic Fleet?
- Would you prefer a checked-in generated actor scaffold or a small, explicit set of lifecycle forwarding methods?
- What is the cleanest current Mops mechanism for injecting a generated package during a build without modifying
mops.tomlormops.lock? - Which Mops and Motoko toolchain assumptions tend to cause reproducibility problems in CI?
- Would a generated typed Motoko client for a schema-specific Rust IcyDB service be useful?
- Would you need a reduced, parent-only SQL API, or would typed CRUD and query methods be preferable?
- What upgrade and stable-state behaviour would you expect from a managed Motoko guest?
- Are there important Motoko lifecycle or persistence constraints that this architecture overlooks?
This is currently an architectural exploration, not a shipping announcement.
The goal of the first phase is to discover any hard blockers before committing Canic’s production ABI or publishing an SDK.