Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/icp-cli/src/operations/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ async fn sync_canister(
&Params {
path: canister_path.clone(),
cid: canister_id,
name: canister_info.name.clone(),
environment: environment.to_owned(),
network: network.to_owned(),
canister_ids: canister_ids.clone(),
Expand Down
34 changes: 17 additions & 17 deletions crates/icp-sync-plugin/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ docs; the *reasons* behind those choices are recorded here.
from `sync-exec-input.canister-id`. There is deliberately no field for a
different target, so the single-canister restriction is *structural* rather
than a policy the plugin could bypass.
- **`sync-exec-input` carries the canister ID table** — `canister-ids` exposes
the project's name→principal map for the environment, so a plugin can resolve
canister names it knows about. It is informational only: `canister-call`
still targets the canister being synced, so the table grants no ability to
call other canisters.
- **Filesystem access via WASI, not a host import** — plugins use standard
language APIs (`std::fs`); the host preopens the declared `dirs` read-only. No
bespoke `read-file`/`list-dir` import is needed.
Expand Down Expand Up @@ -62,21 +67,14 @@ crates/icp-sync-plugin/
Public function:

```rust
pub fn run_plugin(
wasm_path: Utf8PathBuf,
base_dir: Utf8PathBuf,
dirs: Vec<String>,
files: Vec<String>,
target_canister_id: Principal,
agent: Agent,
proxy: Option<Principal>,
identity_principal: Principal,
environment: String,
compute_limit_secs: u64,
stdio: Option<Sender<String>>,
) -> Result<Vec<String>, RunPluginError>
pub fn run_plugin(invocation: PluginInvocation) -> Result<Vec<String>, RunPluginError>
```

`PluginInvocation` bundles the inputs: `wasm_path`, `base_dir`, `dirs`, `files`,
`target_canister_id` (the canister being synced), `agent`, `proxy`,
`identity_principal`, `environment`, `compute_limit_secs`, and the exposed
`canister_ids` table, plus `stdio`.

`dirs` and `files` are the manifest-relative path strings, straight from the
adapter. The runtime owns *all* filesystem access anchored at `base_dir`: it
preopens each `dir` from `base_dir.join(dir)` and reads each `file` from
Expand Down Expand Up @@ -188,7 +186,9 @@ pub struct Adapter {
### `crates/icp/src/canister/sync/plugin.rs`

Resolves the wasm (local read or remote HTTP fetch into the package cache),
verifies sha256, then calls `icp_sync_plugin::run_plugin(...)`, forwarding the
manifest's `dirs`/`files` strings unchanged. The runtime — not the CLI — opens
those paths and enforces the path-safety checks, so the CLI no longer touches
the plugin's input files itself.
verifies sha256, builds the exposed canister ID table, then calls
`icp_sync_plugin::run_plugin(...)` with a `PluginInvocation`. The runtime — not
the CLI — opens the declared paths and enforces the path-safety checks, so the
CLI no longer touches the plugin's input files itself. `exposed_canister_ids`
adds a bare-local-name duplicate for every canister in the same subproject as
the one being synced.
3 changes: 2 additions & 1 deletion crates/icp-sync-plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ mod path;
mod runtime;

pub use runtime::{
DEFAULT_PLUGIN_COMPUTE_LIMIT_SECS, PLUGIN_COMPUTE_LIMIT_ENV, RunPluginError, run_plugin,
DEFAULT_PLUGIN_COMPUTE_LIMIT_SECS, PLUGIN_COMPUTE_LIMIT_ENV, PluginInvocation, RunPluginError,
run_plugin,
};
Loading
Loading