# Releases and changelogs

https://exo.now/docs/shipping/releases

> Every deployment gets an internal version and, when stable, a tenant-specific public "Stable N" release.



Source: [tenant releases and changelogs](../../../docs/releases.md).

## Two version identities [#two-version-identities]

| Identifier       | Example        | Audience                 | Purpose                                                    |
| ---------------- | -------------- | ------------------------ | ---------------------------------------------------------- |
| Internal version | `2.4.0+abc123` | Operators and developers | Precisely identifies the build, commit, or migration state |
| Public release   | `Stable 18`    | Site users and clients   | A simple, memorable indication of the stable version       |

Public numbers are independent for each tenant. The first stable release is `Stable 1`, and each
later one increments by one. Drafts, previews, and internal releases don't consume a number, and a
published number is never reused. **Stable N** is the default human-facing name in product emails,
changelogs, dashboards, and updates. The exact technical version stays available as secondary
evidence.

## Publishing workflow [#publishing-workflow]

1. Create a release draft for the tenant and record its internal version.
2. Add a title, summary, highlights, and optional detailed notes.
3. Link the prompt-linked commits, change review, Entire checkpoint, deployment, changelog, and
   roadmap item.
4. Review the release against the staging build.
5. Send the approval packet to an authorized owner.
6. After explicit owner approval on the release pull request, merge the candidate into `main` and
   publish it on the `stable` channel.
7. Exo assigns the next public release number and publication date.
8. Verify the live version, tenant health checks, and changelog entry.
9. Send the configured changelog email, first to the owner-preview address, and keep non-secret
   delivery evidence.

Publishing a changelog entry records a release. It does not bypass the release pull-request gate
or deploy code by itself.

## Approval packet [#approval-packet]

```text
Changed
- ...

Removed
- Nothing.

Pressure-test / concerns
- No specific concerns.

Validation
- ...

Deployment impact
- ...

Rollback
- ...
```

Call out data migrations, authentication or authorization changes, destructive operations,
provider changes, and tenant-specific behavior explicitly. Don't invent a concern when there is
none. Approval to merge code is not approval to deploy it unless the owner explicitly grants both.

## Cadence [#cadence]

* Integrate task-sized commits into staging as soon as they pass validation.
* Consolidate reviewed staging commits into a release pull request instead of approval-gating
  every staging update.
* Don't let approved work sit unreleased without a stated reason.
* Keep staging on the same commit and configuration intended for production.
* Never report a release as live until the deployed version and health checks are verified.

## Public changelog [#public-changelog]

Off by default. When a tenant enables it, the built-in renderer exposes `/changelog`, and external
renderers can read `GET /api/content/:tenant/changelog`, which returns only published, public,
stable releases.
