> Source: https://nexusatlas.dev/releases/versioning — Nexus Atlas developer documentation (Releases). Converted from the HTML page; the page is canonical.

# Versioning

A version number is a promise about what still works together. For a library the promise is about an API. For Nexus Atlas it is about a fleet: whether two nodes on different versions form one network, whether yesterday's configuration file loads, whether a relay carries the traffic, whether the phone pairs and the console understands the report. The family is versioned on one idea: the numbers people install are kept apart from the numbers machines compare.

## Two kinds of numbers

**Release numbers** are what people install and talk about: `x.y.z`, one per release train, under the rules in the next section. **Contract numbers** are small integers that machines compare. A contract is something two parties must agree on before they can work together, and each one carries its own number that only ever goes up:

| Contract | Who must agree | What it covers |
|----------|----------------|----------------|
| wire | Every node in a fleet | The protocol byte in every packet, the header layouts, the native serial frame. |
| relay | A node and the relay server it attaches to | The relay envelope, the error codes, the directory and federation messages. |
| seal | The two ends of an end-to-end sealed flow | The end-to-end seal format and what it binds. |
| pairing | The node that mints a code and the node that redeems it | The pairing-code format. |
| adapter | The daemon and a radio or modem adapter | The interface through which an adapter reports its device and takes intent. |
| report | A node and the console | The shape of the status reports, events and heartbeats a node sends. |
| api | A node and whatever calls it | The REST API, versioned in its path as /api/v1. |

Every component declares the set of contract numbers it speaks, and two components work together when their sets overlap. The numbers are printed beside the release wherever a version is shown, as **atlasd 3.0.0 · wire 5 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1**, so nobody has to remember which app works with which daemon: the app says "wire 5" and the daemon says "wire 5". The wire number is the one that decides whether two nodes interoperate, which is why a wire change is what makes a new major below, and why a minor or a patch never changes it.

## Release numbers: x.y.z, with the fleet as the unit

Atlas uses three numbers in the familiar shape. What differs is the meaning of "compatible". In a library, compatible means a caller written against the old version still compiles. In Atlas, compatible means a node on the new version and a node on the old one still form one fleet, carry each other's traffic and agree on routes. Each number answers one operator question, and each maps onto one update class of the [fleet push](https://nexusatlas.dev/guides/push-release).

| Number | Changes when | What an operator may assume |
|--------|--------------|-----------------------------|
| x, major | A contract breaks: the wire, the seal, the pairing code, the relay envelope or the adapter interface changes shape. Nodes on different majors do not form a fleet. | Upgrade a deployment as a deployment, with the required update class, so no node is left speaking the old wire. Every removed configuration key is listed with its replacement. |
| y, minor | New capability that leaves every contract intact. A node on x.y forms a fleet with nodes on x.(y-1); a feature the older peer lacks is negotiated off towards that peer. New configuration keys arrive with defaults that reproduce the previous behaviour, and a key marked deprecated keeps working with a warning. | Roll the fleet in stages, with the best-effort class. Two adjacent minors in one fleet is a supported state for the length of the rollout. |
| z, patch | Fixes only. No new key, no contract change, no behaviour beyond the one the fix names. | Replace the binary and restart, in any order, at any time. |

**Additions to the advert.** From wire 5 on, additions to the link-state advert go into its signed extension area and do not bump the wire: every node keeps and verifies an extension entry it does not know, and reads only the ones it does, so a new advert field can ship in a minor. A new top-level field, or a changed meaning for an existing one, still bumps the wire, and with it the major.

> **The one rule to remember:** same **x**, same fleet. Everything else on this page follows from it.

## Release history

Each major so far, with the contract that made it one. The full notes are on [Release notes](https://nexusatlas.dev/releases).

| Release | Contracts | Why this number |
|---------|-----------|-----------------|
| 3.0.0 current | wire 5 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1 | A major, because the wire changed: the signed advert gained an extension area, and with it the first extension, the bearer kinds each node advertises for its links. A wire-4 node cannot verify a wire-5 advert. Every other contract is unchanged. Pushed with the required class, relays first; the hosted relays carry wires 5 and 4. From wire 5 on, a new advert field goes into the extension area and does not bump the wire. |
| 2.0.0 | wire 4 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1 | A major, because the wire changed: link-state adverts carry the prefixes a seam host imports for Interconnect prefix mode, inside the signed body, and a wire-3 node cannot verify a wire-4 advert. Every other contract is unchanged. Pushed with the required class; the hosted relays carry wires 4 and 3, so they serve fleets on either side of the upgrade. |
| 1.0.0 | wire 3 · relay 2 · seal 2 · pairing 3 · adapter 1 · report 2 · api 1 | The first numbered line: every earlier build carries this label. Wire 3 opens both handshake messages with the capability bitset. |

## Four release trains

Things that are tested together and deployed together share one number. Things on their own cadence carry their own number and declare the contracts they speak.

- **The node train.** The daemon, the dashboard it serves, the `atlas-config` tool, the adapters built in the tree, the desktop indicator and the live-CD bundle. One tag, one number, one signed and attested release for every target.

- **The relay train.** The relay server. Same repository and same tag number as the node train, so there is no second number to learn, but deployed on its own cadence. Its rule: a relay carries the current wire and the one before it, so the hosted relays can run ahead of every customer fleet. It forwards sealed envelopes without opening them, which is what makes carrying two wires at once possible.

- **The Android app.** Its own `x.y.z` on the store cadence. The About screen shows the embedded core release and the contracts the app speaks. The app's major follows the core's major, since a wire change forces it; its minor and patch are its own.

- **The cloud.** The control plane, the consoles and the sites. No user-facing version at all: they are deployed continuously and are bound only by contracts. They accept every report schema and API version of every supported node release, and a contract change on that side is announced in the node release notes, never the other way round.

Adapters written by radio and modem vendors carry the vendor's own numbers and declare the adapter contract they implement, the way a driver declares the kernel interface it was built against.

## Configuration across versions

The configuration surface is defined by the daemon's own generated schema, and the [reference](https://nexusatlas.dev/docs/config) regenerates from it, so the two cannot drift. Within a major, a key is only ever added or deprecated: an added key has a default that reproduces the previous behaviour, and a deprecated key keeps working while `atlasd config check` names it and its replacement. A key is removed only at a major, and the release notes of that major list every removed key beside the key that replaces it. A file that passed `config check` on `x.y.z` therefore passes on every later `x.*`, and an upgrade is rehearsed with `config check` before it is run.

## Release lines and support windows

A release line is an `x.y`. Fixes are published on the current line and on the line before it, so a fleet mid-rollout is never asked to take new capability in order to receive a fix. When a new major ships, the last line of the previous major keeps receiving security fixes for twelve months, which is the window a deployed fleet has to plan the one upgrade that must be done as a deployment. The hosted relays and the cloud support every release inside those windows, which also bounds how long an old report schema has to be understood.

## Where the numbers show

- **On the node.** The dashboard's About view and `atlasd --version` print the release, the build it was made from and every contract number. The build rides inside the version string, as `1.4.2+abc1234`, and is reported to the console with every heartbeat.

- **In the console.** The fleet view flags a node whose contracts do not overlap with the rest of the fleet and names the contract, so version skew is a warning before it is an outage.

- **In the documentation.** Every page under [/docs](https://nexusatlas.dev/docs) is cut per release and selectable by number; the *current* entry follows development. The app's and the relay's release notes name the documentation line they were verified against.

## What every release note states

- The release number and every contract number, and which contracts changed.

- The update class the release should be pushed with: *required*, *best-effort* or *left-behind*.

- Configuration keys added, deprecated and removed, each with its default or its replacement.

- The oldest app, relay and console the release has been verified against.

- Accepted dependency advisories, with the reasoning, and the known issues.

## What was considered, and why not

- **Dates, as in 2026.10.** A date says when a build was made and nothing about whether two builds interoperate, which is the only question an operator with a mixed fleet is asking.

- **The wire number alone.** It answers the interoperability question and nothing else: a fix and a new capability would carry the same number.

- **A number per component.** The daemon, the tool, the dashboard and the relay server would each need a line in a compatibility matrix that every operator carries in their head. One shared number per train plus the printed contract numbers carries the same information without the matrix.

- **Semantic versioning as a library uses it.** Adopted in shape, redefined in meaning: the compatibility the numbers promise is between nodes in a fleet, between a node and the services around it, and between a configuration file and the daemon that loads it, not between a caller and an API.
