A type id keys one Directory row and one organisation registry row, and migrating repoints only the organisation's row in place without adding a second.
A component keeps one fixed type id across every version. A new implementation repoints the existing registry row instead of registering a second, competing entry.
The platform compares each component against the current module set and reports one of three statuses. The Console's System updates page shows them as Up to date, Upgrade available and Not installed, with two more states for components it cannot upgrade or could not read.
Comparing and starting a migration both take the admin or system manager role, and a migration runs as a signed background workflow. Validate the upgrade against representative chain state before production.
Staying current is a repoint, not a rebuild
A system version tells you whether the contracts an organisation deployed match the platform's current module set. When System updates in the Console shows Upgrade available, an authorised operator starts a migration, which repoints the outdated component to its current implementation without changing its address. The expectation it compares against lives in the Directory, the platform's own on-chain catalogue, one per network. The module set is the bundle of implementation addresses the Directory holds as current across every component type. A chain's implementations are locked in at deployment. The Directory's addresses keep advancing with fixes, new capabilities, and, over time, compliance features that graduate from optional to standard. A chain that never migrates keeps the exact behaviour it deployed with, including any defect fixed since, and misses later capabilities without anyone deciding to skip them. Security fixes in contract logic reach the chain only when the organisation starts a migration.
A component's identity in the registry does not change across versions, so staying current repoints the same, already-integrated component at newer logic. The organisation does not redeploy its system, and counterparties keep trusting the same contract address.
Starting a migration takes explicit authority, and a second request joins the run already underway
The Console's System updates page is where an operator reads and starts a migration. It lists every component in one table with the columns Component, State, Tokens affected and Area, where Area is the group the component belongs to, such as token factories, add-ons or compliance modules. A replacement of a global compliance module needs the compliance manager role on the signing wallet, and the run leaves it out without that role. System updates describes the page.
The migration submits transactions from the organisation's own signing wallet, so starting one needs three things before anything on-chain is signed. The wallet holds the role a comparison needs on the system contract, it holds a management key on the organisation identity, and you pass a wallet verification step, such as a PIN code. Without the key, the start is refused. If a migration is already running for the organisation, meaning it is running, waiting on a step, or suspended, a second start request joins the run already in progress rather than starting a competing one. The Console shows the same live progress either way. The migration proceeds as a background workflow, so an operator can navigate away and come back to see it still running, waiting on a step, or finished.
A version bump repoints one registry row and never creates a second
Each organisation holds its own addon registry, a contract on its own chain that the migration repoints. The Directory is a separate, platform-owned catalogue on the same chain. The organisation's registry repoints itself to match what the Directory expects. It never changes the Directory. Every component the Directory tracks is addressed by a stable type id: for example, the settlement addon's id is the fixed hash of the string “xvp-settlement”. Every implementation of that same addon declares that identical id, because the id names the slot in the registry, not a specific version of the logic behind it. Installing a component in an organisation's registry for the first time calls a function named registerSystemAddon, which reverts if the organisation already has that type id registered and active. Calling it for an archived type id unarchives the entry. Shipping a new version instead calls setAddonImplementation, which requires the organisation to already have that id registered and overwrites the implementation address stored at that row.
A new version of a component is the same registry entry pointed at a new implementation. Addon proxies resolve their logic through the row on every call, so they move when the row changes. For a factory-style addon, the instance implementation the factory deploys is a separate setting that the migration syncs in its own step, as the factory comparison describes. On chain, the registry accepts that change from any wallet that holds the System manager role, in one call with no second signer and no delay. Control who holds that role, and require custody approval on its wallet, if a repoint needs more than one person.
Comparing an organisation's registry against the Directory's module set compares addresses only. For each component, the platform reads the address the organisation's registry has and compares it to the address the Directory expects. A component's status follows directly from that comparison, as this table shows.
Factory-style addons carry a second, independent comparison. The factory contract's own registry row can be current while the instance implementation it deploys, the logic that already-created instances run, still lags behind, since the two can be updated separately. Only the type id ties them together as one addon.
The Console shows two more states. Needs compliance manager marks a global compliance module replacement that the signing wallet lacks the role for. Not verified marks a component whose tokens' version the platform could not read.
A status check reports what to repoint, never what changed
A migration comparison call returns components grouped the same way the Console displays them, each carrying a status of up-to-date, update-available or new. A component's status alone tells you whether a repoint is available. It does not tell you what changed in the new implementation, since the comparison is address-level, not a semantic diff of behaviour. Reading the implementation change is a source-level exercise against the module set's release notes or diff, not something the compare endpoint answers.
Starting the migration itself is not a single transaction. It runs as a durable background workflow keyed to the organisation, so a client that starts a migration and loses its connection can reconnect and resume watching the same run rather than losing state or accidentally starting a second one. Only the running, waiting and suspended states count as an existing run that a second start request can join.
A run moves between running, waiting and suspended until it completes or fails. A retry after a failure starts a new run and never resumes the one that failed.
The workflow signs its on-chain calls with the organisation's own submission signer, resolved per network and system, according to the configured custody path. A signer that cannot be resolved degrades specific steps, such as feed backfill, instead of failing the whole run.
Three further details shape what a migration touches. First, an organisation can opt in to migrating components the Directory marks experimental. Left at its default, the migration skips them and they stay visible as pending rather than being repointed silently. Second, a small set of components sync without ever appearing as a row in the comparison or in the Console: they still repoint, but a reader watching only the visible list does not see them move. Third, when a factory-style addon does not support the interface a factory-instance update needs, the migration skips that one factory's instance update and the run continues. The workflow's own log records the skip, and the Console does not show it.
Authorise and validate an upgrade before production
The selected signing path applies its verification and approval requirements. An authenticated API caller can also start the workflow when authorised.
Validate the selected module set against the deployment's current state before a production upgrade. A local chain fork can expose assumptions that a fresh test deployment would miss. The migration API checks authorisation and starts the workflow. It does not run or verify a deployment-specific fork test for you.
- Review the release and the current deployment.
- Validate the upgrade against representative state, for example on a local fork of the chain.
- An authorised operator starts the migration.
- The signing policy authorises each transaction.
- Review the workflow outcome and the component changes.
Validation is an operational step before the authorised migration request. Retain its results with the change approval.
On-chain implementation-change events record which components changed. Combine them with the workflow outcome, initiating actor, and your change-approval evidence. The chain and workflow journal do not replace that approval record.
Frequently asked questions
Does migrating change a component's address that other systems integrate against?
No. A migration overwrites the implementation address stored at the registry row. The row's own address, and the address of anything already deployed through it, stays exactly where it was. A counterparty or integration that already has that address saved keeps the same address. Review behaviour and interface compatibility before upgrading. A stable address does not guarantee unchanged behaviour.
Can a chain skip a version and jump straight to the latest?
Yes. The comparison and repoint mechanism does not require passing through every intermediate version: an organisation's registry compares its current address directly against what the Directory expects and repoints once. What a specific module set's implementation is allowed to assume about the prior version it replaces is a source-level concern for that implementation, not a limitation of the repoint mechanism itself.
Do you have to start a migration to see whether a component has an update available?
No. Comparing reads the organisation's current on-chain state and signs nothing, so it commits the organisation to nothing. It still needs the admin or system manager role on the selected wallet, the same role as starting a migration. A caller without it is refused with “System updates need the admin or system manager role.”