Skip to content

feat: new canister setting status_visibility#10667

Open
mraszyk wants to merge 13 commits into
masterfrom
mraszyk/canister-status-visibility
Open

feat: new canister setting status_visibility#10667
mraszyk wants to merge 13 commits into
masterfrom
mraszyk/canister-status-visibility

Conversation

@mraszyk

@mraszyk mraszyk commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What

Introduces a new canister setting, status_visibility, that governs which
principals are allowed to read a canister's status via the canister_status
management endpoint. It mirrors the existing log_visibility and
snapshot_visibility settings:

type status_visibility = variant {
    controllers;
    public;
    allowed_viewers : vec principal;
};
  • controllers (default): only the canister's controllers (and subnet
    admins) can read the status — the pre-existing behavior.
  • public: anyone can read the status.
  • allowed_viewers: the controllers, the subnet admins, and up to 10
    explicitly listed principals can read the status.

How

  • Access control: a new validate_status_visibility helper reuses the
    existing VisibilitySettings::has_access mechanism. It is enforced on both
    the ingress-acceptance path (should_accept_ingress_message) and both
    execution paths (replicated update and non-replicated query) via
    get_canister_status. A canister reading its own status is still exempt.
  • State: status_visibility is added to SystemState, persisted in
    CanisterStateBits (proto tag 69). Checkpoints written before this change
    decode to the default (controllers), so loading old state is
    backward-compatible.
  • New error code: denied canister_status calls now return the dedicated
    CanisterStatusAccessDenied (542) error code, replacing the previous
    CanisterInvalidController / CanisterInvalidControllerOrSubnetAdmin. It maps
    to the same CanisterError reject code as before.

Compatibility notes

  • Default preserves existing behavior: canisters created without specifying
    the setting default to controllers, so access is unchanged.
  • Error-code change: tooling that matched on the exact ErrorCode for a
    denied canister_status (previously CanisterInvalidController /
    CanisterInvalidControllerOrSubnetAdmin) will now see
    CanisterStatusAccessDenied. The reject code is unchanged.

Testing

  • New integration test rs/execution_environment/tests/canister_status.rs
    exercises the full matrix of {status_visibility} x {controller, subnet_admin, allowed_viewer, other} x {update, query} call paths, asserting the
    granted/denied outcome (and that canister_status returns the expected
    status visibility upon success), and, on denial, the returned error code and
    description.
  • The test also asserts the canister_status query success metric increments
    exactly once for an allowed query call and never for a denied query or an
    update call — restoring (and broadening) the coverage from the
    canister_status_via_query_call_* tests removed from execution_test.rs.

@github-actions github-actions Bot added the feat label Jul 6, 2026
mraszyk and others added 6 commits July 6, 2026 14:21
# Conflicts:
#	rs/execution_environment/tests/execution_test.rs
#	rs/protobuf/src/gen/state/state.canister_state_bits.v1.rs
…n_test.rs

Commit 2c0413f ("simplify") deliberately removed the three
canister_status_via_query_call_* tests and the canister_status_count
helper from execution_test.rs, as they are fully covered by the
table-driven test_status_visibility_of_canister_status in
canister_status.rs (which exercises every visibility x sender
combination over both the query and update call paths).

The merge of master (6ab53de) accidentally resurrected these tests
during conflict resolution, reintroducing the stale negative test that
still asserted the pre-status-visibility error code
(CanisterInvalidControllerOrSubnetAdmin instead of the new
CanisterStatusAccessDenied). Re-remove them to restore the intended
state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mraszyk mraszyk force-pushed the mraszyk/canister-status-visibility branch from bef2cc0 to 7849177 Compare July 13, 2026 15:50
mraszyk and others added 2 commits July 15, 2026 07:19
Re-add the query success-metric coverage lost when the
canister_status_via_query_call_* tests were removed from execution_test.rs,
folding it into the status_visibility matrix test: the successful
canister_status query metric must increment exactly once for an allowed
query call and never for a denied query or an update call.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Create the test canister with zero cycles: the subnet uses a free cost
  schedule, so no cycles are needed (removes the INITIAL_CYCLES_BALANCE
  constant that was carried over from the original tests).
- Fix the two `.expect` messages on the success path so each matches the
  layer it unwraps: the outer Result is the access-control gate, the inner
  Result is the reply/reject layer (unreachable via ingress/query).

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new canister setting, status_visibility, to control who can call the management canister’s canister_status endpoint, aligning it with existing visibility patterns (logs/snapshots) while preserving default behavior (controllers). The change propagates through the public management canister types, replicated state persistence (protobuf/checkpoints), access-control enforcement in the execution environment, and test coverage (including a new integration test matrix and updated error-code expectations).

Changes:

  • Introduce StatusVisibility as a first-class setting in management types and canister settings APIs, and persist it in checkpoints/protobuf (tag 69).
  • Enforce status_visibility for canister_status across ingress acceptance and execution paths, returning the new CanisterStatusAccessDenied error code on denial.
  • Add/adjust tests to cover the access matrix and metric behavior; update existing tests for the new error code.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rs/types/management_canister_types/tests/ic.did Extends candid test interface with status_visibility and new settings fields.
rs/types/management_canister_types/src/lib.rs Adds StatusVisibility type + protobuf conversions; wires it into settings/status result types.
rs/state_manager/src/tip.rs Serializes status_visibility into checkpointed canister state bits.
rs/state_manager/src/checkpoint.rs Loads status_visibility from persisted canister state bits.
rs/state_layout/src/state_layout/tests.rs Updates default CanisterStateBits test fixture to include status_visibility.
rs/state_layout/src/state_layout/proto.rs Adds protobuf encode/decode plumbing for status_visibility in CanisterStateBits.
rs/state_layout/src/state_layout.rs Extends CanisterStateBits struct with status_visibility.
rs/rust_canisters/tests/test/canister_management.rs Updates expected error code for denied canister_status.
rs/replicated_state/src/canister_state/system_state.rs Adds status_visibility to SystemState and ensures default/init/checkpoint paths carry it.
rs/replicated_state/src/canister_state.rs Exposes status_visibility() accessor on CanisterState.
rs/replica_tests/tests/canister_lifecycle.rs Updates test construction of CanisterStatusResultV2 to include status_visibility.
rs/protobuf/src/gen/state/state.canister_state_bits.v1.rs Regenerates prost types to include StatusVisibility and tag 69 in CanisterStateBits.
rs/protobuf/def/state/canister_state_bits/v1/canister_state_bits.proto Adds StatusVisibility messages and field 69; bumps Next ID.
rs/pocket_ic_server/src/pocket_ic.rs Sets explicit default status_visibility when creating canisters in PocketIC scenarios.
rs/nervous_system/clients/src/update_settings.rs Adapts client-side update_settings conversion to new field (currently always sending None).
rs/execution_environment/tests/execution_test.rs Removes older canister_status query metric/access tests (replaced by new matrix test).
rs/execution_environment/tests/canister_status.rs Adds new integration test covering {visibility} x {caller} x {update/query} plus metrics assertions.
rs/execution_environment/src/execution/common.rs Introduces validate_status_visibility helper to centralize access checks.
rs/execution_environment/src/execution_environment/tests.rs Updates ingress acceptance tests to expect CanisterStatusAccessDenied.
rs/execution_environment/src/canister_settings.rs Extends settings parsing/builders and visibility abstraction to include StatusVisibility.
rs/execution_environment/src/canister_manager/types.rs Adds CanisterStatusAccessDenied variant + mapping to UserError (error code 542).
rs/execution_environment/src/canister_manager/tests.rs Updates manager tests to assert new error code/message for denied status calls.
rs/execution_environment/src/canister_manager.rs Enforces status_visibility for canister_status (ingress acceptance + execution paths) and returns it in results.
rs/cycles_account_manager/src/cycles_account_manager.rs Bumps max “delayed ingress induction cost” payload size constant for update_settings payload changes.
Comments suppressed due to low confidence (1)

rs/nervous_system/clients/src/update_settings.rs:96

  • CanisterSettings is documented as matching the ic-interface-spec, but the new status_visibility setting is not represented here and is always sent as None in the CanisterSettingsArgs conversion. This means nervous-system clients cannot set status_visibility (even to the defaults like controllers/public), and the local struct is now out of sync with the management canister interface.
        management_canister::CanisterSettingsArgs {
            controllers: controllers.map(management_canister::BoundedControllers::new),
            compute_allocation,
            memory_allocation,
            freezing_threshold,
            reserved_cycles_limit,
            log_visibility: log_visibility.map(management_canister::LogVisibilityV2::from),
            snapshot_visibility: snapshot_visibility
                .map(management_canister::SnapshotVisibility::from),
            status_visibility: None,
            log_memory_limit: None,
            wasm_memory_limit,
            wasm_memory_threshold,
            environment_variables: None,
            minimum_incoming_canister_call_cycles: None,

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

@mraszyk mraszyk marked this pull request as ready for review July 15, 2026 08:21
@mraszyk mraszyk requested review from a team as code owners July 15, 2026 08:21

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This pull request changes code owned by the Governance team. Therefore, make sure that
you have considered the following (for Governance-owned code):

  1. Update unreleased_changelog.md (if there are behavior changes, even if they are
    non-breaking).

  2. Are there BREAKING changes?

  3. Is a data migration needed?

  4. Security review?

How to Satisfy This Automatic Review

  1. Go to the bottom of the pull request page.

  2. Look for where it says this bot is requesting changes.

  3. Click the three dots to the right.

  4. Select "Dismiss review".

  5. In the text entry box, respond to each of the numbered items in the previous
    section, declare one of the following:

  • Done.

  • $REASON_WHY_NO_NEED. E.g. for unreleased_changelog.md, "No
    canister behavior changes.", or for item 2, "Existing APIs
    behave as before.".

Brief Guide to "Externally Visible" Changes

"Externally visible behavior change" is very often due to some NEW canister API.

Changes to EXISTING APIs are more likely to be "breaking".

If these changes are breaking, make sure that clients know how to migrate, how to
maintain their continuity of operations.

If your changes are behind a feature flag, then, do NOT add entrie(s) to
unreleased_changelog.md in this PR! But rather, add entrie(s) later, in the PR
that enables these changes in production.

Reference(s)

For a more comprehensive checklist, see here.

GOVERNANCE_CHECKLIST_REMINDER_DEDUP

@zeropath-ai

zeropath-ai Bot commented Jul 15, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to f092104.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/cycles_account_manager/src/cycles_account_manager.rs
      Increase MAX_DELAYED_INGRESS_COST_PAYLOAD_SIZE from 352 to 366
► rs/execution_environment/src/canister_manager.rs
      Add CanisterStatus handling with status visibility validation
► rs/execution_environment/src/canister_manager.rs
      Integrate status_visibility into status checks and propagation
► rs/execution_environment/src/canister_manager/tests.rs
      Update tests to reflect CanisterStatusAccessDenied instead of previous errors
► rs/execution_environment/src/canister_manager/types.rs
      Add CanisterStatusAccessDenied variant and mapping to UserError
► rs/execution_environment/src/canister_settings.rs
      Add status_visibility field to CanisterSettings and related accessors
► rs/execution_environment/src/execution/common.rs
      Add validate_status_visibility function
► rs/execution_environment/tests/canister_status.rs
      New tests for canister_status visibility scenarios
► rs/execution_environment/tests/execution_test.rs
      Remove legacy canister_status query count helper and related tests
► rs/protobuf/def/state/canister_state_bits/v1/canister_state_bits.proto
      Add StatusVisibility message and status_visibility field
► rs/protobuf/src/gen/state/state.canister_state_bits.v1.rs
      Add generated StatusVisibility-related structures
► rs/replicated_state/src/canister_state.rs
      Expose status_visibility accessor
► rs/replicated_state/src/canister_state/system_state.rs
      Include status_visibility in SystemState construction and propagation
► rs/rust_canisters/tests/test/canister_management.rs
      Adjust expectation to CanisterStatusAccessDenied in error cases
► rs/state_layout/src/state_layout.rs
      Include StatusVisibility in imports
► rs/state_layout/src/state_layout/proto.rs
      Serialize/deserialize status_visibility in CanisterStateBits

@zeropath-ai

zeropath-ai Bot commented Jul 15, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to f092104.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/cycles_account_manager/src/cycles_account_manager.rs
      Increase MAX_DELAYED_INGRESS_COST_PAYLOAD_SIZE from 352 to 366
► rs/execution_environment/src/canister_manager.rs
      Add CanisterStatus handling with status visibility validation
► rs/execution_environment/src/canister_manager.rs
      Integrate status_visibility into status checks and propagation
► rs/execution_environment/src/canister_manager/tests.rs
      Update tests to reflect CanisterStatusAccessDenied instead of previous errors
► rs/execution_environment/src/canister_manager/types.rs
      Add CanisterStatusAccessDenied variant and mapping to UserError
► rs/execution_environment/src/canister_settings.rs
      Add status_visibility field to CanisterSettings and related accessors
► rs/execution_environment/src/execution/common.rs
      Add validate_status_visibility function
► rs/execution_environment/tests/canister_status.rs
      New tests for canister_status visibility scenarios
► rs/execution_environment/tests/execution_test.rs
      Remove legacy canister_status query count helper and related tests
► rs/protobuf/def/state/canister_state_bits/v1/canister_state_bits.proto
      Add StatusVisibility message and status_visibility field
► rs/protobuf/src/gen/state/state.canister_state_bits.v1.rs
      Add generated StatusVisibility-related structures
► rs/replicated_state/src/canister_state.rs
      Expose status_visibility accessor
► rs/replicated_state/src/canister_state/system_state.rs
      Include status_visibility in SystemState construction and propagation
► rs/rust_canisters/tests/test/canister_management.rs
      Adjust expectation to CanisterStatusAccessDenied in error cases
► rs/state_layout/src/state_layout.rs
      Include StatusVisibility in imports
► rs/state_layout/src/state_layout/proto.rs
      Serialize/deserialize status_visibility in CanisterStateBits

@mraszyk mraszyk dismissed github-actions[bot]’s stale review July 15, 2026 08:25

No canister behavior changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants