Skip to main content

Versioning

Packed release integers

App releases use semantic major.minor.patch labels in filenames and UI, but the manifest and Candid wire carry one Nat:

packed = major * 10_000 + minor * 100 + patch

minor and patch are each 0–99.

SemanticPacked
0.1.0100
0.1.1101
0.2.0200
1.0.010000

The supported floor is 0.1.0; lower packed values are rejected.

Where each form appears:

Uses the packed integerUses the semantic label
neutron.json versionPackage filenames
Dependency min_versionInstall and Settings UI
Install inventoriesHuman-facing release notes
Repository manifests

The upgrade policy

Owner-facing browser installs are release upgrades. Replacing an installed app requires a strictly higher packed version. Equal versions and downgrades are rejected before compilation even starts, and the kernel independently rejects a target below the committed version.

This is enforced in two places on purpose — the browser check gives a fast, clear error, and the canister check means a client that skipped it still cannot land a downgrade.

The trusted local whole-set path is different: it performs a destructive reinstall rather than an incremental browser update and may explicitly permit an equal-version redeploy. It still rejects downgrades when preserving an installed set.

An app distributed to users must increment its release version for every update. There is no in-place republish.

Independent version lanes

Several things in a Neutron package are versioned, and they are deliberately not coupled:

LaneFormChanges when
App releasePacked integer, min 100You ship anything
Memory schema versionPositive integer per memory rootThe persistent type changes
Capability API versionPositive integer per capabilityThe capability's contract changes
Manifest formatCurrently 3The manifest contract changes
Lockfile formatCurrently 2The lineage lock contract changes

Note that the manifest is format 3 while the managed-memory lock remains format 2 — that is correct, not a mismatch.

Capability API versions are per capability. The authored Certified Assets declaration and its backend interface are API 2, while the derived certified_read_routes capability-plan entry is API 1. HTTP POST handler routes are also API 1. Publication mounts derive exact-Neutron-host GET/HEAD; portable immutable and mutable blob mounts derive canister-gateway GET.

Version compatibility for dependencies

A consumer declares min_version for each provider it depends on. The compiler accepts a provider at or above that version, provided every requested function is still exposed and still type-compatible.

The obligation this places on a provider is worth stating plainly:

Later provider releases must preserve exported functions compatibly. Breaking a signature means introducing a new function name, not changing the old one.

A provider cannot be uninstalled while a consumer still declares it.

Skipped releases

A package that supports installation over several older schema versions must preserve each supported installed schema identity and carry schemas and migration edges that form exactly one path from that version to the target. Edges may jump schema versions; they do not have to correspond to every skipped app release. A multi-edge path is composed into one migration plan.

See Managed memory.

update_source

An app may name a canonical, non-anonymous, non-management canister principal as its update source. A later package may change or remove it; the kernel displays that transition during review and commits it with the rest of the package.

The field identifies a download location. It is not a trusted publisher, not an attestation, and not a capability grant. See Updates.