Skip to content

Versioning

arkhe follows Semantic Versioning 2.0.0: MAJOR.MINOR.PATCH.

The version is still 0.x — see Before 1.0. The current release is not written here, because it would go stale at every release; it is in the changelog.

What the version covers

SemVer is only meaningful once you say what the public surface is. For a piece of infrastructure rather than a library, it is broader than "the functions we export".

Part of the contract Example of a breaking change
Resolution behaviour An inflection stops answering; a status code changes; suffix passthrough stops resolving through an ancestor
REST API A field is removed or renamed; a request that used to succeed now fails
Environment variables A setting is renamed or removed; a default changes in a way that alters behaviour
CLI A command or option is removed or renamed; output that scripts parse changes shape
Database schema A migration that cannot be applied to an existing ledger, or that loses data
The invariants Any of them weakening. See below

Not covered: internal module layout, the admin interface's markup, log formats, and anything under compose/ (those are demonstrations).

The invariants are part of the contract

These refusals are what arkhe is for. Weakening one is a major change even if no signature moves:

  • a name that has been published becomes removable without a reason, without the ARK retyped, or from outside the caller's reach (removing one is possible — narrowly, and recorded; 0.4.0 opened that door on purpose and said so)
  • a namespace becomes deletable
  • a withdrawn name becomes mintable again
  • retired becomes reversible
  • minting can silently become an update
  • reach becomes widenable by a request
  • a person subject can hold an API key, or a machine subject can be named through an external login

A release that did any of those quietly would be worse than one that broke a function signature, because the damage would be to identifiers rather than to a build.

Migrations

A minor release may add a migration; it must never lose data. Every migration is run upgrade → downgrade → upgrade against PostgreSQL before every release (scripts/check.sh), because SQLite accepts schemas PostgreSQL rejects.

The ledger cannot be rebuilt. Under NR a lost ARK cannot be minted again, so "restore from the source system" is not available to us the way it is to most services.

Before 1.0

While the version starts with 0, the minor number carries breaking changes: 0.1.0 → 0.2.0 may break, 0.0.1 → 0.0.2 should not.

1.0 will be tagged when:

  • the ARK conformance record has no outstanding gaps,
  • the schema has been stable across at least one real migration, and
  • an organisation other than the first is running it.

Until then, pin an exact version.

Releasing

# 1. The version and the changelog (the section for it, and both link definitions)
vim pyproject.toml CHANGELOG.md CHANGELOG.ja.md && uv lock

# 2. Check, without releasing anything. This is the default
bash scripts/release.sh v0.1.0

# 3. Release: tag, push, and create the GitHub release
bash scripts/release.sh v0.1.0 --publish

# 4. Publish the documentation, so the changelog page catches up
bash scripts/deploy-docs.sh

Checking and releasing are separate on purpose. Step 2 is cheap and can be repeated; a tag and a GitHub release cannot be taken back, so nothing is published without --publish.

The script refuses to go on unless the tag matches pyproject.toml, both changelogs carry a section and a link definition for the version, and the unreleased comparison link has moved to the new one. Everything else follows from pyproject.toml — the package, the OpenAPI document and the admin footer all read the version from there. A 0.x release is marked as a prerelease on GitHub, so the version number is not mistaken for a stability claim.