Skip to content

Commit 9268eaf

Browse files
committed
refactor(concepts): move canister control content from principals to canisters
The controller table and upgrade hook sequence belong conceptually with canisters, not principals. principals.md is now focused on identity only (principal classes + caller semantics). canisters.md absorbs the control structure table and detailed upgrade steps from the Canister Control Learn Hub article.
1 parent d8b0cd9 commit 9268eaf

3 files changed

Lines changed: 23 additions & 40 deletions

File tree

docs/concepts/canisters.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,13 @@ Installing uploads a Wasm module to the canister and runs its initialization log
9090

9191
### Upgrade
9292

93-
Upgrading replaces the canister's Wasm module while preserving stable memory. The system runs a pre-upgrade hook (to save heap data to stable memory if needed), swaps the Wasm, then runs a post-upgrade hook (to restore data).
93+
Upgrading replaces the canister's Wasm module while preserving stable memory. The runtime executes three steps atomically:
94+
95+
1. `pre_upgrade` (or `system func preupgrade` in Motoko): save any heap data to stable memory before the code swap.
96+
2. New Wasm module is installed.
97+
3. `post_upgrade` (or `system func postupgrade`): read data back from stable memory into the new heap layout.
98+
99+
If `pre_upgrade` traps, the upgrade is aborted and the canister continues running the old code. If `post_upgrade` traps, the new code is installed but the canister is left in a failed state. If a canister ensures all persistent data is always in stable memory, steps 1 and 3 can be left empty.
94100

95101
### Stop and delete
96102

@@ -102,7 +108,16 @@ For step-by-step CLI commands, see [Canister lifecycle management](../guides/can
102108

103109
Controllers are principals (users or other canisters) that have permission to manage a canister: upgrade its code, change its settings, stop it, or delete it.
104110

105-
If a canister has **no controllers**, it is immutable: no one can change its code or settings. This is a strong guarantee for users who want to verify that a canister's behavior will never change.
111+
The control structure can take several forms:
112+
113+
| Control structure | Who is the controller | Effect |
114+
|---|---|---|
115+
| Centralized | A single developer's principal | Full developer control; standard during development |
116+
| Multi-signature | A multi-signer wallet like [Orbit](https://orbitwallet.io/) | Requires multiple keys to approve any change |
117+
| SNS-governed | An SNS governance canister | Upgrades require a governance proposal voted on by token holders |
118+
| No controller | Empty controller list | Immutable canister; code can never be changed |
119+
120+
If a canister has **no controllers**, it is immutable: no one can change its code or settings. This is a strong trust guarantee for users. Immutability can be verified on the [ICP Dashboard](https://dashboard.internetcomputer.org).
106121

107122
## Canister internals
108123

@@ -127,9 +142,9 @@ This has a practical implication: if a canister modifies state and then makes an
127142
## Next steps
128143

129144
- [Cycles](cycles.md): how canisters pay for computation
130-
- [Principals](principals.md): the identity model and canister controllers
145+
- [Principals](principals.md): the identity model and caller authentication
131146
- [App architecture](app-architecture.md): how canisters fit into application design
132147
- [Canister lifecycle](../guides/canister-management/lifecycle.md): practical guide to managing canisters
133148
- [Network overview](network-overview.md): the infrastructure canisters run on
134149

135-
<!-- Upstream: informed by dfinity/portal docs/building-apps/essentials/canisters.mdx, message-execution.mdx; informed by Learn Hub articles "Canister Smart Contracts", "Computational Model" (migrated, source retired) -->
150+
<!-- Upstream: informed by dfinity/portal docs/building-apps/essentials/canisters.mdx, message-execution.mdx; informed by Learn Hub articles "Canister Smart Contracts", "Computational Model", "Canister Control" (migrated, source retired) -->

docs/concepts/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Understand the ideas behind the Internet Computer before you build on it. These
1212
- **[Network Overview](network-overview.md)**: Subnets, nodes, consensus, and boundary nodes.
1313
- **[Application Architecture](app-architecture.md)**: How ICP applications are structured: canisters, frontends, and inter-canister communication.
1414
- **[Canisters](canisters.md)**: Programs that run WebAssembly, hold state, serve HTTP, and pay for their own compute.
15-
- **[Principals](principals.md)**: The identity model: users, canisters, anonymous calls, and canister control.
15+
- **[Principals](principals.md)**: The identity model: who can call a canister, and how caller identity works.
1616

1717
## Core capabilities
1818

docs/concepts/principals.md

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Principals"
3-
description: "What principals are on ICP: the identity model, principal classes, canister control, and how authentication works"
3+
description: "What principals are on ICP: the five principal classes and how caller identity works in practice"
44
---
55

66
A **principal** is any entity that can authenticate with the Internet Computer and be identified when calling a canister. Principals are the building block of identity and access control on ICP: canisters use them to identify callers, enforce permissions, and determine which entities have control over which resources.
@@ -31,42 +31,10 @@ Unsigned request → 2vxsx-fae (anonymous principal)
3131

3232
This means that from a canister's perspective, all callers are principals. There is no separate "user object" or session token: the principal is the identity.
3333

34-
## Canister control
35-
36-
Canisters are managed by their **controllers**: a list of principals (users, other canisters, or DAOs) that have permission to perform management operations on the canister. Controllers can:
37-
38-
- Upgrade the canister's Wasm module.
39-
- Change canister settings (compute allocation, memory allocation, freezing threshold).
40-
- Start or stop the canister.
41-
- Delete the canister and claim its remaining cycles.
42-
- Add or remove other controllers.
43-
44-
The control structure can take several forms:
45-
46-
| Control structure | Who is the controller | Effect |
47-
|---|---|---|
48-
| Centralized | A single developer's principal | Full developer control; standard for development |
49-
| Multi-signature | A multi-signer wallet like [Orbit](https://orbitwallet.io/) | Requires multiple keys to approve changes |
50-
| DAO-governed | An SNS governance canister | Upgrades require a governance proposal |
51-
| No controller | Empty controller list | Immutable canister; code can never be changed |
52-
53-
When a canister has no controllers, it is **immutable**: no one can modify its code or settings. Users who want to trust that a canister's behavior will never change can verify this on the [ICP Dashboard](https://dashboard.internetcomputer.org).
54-
55-
## Canister upgrades and stable memory
56-
57-
When a controller upgrades a canister, the new Wasm module replaces the old one. By default, Wasm heap memory is cleared on upgrade because the new module may have a different memory layout. However, **stable memory is always preserved** across upgrades: it is explicitly managed by the canister (via system API calls) and designed to survive code changes.
58-
59-
The runtime runs upgrade hooks atomically around the code swap:
60-
1. `pre_upgrade` (or `system func preupgrade` in Motoko): save any heap data to stable memory.
61-
2. New Wasm module is installed.
62-
3. `post_upgrade` (or `system func postupgrade`): read data back from stable memory into the new heap layout.
63-
64-
If the `pre_upgrade` hook traps, the upgrade is aborted and the canister continues running the old code. If `post_upgrade` traps, the new code is installed but the canister is left in a failed state.
65-
6634
## Next steps
6735

68-
- [Canisters](canisters.md): how canisters work, lifecycle, and message types
36+
- [Canisters](canisters.md): how canisters work, controllers, lifecycle, and message types
6937
- [Authentication](../guides/authentication/internet-identity.md): integrating Internet Identity and other authentication providers
7038
- [IC Interface Specification: Principals](../references/ic-interface-spec/index.md#principal): the formal specification
7139

72-
<!-- Upstream: informed by Learn Hub articles "What is a Principal?", "Canister Control" (migrated, source retired) -->
40+
<!-- Upstream: informed by Learn Hub article "What is a Principal?" (migrated, source retired) -->

0 commit comments

Comments
 (0)