Skip to content

feat(registry): Allow blanking a Cloud Engine's replica_version_id. - #11172

Open
pietrodimarco-dfinity wants to merge 1 commit into
masterfrom
pdm/registry-blank-engine-replica-version
Open

feat(registry): Allow blanking a Cloud Engine's replica_version_id.#11172
pietrodimarco-dfinity wants to merge 1 commit into
masterfrom
pdm/registry-blank-engine-replica-version

Conversation

@pietrodimarco-dfinity

Copy link
Copy Markdown
Contributor

Motivation

A blank SubnetRecord.replica_version_id is the normal, documented state for a Cloud Engine: when blank, the engine's replica version comes from StandardEngineReplicaVersionRecord instead of being pinned (see the field docs in subnet.proto). create_subnet creates engines that way.

But an engine that does pin a version could not be put back on the standard version. deploy_guestos_to_all_subnet_nodes is the only endpoint that writes replica_version_id, and it required that version to be elected — a blank version never is, so the call traps with Replica version '' is NOT elected. That applies to every caller, Governance included, so there was no route at all (and update_subnet deliberately does not carry replica_version_id).

Changes

Make the elected check conditional:

if payload.replica_version_id.is_empty() {
    self.check_blank_replica_version_id_is_allowed(subnet_id);
} else {
    check_replica_version_is_elected(self, &payload.replica_version_id);
}

check_blank_replica_version_id_is_allowed asserts the same three conditions under which the SubnetRecord invariant tolerates a blank id (invariants::replica_version), so the mutation cannot produce state the invariant would then reject:

  1. IS_BLANK_REPLICA_VERSION_ID_FOR_CLOUD_ENGINES_ENABLED is on,
  2. the subnet is a CloudEngine,
  3. a StandardEngineReplicaVersionRecord exists to determine the version from.

Non-blank versions still have to be elected. The rule is caller-agnostic — Governance and the engine controller canister get the same treatment, and the existing engine-controller-only CloudEngine guard is untouched.

Incidental: get_standard_engine_replica_version_record becomes pub(crate) (it was private to its own module).

Tests

Six unit tests: the engine controller and Governance can each blank a Cloud Engine; it panics when the feature is disabled, when there is no StandardEngineReplicaVersionRecord, and for a non-CloudEngine subnet; plus a non-blank unelected version still panics, so the new branch cannot silently weaken the existing check.

Verification beyond rustfmt is left to CI.

🤖 Generated with Claude Code

`deploy_guestos_to_all_subnet_nodes` is the only endpoint that writes
`SubnetRecord.replica_version_id`, and it required that version to be
elected. A blank version never is, so a Cloud Engine that pins a version
could not be put back on the standard engine version -- even though a blank
`replica_version_id` is allowed (and typical) for Cloud Engines, and
`create_subnet` creates them that way.

Make the elected check conditional. A blank version is validated against the
same conditions under which the SubnetRecord invariant tolerates it: the
feature is enabled, the subnet is a CloudEngine, and Registry has a
StandardEngineReplicaVersionRecord to determine the replica version from.
Non-blank versions still have to be elected.

The rule is caller-agnostic -- Governance and the engine controller canister
get the same treatment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pietrodimarco-dfinity
pietrodimarco-dfinity requested a review from a team as a code owner August 17, 2026 17:40

@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 Aug 17, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 5f13942.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/registry/canister/src/mutations/do_deploy_guestos_to_all_subnet_nodes.rs
    • Update logic to allow blank replica_version_id for Cloud Engines when enabled, with validation against StandardEngineReplicaVersionRecord; add new helper check_blank_replica_version_id_is_allowed and related assertions.
Bug Fix ► rs/registry/canister/src/mutations/do_update_standard_engine_replica_version.rs
    • Make get_standard_engine_replica_version_record public(crate) to be accessible within module.
Documentation/Changelog Update ► rs/registry/canister/unreleased_changelog.md
    • Document that deploy_guestos_to_all_subnet_nodes now accepts a blank replica_version_id for Cloud Engines when a StandardEngineReplicaVersionRecord exists.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant