feat(network): require explicit root-key for connected networks#645
Open
lwshang wants to merge 1 commit into
Open
feat(network): require explicit root-key for connected networks#645lwshang wants to merge 1 commit into
lwshang wants to merge 1 commit into
Conversation
The root-key for a connected network was optional and silently defaulted to the IC mainnet key. That masked misconfiguration: a connected network pointing somewhere non-mainnet would appear to work until the first real message-verification failure. Make root-key required for connected networks and give it three forms: - `mainnet`: use the canonical IC mainnet root key (e.g. to reach mainnet through a custom boundary node without repeating the literal). - `fetch`: fetch the key from the network on each use. Trust-on-first-use and unverified, so intended only for testnets you or someone you trust operate; a warning is printed on every fetch. - a hex-encoded key, as before. The fetch happens in the network Accessor via an anonymous bootstrap agent, so the key is resolved before identity/delegation verification needs it. `network status` now reports provenance: a `root_key_source` field in --json and a `(fetched - ...)` / `(mainnet)` / `(configured)` label in text. Only the built-in `ic` network keeps the implicit mainnet key. This is technically breaking, but non-mainnet connected networks already needed an explicit key, so in practice only mainnet-via-custom-URL configs must add `root-key: mainnet`. Also fixes the icp-network-inline / icp-network-connected examples, which defined a `staging` network but no matching environment and told users to run `icp deploy --network staging` (deploy takes --environment, not --network); both now define a `staging` environment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes connected-network root key handling explicit and safer by requiring users to choose how the root key is obtained (pinned, canonical mainnet, or fetched trust-on-first-use), and surfaces root-key provenance in network status output. It updates schemas, docs, examples, and adds an end-to-end test for the fetch flow.
Changes:
- Require
root-keyfor all connected networks (except the built-inicnetwork which still uses the implicit mainnet key). - Add
root-key: mainnet | fetch | <hex>support, including runtime fetching via a bootstrap anonymous agent and provenance reporting (root_key_source). - Update examples/docs and add an E2E test covering
root-key: fetchwithout relying on external networks.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| examples/icp-network-inline/README.md | Fixes example usage to deploy via an environment instead of --network. |
| examples/icp-network-inline/icp.yaml | Adds root-key: mainnet and defines a staging environment targeting the staging network. |
| examples/icp-network-connected/README.md | Fixes example usage to deploy via an environment instead of --network. |
| examples/icp-network-connected/networks/staging.yaml | Adds root-key: mainnet to the connected network definition. |
| examples/icp-network-connected/icp.yaml | Adds a staging environment mapping to the staging network. |
| docs/schemas/network-yaml-schema.json | Updates schema: root-key is required and supports mainnet/fetch/hex via RootKeySpec. |
| docs/schemas/icp-yaml-schema.json | Updates schema: root-key is required and supports mainnet/fetch/hex via RootKeySpec. |
| docs/reference/configuration.md | Documents root-key requirement and the three supported forms. |
| docs/reference/cli.md | Updates --root-key option docs to include mainnet/fetch/hex. |
| docs/migration/from-dfx.md | Updates migration guidance to reflect explicit root-key choice and new options. |
| docs/concepts/project-model.md | Updates example connected network configuration to include root-key: mainnet. |
| docs/concepts/environments.md | Updates connected-network examples to include root-key: fetch. |
| crates/icp/src/project.rs | Ensures built-in ic network uses RootKeySpec::Mainnet explicitly. |
| crates/icp/src/network/mod.rs | Switches connected root_key to RootKeySpec and wires bootstrap agent into accessor. |
| crates/icp/src/network/access.rs | Resolves root key bytes for connected networks (mainnet/configured/fetched) and records provenance. |
| crates/icp/src/manifest/network.rs | Makes connected root_key required and introduces RootKeySpec parsing + schema. |
| crates/icp/src/lib.rs | Updates mock project loader/test data to use RootKeySpec::Mainnet and include root-key where required. |
| crates/icp/src/context/tests.rs | Updates tests to populate new root_key_source field in NetworkAccess. |
| crates/icp/src/context/mod.rs | Updates URL network selection to carry RootKeySpec rather than raw bytes. |
| crates/icp/src/context/init.rs | Initializes network accessor with an agent creator for bootstrap root-key fetches. |
| crates/icp-cli/tests/project_tests.rs | Updates test manifest to include required root-key for connected networks. |
| crates/icp-cli/tests/network_tests.rs | Updates test manifest to include required root-key for connected networks. |
| crates/icp-cli/tests/network_status_tests.rs | Adds E2E test validating root-key: fetch warning + provenance + key correctness. |
| crates/icp-cli/src/options.rs | Updates --root-key parsing to accept mainnet/fetch/hex via RootKeySpec. |
| crates/icp-cli/src/commands/network/status.rs | Adds root_key_source to JSON and provenance labeling in text output. |
| CHANGELOG.md | Documents the new required root-key behavior and provenance reporting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
adamspofford-dfinity
approved these changes
Jul 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
root-keyfor a connected network was optional and silently defaulted to the IC mainnet key. That masked misconfiguration: a connected network pointing somewhere non-mainnet would appear to work until the first real message-verification failure.This makes
root-keyrequired for connected networks and gives it three forms:mainnet— use the canonical IC mainnet root key (e.g. to reach mainnet through a custom boundary node without repeating the 266-char literal). Responses are still fully verified against the real mainnet key.fetch— fetch the key from the network on each use. Trust-on-first-use and unverified, so intended only for testnets you (or someone you trust) operate. AWARNis printed on every fetch.Only the built-in
icnetwork keeps the implicit mainnet key.Design notes
fetchordering problem.root-keyis needed to verify delegated (Internet Identity) chains before the agent exists, butfetch_root_key()needs an agent + a round-trip. Resolved by doing the fetch inside the networkAccessorvia an anonymous bootstrap agent, soNetworkAccessalready carries resolved bytes by the time identity verification runs. Context's agent-build flow is unchanged.network statusgains aroot_key_sourcefield in--json(managed/mainnet/configured/fetched) and a plain-ASCII label in text output, e.g.Root Key: 3081… (fetched - unverified, trust-on-first-use). Theroot_keyfield stays a flat hex string (non-breaking for JSON consumers); the warning goes to stderr so--jsonstdout stays clean.Breaking change (staying on v1.x)
Technically breaking — a connected network with no
root-keynow fails to load. But non-mainnet connected networks already needed an explicit key to work, so in practice only a mainnet-via-custom-URL network must addroot-key: mainnet. Small, acceptable radius → no major-version bump. See CHANGELOG.Also in this PR
Fixes the
icp-network-inline/icp-network-connectedexamples, which defined astagingnetwork but no matching environment and told users to runicp deploy --network staging— butdeploytakes--environment, not--network. Both now define astagingenvironment and the READMEs useicp deploy --environment staging.Testing
cargo test,cargo fmt --check,cargo clippy --tests --benches -- -D warningsall green.status_connected_network_fetches_root_key: starts a managed local network in one project, connects to it from a second project withroot-key: fetch, and asserts the fetch warning, thefetchedlabel/root_key_source, and that the fetched key matches the running network's actual root key — no external network required.🤖 Generated with Claude Code