Skip to content

Commit bc436e7

Browse files
mraszykclaude
andauthored
docs: add status_visibility canister setting to canister_status docs (#315)
Reflect the new status_visibility canister setting (dfinity/ic#10667), which governs who can read a canister's status via canister_status: controllers (default), public, or allowed_viewers. Mirrors the existing log_visibility and snapshot_visibility settings. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0ad1f39 commit bc436e7

5 files changed

Lines changed: 91 additions & 7 deletions

File tree

docs/references/ic-interface-spec/abstract-behavior.md

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ CanisterSnapshotVisibility
462462
= Controllers
463463
| Public
464464
| AllowedViewers [Principal]
465+
CanisterStatusVisibility
466+
= Controllers
467+
| Public
468+
| AllowedViewers [Principal]
465469
CanisterLog = {
466470
idx : Nat;
467471
timestamp_nanos : Nat;
@@ -518,6 +522,7 @@ S = {
518522
canister_history: CanisterId ↦ CanisterHistory;
519523
canister_log_visibility: CanisterId ↦ CanisterLogVisibility;
520524
canister_snapshot_visibility: CanisterId ↦ CanisterSnapshotVisibility;
525+
canister_status_visibility: CanisterId ↦ CanisterStatusVisibility;
521526
canister_logs: CanisterId ↦ [CanisterLog];
522527
query_stats: CanisterId ↦ [QueryStats];
523528
system_time : Timestamp
@@ -628,6 +633,7 @@ The initial state of the IC is
628633
canister_history = ();
629634
canister_log_visibility = ();
630635
canister_snapshot_visibility = ();
636+
canister_status_visibility = ();
631637
canister_logs = ();
632638
query_stats = ();
633639
system_time = T;
@@ -801,7 +807,19 @@ liquid_balance(S, E.content.canister_id) ≥ 0
801807
E.content.arg = candid({canister_id = CanisterId, …})
802808
E.content.sender ∈ S.controllers[CanisterId] ∪ S.subnet_admins[S.canister_subnet[CanisterId]]
803809
E.content.method_name ∈
804-
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_status", "canister_metrics" }
810+
{ "start_canister", "stop_canister", "uninstall_code", "delete_canister", "canister_metrics" }
811+
) ∨ (
812+
E.content.canister_id = ic_principal
813+
E.content.arg = candid({canister_id = CanisterId, …})
814+
(E.content.sender ∈ S.subnet_admins[S.canister_subnet[CanisterId]])
815+
or
816+
(S.canister_status_visibility[CanisterId] = Public)
817+
or
818+
(S.canister_status_visibility[CanisterId] = Controllers and E.content.sender ∈ S.controllers[CanisterId])
819+
or
820+
(S.canister_status_visibility[CanisterId] = AllowedViewers Principals and (E.content.sender ∈ S.controllers[CanisterId] or E.content.sender ∈ Principals))
821+
E.content.method_name ∈
822+
{ "canister_status" }
805823
) ∨ (
806824
E.content.canister_id = ic_principal
807825
E.content.sender ∈ S.subnet_admins[S.canister_subnet[ECID]]
@@ -1745,6 +1763,11 @@ if A.settings.snapshot_visibility is not null:
17451763
New_canister_snapshot_visibility = A.settings.snapshot_visibility
17461764
else:
17471765
New_canister_snapshot_visibility = Controllers
1766+
1767+
if A.settings.status_visibility is not null:
1768+
New_canister_status_visibility = A.settings.status_visibility
1769+
else:
1770+
New_canister_status_visibility = Controllers
17481771
```
17491772

17501773
State after
@@ -1774,6 +1797,7 @@ S' = S with
17741797
canister_history[Canister_id] = New_canister_history
17751798
canister_log_visibility[Canister_id] = New_canister_log_visibility
17761799
canister_snapshot_visibility[Canister_id] = New_canister_snapshot_visibility
1800+
canister_status_visibility[Canister_id] = New_canister_status_visibility
17771801
canister_logs[Canister_id] = []
17781802
messages = Older_messages · Younger_messages ·
17791803
ResponseMessage {
@@ -1916,6 +1940,8 @@ S' = S with
19161940
canister_log_visibility[A.canister_id] = A.settings.log_visibility
19171941
if A.settings.snapshot_visibility is not null:
19181942
canister_snapshot_visibility[A.canister_id] = A.settings.snapshot_visibility
1943+
if A.settings.status_visibility is not null:
1944+
canister_status_visibility[A.canister_id] = A.settings.status_visibility
19191945
messages = Older_messages · Younger_messages ·
19201946
ResponseMessage {
19211947
origin = M.origin
@@ -1927,7 +1953,8 @@ S' = S with
19271953

19281954
#### IC Management Canister: Canister status
19291955

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

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

@@ -1991,7 +2018,13 @@ S.messages = Older_messages · CallMessage M · Younger_messages
19912018
M.callee = ic_principal
19922019
M.method_name = 'canister_status'
19932020
M.arg = candid(A)
1994-
M.caller ∈ S.controllers[A.canister_id] ∪ {A.canister_id} ∪ S.subnet_admins[S.canister_subnet[A.canister_id]]
2021+
(M.caller ∈ {A.canister_id} ∪ S.subnet_admins[S.canister_subnet[A.canister_id]])
2022+
or
2023+
(S.canister_status_visibility[A.canister_id] = Public)
2024+
or
2025+
(S.canister_status_visibility[A.canister_id] = Controllers and M.caller ∈ S.controllers[A.canister_id])
2026+
or
2027+
(S.canister_status_visibility[A.canister_id] = AllowedViewers Principals and (M.caller ∈ S.controllers[A.canister_id] or M.caller ∈ Principals))
19952028
19962029
```
19972030
@@ -2033,7 +2066,13 @@ is_effective_canister_id(E.content, ECID)
20332066
S.system_time <= Q.ingress_expiry or Q.sender = anonymous_id
20342067
Q.arg = candid(A)
20352068
A.canister_id ∈ verify_envelope(E, Q.sender, S.system_time)
2036-
Q.sender ∈ S.controllers[A.canister_id] ∪ S.subnet_admins[S.canister_subnet[A.canister_id]]
2069+
(Q.sender ∈ S.subnet_admins[S.canister_subnet[A.canister_id]])
2070+
or
2071+
(S.canister_status_visibility[A.canister_id] = Public)
2072+
or
2073+
(S.canister_status_visibility[A.canister_id] = Controllers and Q.sender ∈ S.controllers[A.canister_id])
2074+
or
2075+
(S.canister_status_visibility[A.canister_id] = AllowedViewers Principals and (Q.sender ∈ S.controllers[A.canister_id] or Q.sender ∈ Principals))
20372076
20382077
```
20392078
@@ -2942,6 +2981,7 @@ S with
29422981
canister_history[A.canister_id] = (deleted)
29432982
canister_log_visibility[A.canister_id] = (deleted)
29442983
canister_snapshot_visibility[A.canister_id] = (deleted)
2984+
canister_status_visibility[A.canister_id] = (deleted)
29452985
canister_logs[A.canister_id] = (deleted)
29462986
query_stats[A.canister_id] = (deleted)
29472987
chunk_store[A.canister_id] = (deleted)
@@ -3182,6 +3222,11 @@ if A.settings.snapshot_visibility is not null:
31823222
New_canister_snapshot_visibility = A.settings.snapshot_visibility
31833223
else:
31843224
New_canister_snapshot_visibility = Controllers
3225+
3226+
if A.settings.status_visibility is not null:
3227+
New_canister_status_visibility = A.settings.status_visibility
3228+
else:
3229+
New_canister_status_visibility = Controllers
31853230
```
31863231

31873232
State after
@@ -3209,6 +3254,7 @@ S' = S with
32093254
canister_history[Canister_id] = New_canister_history
32103255
canister_log_visibility[Canister_id] = New_canister_log_visibility
32113256
canister_snapshot_visibility[Canister_id] = New_canister_snapshot_visibility
3257+
canister_status_visibility[Canister_id] = New_canister_status_visibility
32123258
canister_logs[Canister_id] = []
32133259
query_stats[CanisterId] = []
32143260
messages = Older_messages · Younger_messages ·
@@ -4191,6 +4237,8 @@ S with
41914237
canister_log_visibility[Canister_id] = (deleted)
41924238
canister_snapshot_visibility[New_canister_id] = S.canister_snapshot_visibility[Canister_id]
41934239
canister_snapshot_visibility[Canister_id] = (deleted)
4240+
canister_status_visibility[New_canister_id] = S.canister_status_visibility[Canister_id]
4241+
canister_status_visibility[Canister_id] = (deleted)
41944242
canister_logs[New_canister_id] = S.canister_logs[Canister_id]
41954243
canister_logs[Canister_id] = (deleted)
41964244
query_stats[New_canister_id] = S.query_stats[Canister_id]

docs/references/ic-interface-spec/changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ sidebar:
88

99
## Changelog {#changelog}
1010

11+
### 0.65.0 (2026-08-03) {$0_65_0}
12+
* New canister setting `status_visibility` controlling who can read a canister's status via the
13+
`canister_status` endpoint: `controllers` (default) restricts access to the canister's controllers,
14+
`public` allows anyone, and `allowed_viewers` grants access to a list of up to 10 principals in addition
15+
to the controllers. The canister itself and subnet admins can always read the status.
16+
1117
### 0.64.0 (2026-07-06) {$0_64_0}
1218
* New optional `permissions` field in request delegations restricting the kinds of requests
1319
the delegation applies for: the value `"queries"` restricts the delegation to query calls

docs/references/ic-interface-spec/management-canister.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ The optional `settings` parameter can be used to set the following settings:
119119

120120
Default value: `controllers`.
121121

122+
- `status_visibility` (`status_visibility`)
123+
124+
Controls who can access the canister's status through the `canister_status` endpoint of the management canister. Can be one of:
125+
- `controllers`: Only the canister's controllers can read its status
126+
- `public`: Anyone can read the canister's status
127+
- `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
128+
129+
Regardless of this setting, subnet admins and the canister itself can always read the canister's status.
130+
131+
Default value: `controllers`.
132+
122133
- `wasm_memory_threshold` (`nat`)
123134

124135
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:
@@ -264,6 +275,8 @@ Indicates various information about the canister. It contains:
264275

265276
- The visibility of the canister's snapshots.
266277

278+
- The visibility of the canister's status.
279+
267280
- The WASM heap memory limit of the canister in bytes (the value of `0` means that there is no explicit limit).
268281

269282
- 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.
@@ -292,7 +305,13 @@ Indicates various information about the canister. It contains:
292305

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

295-
Only the controllers of the canister or the canister itself or subnet admins can request its status.
308+
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:
309+
310+
- `controllers`: only the canister's controllers can request the status (default);
311+
- `public`: everyone can request the status;
312+
- `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.
313+
314+
Regardless of this setting, the canister itself and subnet admins can always request the canister's status.
296315

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

docs/references/management-canister.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Several methods accept or return a `canister_settings` record. The fields are:
2828
| `wasm_memory_threshold` | `nat` | `0` | Remaining Wasm memory threshold that triggers the low-memory hook |
2929
| `log_visibility` | `log_visibility` | `controllers` | Who can read canister logs: `controllers`, `public`, or `allowed_viewers(vec principal)` |
3030
| `snapshot_visibility` | `snapshot_visibility` | `controllers` | Who can list and read canister snapshots: `controllers`, `public`, or `allowed_viewers(vec principal)` |
31+
| `status_visibility` | `status_visibility` | `controllers` | Who can read the canister status: `controllers`, `public`, or `allowed_viewers(vec principal)` |
3132
| `environment_variables` | `opt record` | `null` | Key-value pairs accessible during canister execution |
3233

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

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

121-
- **Caller:** Controllers, the canister itself, or subnet admins (canisters or external users; also available as a query call)
122+
- **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)
122123
- **Parameters:**
123124
- `canister_id` (`principal`)
124125
- **Returns:** A record containing:
@@ -134,6 +135,8 @@ Returns detailed information about a canister: status, settings, module hash, cy
134135
- `idle_cycles_burned_per_day` (`nat`): daily idle burn rate
135136
- `query_stats`: query call statistics (total calls, instructions, request/response bytes)
136137

138+
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.
139+
137140
### `canister_metrics`
138141

139142
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).

public/references/ic.did

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ type snapshot_visibility = variant {
1414
allowed_viewers : vec principal;
1515
};
1616

17-
type environment_variable = record {
17+
type status_visibility = variant {
18+
controllers;
19+
public;
20+
allowed_viewers : vec principal;
21+
};
22+
23+
type environment_variable = record {
1824
name: text;
1925
value: text;
2026
};
@@ -28,6 +34,7 @@ type canister_settings = record {
2834
minimum_incoming_canister_call_cycles : opt nat;
2935
log_visibility : opt log_visibility;
3036
snapshot_visibility : opt snapshot_visibility;
37+
status_visibility : opt status_visibility;
3138
wasm_memory_limit : opt nat;
3239
wasm_memory_threshold : opt nat;
3340
environment_variables : opt vec environment_variable;
@@ -42,6 +49,7 @@ type definite_canister_settings = record {
4249
minimum_incoming_canister_call_cycles : nat;
4350
log_visibility : log_visibility;
4451
snapshot_visibility : snapshot_visibility;
52+
status_visibility : status_visibility;
4553
wasm_memory_limit : nat;
4654
wasm_memory_threshold : nat;
4755
environment_variables : vec environment_variable;

0 commit comments

Comments
 (0)