Skip to content

chore: release 0.49.0 — ic-management-canister-types 0.8.0, query-default reads, list_canisters - #737

Merged
lwshang merged 8 commits into
mainfrom
release-0.49.0
Jul 13, 2026
Merged

lwshang merged 8 commits into
mainfrom
release-0.49.0

Conversation

@lwshang

@lwshang lwshang commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Release 0.49.0. Bumps ic-management-canister-types 0.7.1 → 0.8.0 and builds on the new types/methods, plus a couple of related ic-utils ergonomics. All workspace crates go 0.48.1 → 0.49.0.

ic-utils — management canister

  • ic-management-canister-types 0.8.0. Picks up the snapshot_visibility canister setting and the list_canisters / canister_metrics types.
    • New with_snapshot_visibility setter on CreateCanisterBuilder and UpdateSettingsBuilder.
    • Re-exports SnapshotVisibility, CanisterIdRange, ListCanistersResult, CyclesConsumed, CanisterMetricsArgs, CanisterMetricsResult.
  • canister_metrics() — new ManagementCanister read.
  • list_canisters() — subnet-scoped, query-only management method (subnet-administrators only per the interface spec). Routed to the subnet-scoped query endpoint via Agent::query_signed with EffectiveId::Subnet — reusing the existing agent mechanism rather than adding a QueryBuilder::with_effective_subnet_id, keeping update/query API symmetry.
  • Query-default reads. canister_status and canister_metrics — the only two management reads the replica accepts as both query and update — now return a QueryOrUpdateCall that issues a cheap, non-replicated query by default (.call().await), with .as_update().call().await to opt into a replicated, certified call. Query responses are replica-signed and verified by the agent unless verification is disabled. fetch_canister_logs and list_canisters stay query-only per spec.
  • with_canister_settings(CanisterSettings) on CreateCanisterBuilder and UpdateSettingsBuilder, for callers that already hold a full settings struct (e.g. forwarding one, as icp-cli's create_mgmt does). Currently mutually exclusive with the individual with_* setters (building errors if combined); can be loosened to a merge model later without breaking callers.

Breaking changes

  • Re-exported CanisterSettings / DefiniteCanisterSettings gained a snapshot_visibility field; neither is #[non_exhaustive], so struct-literal construction must add it.
  • canister_status now returns QueryOrUpdateCall (query by default) instead of impl AsyncCall (replicated update). Migrate .call_and_wait().await → .call().await, or .as_update().call().await to keep the old behavior.
  • MgmtMethod gained CanisterMetrics and ListCanisters variants; it is not #[non_exhaustive], so exhaustive matches must add arms.

See CHANGELOG.md for the full list.

Testing / infra

  • Bumped the ref-tests pocket-ic git rev to release-2026-07-09_04-35-base (pocket-ic 13.0.0 → 15.0.0) and the icx crates.io pin to 15.0.0 to keep the major in sync. Re-tuned provisional_create_canister_with_cycles for pocket-ic 15's stricter memory reserved-cycles floor.
  • New (non-ignored) ref-tests for canister_metrics, list_canisters (subnet-admin harness), and with_canister_settings (happy path + mutual-exclusion error). The canister_metrics test exercises both the query and .as_update() paths.
  • Full ref-tests suite green (ic-ref 36, integration 17); workspace clippy --all-targets and fmt --check clean.

🤖 Generated with Claude Code

lwshang and others added 7 commits July 13, 2026 10:33
Bump `ic-management-canister-types` 0.7.1 -> 0.8.0 and adjust ic-utils for
the new types/fields:

- `CanisterSettings`/`DefiniteCanisterSettings` gained a `snapshot_visibility`
  field; add `with_snapshot_visibility` to `CreateCanisterBuilder` and
  `UpdateSettingsBuilder` and thread it through every settings literal.
- Add `ManagementCanister::canister_metrics()` (ingress-callable per the IC
  interface spec) plus the `MgmtMethod::CanisterMetrics` variant.
- Re-export the new types: `SnapshotVisibility`, `CanisterIdRange`,
  `ListCanistersResult`, `CyclesConsumed`, `CanisterMetricsArgs`,
  `CanisterMetricsResult`.

Bump all workspace crates 0.48.1 -> 0.49.0 (the re-exported settings structs
are not `#[non_exhaustive]`, so the new field is a breaking change).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `ManagementCanister::list_canisters`, the subnet-scoped, query-only
management-canister method. Per the IC interface spec it may only be called by
subnet administrators via non-replicated queries, so it is signed and routed to
the subnet-scoped `/api/v3/subnet/<id>/query` endpoint via
`Agent::query_signed(EffectiveId::Subnet(_), _)` — reusing the existing agent
mechanism rather than adding a `QueryBuilder::with_effective_subnet_id`, keeping
update/query API symmetry (there is no `UpdateBuilder::with_effective_subnet_id`
either). Adds the `MgmtMethod::ListCanisters` variant and an `icx` arm that
bails, since it can't be routed by effective canister id.

Bump the ref-tests pocket-ic git rev to release-2026-07-09_04-35-base
(pocket-ic 13.0.0 -> 15.0.0) and the `icx` crates.io pin to 15.0.0 to keep the
major version in sync. Re-tune `provisional_create_canister_with_cycles` for
pocket-ic 15's stricter memory reserved-cycles floor.

Add (non-ignored) ref-tests for `canister_metrics` and `list_canisters`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`ManagementCanister::canister_status` and `canister_metrics` are the only two
management read methods the replica accepts as both a query and an update. They
now return a `QueryOrUpdateCall` builder that issues a cheap, non-replicated
query by default (`.call().await`), with `.as_update().call().await` to opt into
a replicated, certified update call. Query responses are replica-signed and
verified by the agent unless verification is disabled, which addresses the
"single replica" trust caveat for callers that don't need full replication.

`fetch_canister_logs` and `list_canisters` stay query-only (the interface spec
forbids replicated calls), so they don't get the update toggle.

BREAKING: `canister_status` previously returned `impl AsyncCall` and performed a
replicated update. Callers migrate `.call_and_wait().await` to `.call().await`
(query) or `.as_update().call().await` (previous behavior).

The `provisional_create_canister_with_cycles` ref-test uses `.as_update()` for
its cycle-balance reads, which need a certified read at a definite round rather
than a query whose auto-advancing timestamp reflects extra idle burn. The
`canister_metrics` ref-test exercises both call styles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`CreateCanisterBuilder` and `UpdateSettingsBuilder` can now accept a fully built
`CanisterSettings` via `with_canister_settings(...)`, for callers that already
hold one (decoded from config, forwarded from another call, etc.) instead of
decomposing it into individual `with_*` setters. This lets downstream code (e.g.
icp-cli's create_mgmt) route a ready-made settings struct through the builder —
combined with `with_effective_subnet_id`, that replaces a hand-rolled
management-canister update call.

The whole-struct setter is currently mutually exclusive with the individual
settings setters: `build()`/`prepare()` returns an error if both are used. This
keeps the semantics unambiguous; the restriction can be loosened later to a
merge/override model without breaking callers.

Both builders' settings resolution is factored into a `resolve_settings` helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Release prep for 0.49.0, updating workspace versions and extending ic-utils’ management-canister interface to match ic-management-canister-types 0.8.0 (new settings/type fields, new methods, and query-default reads).

Changes:

  • Bump workspace + dependency versions (notably ic-management-canister-types → 0.8.0, pocket-ic pins, and crate versions → 0.49.0).
  • Extend ic-utils management canister support: snapshot_visibility settings, canister_metrics, list_canisters, and QueryOrUpdateCall (query-by-default) for reads.
  • Update ref-tests to cover new functionality and adapt existing tests to the query-default canister_status behavior.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ref-tests/tests/integration.rs Adjust struct literal to include new snapshot_visibility field.
ref-tests/tests/ic-ref.rs Migrate canister_status calls to query-default .call(), add .as_update() where certification is needed, add new tests for metrics/list_canisters/settings API.
icx/src/main.rs Add routing/argument handling for CanisterMetrics; explicitly reject unsupported subnet-scoped ListCanisters.
icx/Cargo.toml Bump crates.io pocket-ic pin to 15.0.0.
ic-utils/src/interfaces/wallet.rs Update wallet create args to include snapshot_visibility.
ic-utils/src/interfaces/management_canister/builders.rs Add snapshot_visibility + whole-struct with_canister_settings, and factor settings construction via resolve_settings.
ic-utils/src/interfaces/management_canister.rs Add re-exports/types, new management methods, and introduce QueryOrUpdateCall + subnet-scoped list_canisters query routing.
ic-utils/src/canister.rs Update canister-status test to use query-default .call().
CHANGELOG.md Add 0.49.0 release notes and breaking-change guidance.
Cargo.toml Bump workspace version to 0.49.0, update dependency pins (including ic-management-canister-types and pocket-ic git rev).
Cargo.lock Lockfile updates for the version bumps (candid, pocket-ic, workspace crates, etc.).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ic-utils/src/interfaces/management_canister/builders.rs Outdated
Comment thread ic-utils/src/interfaces/management_canister/builders.rs Outdated
Comment thread icx/src/main.rs
@lwshang
lwshang marked this pull request as ready for review July 13, 2026 17:38
@lwshang
lwshang requested a review from a team as a code owner July 13, 2026 17:38
@zeropath-ai

zeropath-ai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to 0553f32.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► ic-utils/src/interfaces/management_canister.rs
    Add CanisterMetrics and ListCanisters support; update canister_status to return QueryOrUpdateCall
► ic-utils/src/interfaces/management_canister/builders.rs
    Add snapshot_visibility and with_canister_settings; enforce mutual exclusivity with individual settings
► ic-utils/src/interfaces/management_canister/builders.rs
    Update CreateCanisterBuilder to support snapshot visibility and CanisterSettings; adjust prepare() logic
► ic-utils/src/interfaces/management_canister/builders.rs
    Introduce canister_settings handling and settings merging logic
► ic-utils/src/canister.rs
    Adjust test to use .call() instead of .call_and_wait() for canister_status
► ref-tests/tests/ic-ref.rs
    Update tests to use .call() for canister_status calls
► ic-utils/src/interfaces/wallet.rs
    Initialize snapshot_visibility field in wallet-related canister builders
Bug Fix ► icx/src/main.rs
    Handle MgmtMethod::CanisterMetrics in effective canister ID routing; add ListCanisters handling path

Comment thread ic-utils/src/interfaces/management_canister/builders.rs Outdated
Comment thread ic-utils/src/interfaces/management_canister/builders.rs Outdated
…elper

Address review feedback: the `resolve_settings(&mut self)` helper cleared the
builder's settings via `.take()`, gutting the receiver — an undocumented
footgun, even though `prepare()`/`build()` owned and immediately dropped `self`.

Inline the resolution into `prepare()` (create) and `build()` (update) instead,
so `self` is consumed naturally by value with no `&mut`/`take`. The shared
mutual-exclusivity error message is factored into a small `reject_mixed_settings`
helper to avoid duplicating the string.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lwshang
lwshang requested a review from adamspofford July 13, 2026 17:56
@lwshang
lwshang enabled auto-merge (squash) July 13, 2026 18:02
@lwshang
lwshang merged commit e9e76f7 into main Jul 13, 2026
16 checks passed
@lwshang
lwshang deleted the release-0.49.0 branch July 13, 2026 18:08
lwshang added a commit to dfinity/icp-cli that referenced this pull request Jul 23, 2026
* refactor: adopt ic-utils with_canister_settings in create_mgmt

Bump the agent-rs crates (ic-agent, ic-utils, ic-identity-hsm) to 0.49.1
and ic-management-canister-types to 0.8.0 so create_mgmt can use the new
CreateCanisterBuilder API from dfinity/agent-rs#737.

create_mgmt now builds the call via
ManagementCanister::create_canister().with_canister_settings(...), and
routes to the target subnet with with_effective_subnet_id(subnet) instead
of resolving a canister id from the subnet's ranges. This drops the manual
Encode!/update/Decode! dance and the canister-range lookup; the function
now takes the subnet Principal directly. Validated end-to-end by the
canister_create_cloud_engine integration test.

Also handle the breaking changes the bump introduces:
- CanisterSettings/DefiniteCanisterSettings gained snapshot_visibility;
  add it to the two exhaustive settings literals (left None with a TODO to
  make it configurable like log_visibility in a follow-up PR).
- ic_agent::identity::Delegation gained permissions; add permissions: None
  to the three literal constructions.
- ManagementCanister::canister_status now returns QueryOrUpdateCall; use
  .call() in the canister top-up test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: explain why imported delegations use permissions: None

The wire DelegationChain from the cli-backend canister has no permissions
field and the CLI only ever signs unrestricted delegations, so every
delegation reconstructed here was signed with permissions absent. Because
the field is skip_serializing_if'd out of the signable hash when None,
reproducing it as None yields the exact signed bytes and the chain still
verifies in DelegatedIdentity::new. Documents this to preempt the concern
that None drops a signed field.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants