Skip to content

Versioning policy

OrbitalReg releases are tagged with Calendar Versioning (CalVer) of the form YYYY.MAJOR.MINOR. The first production-ready CalVer release is 2026.1.0.

2026.1.0   ─┬─  Year of release: four-digit year

2026.1.0   ─┼─  Major release: incremented per feature wave inside a year
            │   (resets at year boundaries — first major of 2027 is 2027.1.0)

2026.1.0   ─┴─  Minor release: incremented per patch / bug-fix release
                inside the current major

Why CalVer?

For self-hosted infrastructure, "is my version current?" matters more than "is my version semantically newer?". CalVer makes the age of a deployment immediately readable: an operator running 2024.3.5 in 2027 can see at a glance that they're two years behind without having to remember the semantic-versioning history.

Pre-CalVer SemVer tags (v0.x.y) remain valid in the build path — checking out an old tag still produces a working binary — but every new release after 2026-05-05 is tagged in the CalVer scheme. The GitHub Actions release pipeline rejects tags that don't match YYYY.MAJOR.MINOR(-rc.N)?.

Examples

TagReading
2026.1.0First production major release in 2026.
2026.1.1First patch on the 2026.1 line — bug-fix only.
2026.2.0Second feature-bundle release of 2026.
2026.2.0-rc.1Release candidate ahead of 2026.2.0.
2027.1.0First major release of the next year.

The optional pre-release suffix (-rc.N, -pre.N, -alpha.N, -beta.N) sorts before the corresponding stable tag — 2026.2.0-rc.2 is older than 2026.2.0.

Cadence

CadenceTypical intervalWhat lands
Patch release1–4 weeksBug fixes, small UI tweaks, docs updates
Major release~1 quarterNew format adapters, new admin surfaces, new APIs
Year boundary~12 monthsResets the major counter; signals broader feature set
LTS (planned)YearlyLast YYYY.MAJOR of each year — 24-month support

The cadence is suggestive, not contractual. If a critical vulnerability lands during the cycle, a patch ships immediately regardless of where we are in the calendar.

Breaking changes

OrbitalReg deprecation policy:

  1. Breaking changes are announced at least one major version in advance.
  2. Deprecated APIs continue to function for the announcement window; they emit a Warning HTTP header — Warning: 299 - "deprecated: <reason>" — so operators can grep their logs for usage.
  3. Deprecated APIs are removed in the major release after the announcement window closes.

Channels for deprecation announcements:

  • Release notes (docs.orbitalreg.com/releases/...) — the authoritative list.
  • Banner on Admin Overview — operators see the next removal window without reading release notes (item 4 of the product roadmap, "scheduled banner").
  • Webhook event system.deprecation_warning — commercial-tier channel for operators that prefer programmatic notification.

EOL policy

Each year-major (YYYY.MAJOR) is supported for 18 months from its first stable release:

2026.1.0   first stable — start of support window
2026.1.5   patches land throughout
2027.7.0   end of support window for the 2026.1 line

After EOL, the line receives no further patches — including security patches. Operators are expected to upgrade to a supported line; the License-page Feature-Matrix (item 60 / delivery #69) tracks this on the in-product license page.

Year-majors are not retroactively bumped to LTS — the LTS designation is published with the release. Historical year-majors that predate the LTS programme (2026.1, 2026.2, …) follow the standard 18-month window.

Update-channel check

A daily background worker pulls a JSON manifest from the operator- configurable URL — defaults to https://updates.orbitalreg.com/manifest.json — and caches the latest.version field so the Admin → Overview page can render an "Up to date" / "Patch available" / "Year behind" badge without each admin's browser making a separate egress call.

The worker is air-gapped-respecting: when the Telemetry channel on /admin/network is blocked, the worker short-circuits and the badge surfaces "update check disabled — air-gapped" instead of a misleading version comparison. Operators that prefer to skip the update check entirely can clear the manifest URL via:

bash
curl -X PUT \
  -H 'Content-Type: application/json' \
  -d '{"manifest_url": ""}' \
  --cookie cookies.txt \
  https://orbitalreg.example.com/api/admin/version-status/settings

A custom (intranet-mirrored) manifest URL is set with the same endpoint:

bash
curl -X PUT \
  -H 'Content-Type: application/json' \
  -d '{"manifest_url": "https://intranet.example.com/orbitalreg/manifest.json"}' \
  --cookie cookies.txt \
  https://orbitalreg.example.com/api/admin/version-status/settings

The manifest format is intentionally tiny:

json
{
  "latest": {
    "version":     "2026.1.0",
    "released_at": "2026-05-15T00:00:00Z",
    "channel":     "stable"
  }
}

Future releases may extend the shape with additional channels (rc, lts) and an eol array; the worker accepts-but-ignores those extras so a self-hosted manifest mirror can update at its own pace.

Migration from pre-CalVer (v0.x.y)

Operators running a v0.x.y build see their installed version verbatim on the admin page, marked pre-CalVer. The first CalVer release after their install is published as 2026.1.0; documentation for the upgrade lives at docs.orbitalreg.com/releases/2026.1.0.

The build path continues to accept v0.x.y tags so re-checking-out a pre-CalVer tag still produces a working binary; only the release pipeline enforces the CalVer pattern.

Validate a tag locally

bash
make version-check
# OK 2026.1.0 matches CalVer YYYY.MAJOR.MINOR

Failing builds print the matched pattern so you can see exactly which shape the pipeline expects:

text
ERROR: version 'v0.5.1' is not CalVer.
       Tag the next release as 2026.1.0 (Year.Major.Minor).
       Pattern: ^20[2-9][0-9]\.[0-9]+\.[0-9]+(-(rc|pre|alpha|beta)\.[0-9]+)?(-dirty)?$

Released under the Apache-2.0 License.