Skip to content
Draft
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
56 changes: 52 additions & 4 deletions docs/references/ic-interface-spec/abstract-behavior.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,10 @@ CanisterSnapshotVisibility
= Controllers
| Public
| AllowedViewers [Principal]
CanisterStatusVisibility
= Controllers
| Public
| AllowedViewers [Principal]
CanisterLog = {
idx : Nat;
timestamp_nanos : Nat;
Expand Down Expand Up @@ -518,6 +522,7 @@ S = {
canister_history: CanisterId ↦ CanisterHistory;
canister_log_visibility: CanisterId ↦ CanisterLogVisibility;
canister_snapshot_visibility: CanisterId ↦ CanisterSnapshotVisibility;
canister_status_visibility: CanisterId ↦ CanisterStatusVisibility;
canister_logs: CanisterId ↦ [CanisterLog];
query_stats: CanisterId ↦ [QueryStats];
system_time : Timestamp
Expand Down Expand Up @@ -628,6 +633,7 @@ The initial state of the IC is
canister_history = ();
canister_log_visibility = ();
canister_snapshot_visibility = ();
canister_status_visibility = ();
canister_logs = ();
query_stats = ();
system_time = T;
Expand Down Expand Up @@ -801,7 +807,19 @@ liquid_balance(S, E.content.canister_id) ≥ 0
E.content.arg = candid({canister_id = CanisterId, …})
E.content.sender ∈ S.controllers[CanisterId] ∪ S.subnet_admins[S.canister_subnet[CanisterId]]
E.content.method_name ∈
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_status", "canister_metrics" }
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_metrics" }
) ∨ (
E.content.canister_id = ic_principal
E.content.arg = candid({canister_id = CanisterId, …})
(E.content.sender ∈ S.subnet_admins[S.canister_subnet[CanisterId]])
or
(S.canister_status_visibility[CanisterId] = Public)
or
(S.canister_status_visibility[CanisterId] = Controllers and E.content.sender ∈ S.controllers[CanisterId])
or
(S.canister_status_visibility[CanisterId] = AllowedViewers Principals and (E.content.sender ∈ S.controllers[CanisterId] or E.content.sender ∈ Principals))
E.content.method_name ∈
{ "canister_status" }
) ∨ (
E.content.canister_id = ic_principal
E.content.sender ∈ S.subnet_admins[S.canister_subnet[ECID]]
Expand Down Expand Up @@ -1745,6 +1763,11 @@ if A.settings.snapshot_visibility is not null:
New_canister_snapshot_visibility = A.settings.snapshot_visibility
else:
New_canister_snapshot_visibility = Controllers

if A.settings.status_visibility is not null:
New_canister_status_visibility = A.settings.status_visibility
else:
New_canister_status_visibility = Controllers
```

State after
Expand Down Expand Up @@ -1774,6 +1797,7 @@ S' = S with
canister_history[Canister_id] = New_canister_history
canister_log_visibility[Canister_id] = New_canister_log_visibility
canister_snapshot_visibility[Canister_id] = New_canister_snapshot_visibility
canister_status_visibility[Canister_id] = New_canister_status_visibility
canister_logs[Canister_id] = []
messages = Older_messages · Younger_messages ·
ResponseMessage {
Expand Down Expand Up @@ -1916,6 +1940,8 @@ S' = S with
canister_log_visibility[A.canister_id] = A.settings.log_visibility
if A.settings.snapshot_visibility is not null:
canister_snapshot_visibility[A.canister_id] = A.settings.snapshot_visibility
if A.settings.status_visibility is not null:
canister_status_visibility[A.canister_id] = A.settings.status_visibility
messages = Older_messages · Younger_messages ·
ResponseMessage {
origin = M.origin
Expand All @@ -1927,7 +1953,8 @@ S' = S with

#### IC Management Canister: Canister status

The controllers of a canister can obtain detailed information about the canister.
Detailed information about a canister can be obtained by the callers permitted by the canister's `canister_status_visibility` setting.
The canister itself and subnet admins can always obtain this information, regardless of the setting.

Given a state `S` and `Canister_id`, we define

Expand Down Expand Up @@ -1991,7 +2018,13 @@ S.messages = Older_messages · CallMessage M · Younger_messages
M.callee = ic_principal
M.method_name = 'canister_status'
M.arg = candid(A)
M.caller ∈ S.controllers[A.canister_id] ∪ {A.canister_id} ∪ S.subnet_admins[S.canister_subnet[A.canister_id]]
(M.caller ∈ {A.canister_id} ∪ S.subnet_admins[S.canister_subnet[A.canister_id]])
or
(S.canister_status_visibility[A.canister_id] = Public)
or
(S.canister_status_visibility[A.canister_id] = Controllers and M.caller ∈ S.controllers[A.canister_id])
or
(S.canister_status_visibility[A.canister_id] = AllowedViewers Principals and (M.caller ∈ S.controllers[A.canister_id] or M.caller ∈ Principals))

```

Expand Down Expand Up @@ -2033,7 +2066,13 @@ is_effective_canister_id(E.content, ECID)
S.system_time <= Q.ingress_expiry or Q.sender = anonymous_id
Q.arg = candid(A)
A.canister_id ∈ verify_envelope(E, Q.sender, S.system_time)
Q.sender ∈ S.controllers[A.canister_id] ∪ S.subnet_admins[S.canister_subnet[A.canister_id]]
(Q.sender ∈ S.subnet_admins[S.canister_subnet[A.canister_id]])
or
(S.canister_status_visibility[A.canister_id] = Public)
or
(S.canister_status_visibility[A.canister_id] = Controllers and Q.sender ∈ S.controllers[A.canister_id])
or
(S.canister_status_visibility[A.canister_id] = AllowedViewers Principals and (Q.sender ∈ S.controllers[A.canister_id] or Q.sender ∈ Principals))

```

Expand Down Expand Up @@ -2942,6 +2981,7 @@ S with
canister_history[A.canister_id] = (deleted)
canister_log_visibility[A.canister_id] = (deleted)
canister_snapshot_visibility[A.canister_id] = (deleted)
canister_status_visibility[A.canister_id] = (deleted)
canister_logs[A.canister_id] = (deleted)
query_stats[A.canister_id] = (deleted)
chunk_store[A.canister_id] = (deleted)
Expand Down Expand Up @@ -3182,6 +3222,11 @@ if A.settings.snapshot_visibility is not null:
New_canister_snapshot_visibility = A.settings.snapshot_visibility
else:
New_canister_snapshot_visibility = Controllers

if A.settings.status_visibility is not null:
New_canister_status_visibility = A.settings.status_visibility
else:
New_canister_status_visibility = Controllers
```

State after
Expand Down Expand Up @@ -3209,6 +3254,7 @@ S' = S with
canister_history[Canister_id] = New_canister_history
canister_log_visibility[Canister_id] = New_canister_log_visibility
canister_snapshot_visibility[Canister_id] = New_canister_snapshot_visibility
canister_status_visibility[Canister_id] = New_canister_status_visibility
canister_logs[Canister_id] = []
query_stats[CanisterId] = []
messages = Older_messages · Younger_messages ·
Expand Down Expand Up @@ -4191,6 +4237,8 @@ S with
canister_log_visibility[Canister_id] = (deleted)
canister_snapshot_visibility[New_canister_id] = S.canister_snapshot_visibility[Canister_id]
canister_snapshot_visibility[Canister_id] = (deleted)
canister_status_visibility[New_canister_id] = S.canister_status_visibility[Canister_id]
canister_status_visibility[Canister_id] = (deleted)
canister_logs[New_canister_id] = S.canister_logs[Canister_id]
canister_logs[Canister_id] = (deleted)
query_stats[New_canister_id] = S.query_stats[Canister_id]
Expand Down
7 changes: 7 additions & 0 deletions docs/references/ic-interface-spec/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ sidebar:

## Changelog {#changelog}

<!-- Needs human verification: assign the next spec version and release date when this feature ships (dfinity/ic#10667). -->
### Unreleased
* New canister setting `status_visibility` controlling who can read a canister's status via the
`canister_status` endpoint: `controllers` (default) restricts access to the canister's controllers,
`public` allows anyone, and `allowed_viewers` grants access to a list of up to 10 principals in addition
to the controllers. The canister itself and subnet admins can always read the status.

### 0.64.0 (2026-07-06) {$0_64_0}
* New optional `permissions` field in request delegations restricting the kinds of requests
the delegation applies for: the value `"queries"` restricts the delegation to query calls
Expand Down
21 changes: 20 additions & 1 deletion docs/references/ic-interface-spec/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ The optional `settings` parameter can be used to set the following settings:

Default value: `controllers`.

- `status_visibility` (`status_visibility`)

Controls who can access the canister's status through the `canister_status` endpoint of the management canister. Can be one of:
- `controllers`: Only the canister's controllers can read its status
- `public`: Anyone can read the canister's status
- `allowed_viewers` (`vec principal`): Only principals in the provided list and the canister's controllers can read its status, the maximum length of the list is 10

Regardless of this setting, subnet admins and the canister itself can always read the canister's status.

Default value: `controllers`.

- `wasm_memory_threshold` (`nat`)

Must be a number between 0 and 2<sup>48</sup>, inclusively, and indicates the threshold on the remaining wasm memory size of the canister in bytes:
Expand Down Expand Up @@ -264,6 +275,8 @@ Indicates various information about the canister. It contains:

- The visibility of the canister's snapshots.

- The visibility of the canister's status.

- The WASM heap memory limit of the canister in bytes (the value of `0` means that there is no explicit limit).

- The "low wasm memory" threshold, which is used to determine when the [canister_on_low_wasm_memory](./canister-interface.md#on-low-wasm-memory) function is executed.
Expand Down Expand Up @@ -292,7 +305,13 @@ Indicates various information about the canister. It contains:

* `response_payload_bytes_total`: the total number of query and composite query response payload (reply data or reject message) bytes.

Only the controllers of the canister or the canister itself or subnet admins can request its status.
Who can request a canister's status is governed by the `status_visibility` field of `canister_settings` and can be one of the following variants:

- `controllers`: only the canister's controllers can request the status (default);
- `public`: everyone can request the status;
- `allowed_viewers` (`vec principal`): only principals in the provided list and the canister's controllers can request the status, the maximum length of the list is 10.

Regardless of this setting, the canister itself and subnet admins can always request the canister's status.

#### Memory Metrics {#ic-canister_status-memory_metrics}

Expand Down
5 changes: 4 additions & 1 deletion docs/references/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Several methods accept or return a `canister_settings` record. The fields are:
| `wasm_memory_threshold` | `nat` | `0` | Remaining Wasm memory threshold that triggers the low-memory hook |
| `log_visibility` | `log_visibility` | `controllers` | Who can read canister logs: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `snapshot_visibility` | `snapshot_visibility` | `controllers` | Who can list and read canister snapshots: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `status_visibility` | `status_visibility` | `controllers` | Who can read the canister status: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `environment_variables` | `opt record` | `null` | Key-value pairs accessible during canister execution |

For practical guidance on configuring these, see the [canister settings guide](../guides/canister-management/settings.md).
Expand Down Expand Up @@ -118,7 +119,7 @@ Removes a canister's code and state, making it empty. Outstanding calls are reje

Returns detailed information about a canister: status, settings, module hash, cycle balance, memory usage, and query statistics.

- **Caller:** Controllers, the canister itself, or subnet admins (canisters or external users; also available as a query call)
- **Caller:** Governed by the `status_visibility` setting (see below); the canister itself and subnet admins can always call it (canisters or external users; also available as a query call)
- **Parameters:**
- `canister_id` (`principal`)
- **Returns:** A record containing:
Expand All @@ -134,6 +135,8 @@ Returns detailed information about a canister: status, settings, module hash, cy
- `idle_cycles_burned_per_day` (`nat`): daily idle burn rate
- `query_stats`: query call statistics (total calls, instructions, request/response bytes)

By default, only controllers can read a canister's status. The `status_visibility` setting relaxes this: set it to `public` to let anyone read the status, or `allowed_viewers` to grant access to a specific list of up to 10 principals (in addition to the controllers). The canister itself and subnet admins can always read the status regardless of this setting.

### `canister_metrics`

Returns cycle consumption metrics for a canister broken down by use case. Metrics are monotonically increasing counters accumulating since canister creation (or since the metrics feature was introduced for existing canisters).
Expand Down
10 changes: 9 additions & 1 deletion public/references/ic.did
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ type snapshot_visibility = variant {
allowed_viewers : vec principal;
};

type environment_variable = record {
type status_visibility = variant {
controllers;
public;
allowed_viewers : vec principal;
};

type environment_variable = record {
name: text;
value: text;
};
Expand All @@ -28,6 +34,7 @@ type canister_settings = record {
minimum_incoming_canister_call_cycles : opt nat;
log_visibility : opt log_visibility;
snapshot_visibility : opt snapshot_visibility;
status_visibility : opt status_visibility;
wasm_memory_limit : opt nat;
wasm_memory_threshold : opt nat;
environment_variables : opt vec environment_variable;
Expand All @@ -42,6 +49,7 @@ type definite_canister_settings = record {
minimum_incoming_canister_call_cycles : nat;
log_visibility : log_visibility;
snapshot_visibility : snapshot_visibility;
status_visibility : status_visibility;
wasm_memory_limit : nat;
wasm_memory_threshold : nat;
environment_variables : vec environment_variable;
Expand Down
Loading