Upgrades and versioning
What a version is
A Lumaft version is MAJOR.MINOR.PATCH, optionally with a prerelease suffix such as -rc.1.
An unsuffixed version is stable. No leading v, no build metadata, and no latest, dev, or
branch-named tags exist.
Pin the digest. A version tag is immutable and resolves to the same digest on both registries, but the digest is the coordinate that cannot be reinterpreted.
What a release publishes
Each release is a directory in the public distribution repository, releases/<version>/, that
no later release overwrites:
release.json— the release record: version, release time, source revision, the multi-architecture image digest, canonical and mirror coordinates, and the composition record.- A snapshot of that release's documentation. The repository root describes the newest
release; when running an older one, read
releases/<version>/docs/. lumaft-cli-<version>.tgzon the matching GitHub Release, with its SHA-256 and size bound into the release record.
releases/index.json lists every release, newest first.
The composition record
Every release record embeds a machine-derived account of what the image is made of: the source
commit; the image index and per-platform digests, the pinned base image, and the Node.js
version; the resolved version of every production dependency, including the embedded SQLite
version; SBOM and provenance references; and verifiedAgainst — only the surfaces this
release was actually tested against (Pulumi CLI versions, deployment schema versions, object
store targets, browsers).
No field is hand-authored, and verifiedAgainst is a test record, not a compatibility promise.
A surface that is listed was exercised; that is all it claims.
Verify what you pull
Every published digest is keylessly signed at promotion time with the release workflow's GitHub OIDC identity. Verify before you run:
cosign verify \
--certificate-identity-regexp '^https://github\.com/dekglas/application/\.github/workflows/promote-public-release\.yml@' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/dekglas/lumaft@sha256:<digest>
Substituting docker.io/dekglas/lumaft@sha256:<digest> verifies the mirror against the same
identity. Only that workflow identity is a trusted signer.
The image is built once in a private candidate boundary and promoted by copying the exact reviewed digest; it is never rebuilt for publication. The candidate build scans both architectures and rejects fixed high or critical findings before promotion.
Support window
Only the newest published release is supported. There are no maintenance lines and no backports: a fix, including a security fix, ships as a new release at the head of the line, and upgrading is the supported way to receive it. A prerelease is superseded by any later release.
Compatibility
| Surface | Contract |
|---|---|
| Image | One edition-neutral, multi-architecture (linux/amd64, linux/arm64) OCI image per release |
| Browser API | Versioned under /api/v1; UI-internal routes carry no compatibility promise |
| Ingestion API | /api/v1/ingestion/…, bearer-token only; stable within a major version |
| Health and diagnostics | /api/v1/health, /api/v1/readiness, /api/v1/storage-health, /api/v1/observation-polling, /api/v1/object-store-traffic; fields may be added within a major |
| Backend configuration | schemaVersion: 1; unknown fields rejected atomically |
| Export document | lumaft-operation-history-export, schema version 6 |
| Database schema | Migrated forward at startup, transactionally; an older image refuses a newer schema |
Supported automation surfaces — the ingestion API, the health probes, and the documented
diagnostics — change incompatibly only in a new major version, after a release whose notes
named the deprecation. Everything else under /api/v1 serves the shipped console and may
change in any release without notice; automation built against it is unsupported.
Release notes
Every release's notes enumerate capability additions, changes, and removals; every schema migration the release applies with its risk class; any deprecation; and the delta to Known limitations. Read them before upgrading, particularly the migration list — a gated migration changes the procedure below.
Upgrade procedure
SQLite
- Read the release notes.
- Stop the replica cleanly:
docker stop -t 30 lumaft(ordocker compose stop). A clean stop checkpoints the WAL and leaves no-walor-shmsidecar. Exit code143is expected. - Take and verify a cold backup. This step is mandatory, because rollback is a restore.
- Start the new digest against the same volume.
- Confirm
/api/v1/readinessreturns200and the console loads.
If the new image refuses to start because the upgrade carries a gated migration, nothing has
been migrated. The log line names the revision and the authorization value; follow
Gated migrations: start once with
LUMAFT_SCHEMA_UPGRADE_APPLY=<revision>, confirm readiness, remove the variable.
Before choosing which image to start, you can read which release last migrated a stopped volume; see Reading the version stamp.
PostgreSQL, one replica
Same steps; the backup is your database tooling's backup (a base backup or pg_dump), taken
while Lumaft is stopped.
PostgreSQL, Enterprise replicas
Only startup-safe migrations permit a rolling deployment. When the release notes list a gated
migration, scale to one replica, apply it as above, then scale back out. Migrations have one
owner; waiting replicas reread the committed schema lineage. After restoring PostgreSQL, restart
every replica.
Rollback
Upgrades are forward-only. An older image started against a database a newer one migrated
exits with the database schema (…) is newer than this image supports (…), naming both
revisions and touching nothing. That refusal is the design.
Rolling back a committed upgrade means:
- Stop and remove the replica.
- Restore the pre-upgrade backup per Backup and disaster recovery.
- Start the older image against the restored file.
Evidence accepted between the upgrade and the rollback is lost with the restore; backends converge forward on the next observation cycle.
Edition downgrade
A license lapse or downgrade never deletes evidence, changes an effective retention policy, or hides history. The rule: a license may gate an act, never a state. A downgrade may refuse to place a new legal hold but never releases one; may refuse to enable state retention for a new backend but never deletes an artifact; may refuse to begin a new PostgreSQL cutover but never migrates or locks an installation already on PostgreSQL. Custom roles stop being assignable and their holders fall back to viewer; existing stack grants keep narrowing reads; configured federated sign-in remains available.
Safe diagnostics for a report
Only Lumaft-authored lines in a documented closed format are safe to share. Include the log line verbatim, closed reason codes, HTTP status codes, the version and digest, the schema revision from the version stamp, and readiness and storage-health results. Never include the database, a backup, an export, Pulumi state, or a credential. See Troubleshooting.