# Verifying Aegis Releases

This guide explains how to verify the authenticity and integrity of an Aegis release.
For the maintainer release runbook, see [Aegis Release Process](./release-process.md).

## Release Integrity

Every Aegis release is signed and attested using industry-standard tools.

### Verify with SHA-256

Download the release and verify its SHA-256 hash:

```bash
# Download the release tarball
curl -LO https://github.com/OneStepAt4time/aegis/releases/download/v0.6.0-preview/aegis-0.6.0-preview.tgz

# Verify the hash
sha256sum aegis-0.6.0-preview.tgz
```

Compare the output against the `checksums.txt` file published in the release assets.

### Verify npm Package

If you installed via npm, verify the package integrity:

```bash
# View the package integrity checksum
npm view @onestepat4time/aegis integrity

# Verify against published checksums
npm pack @onestepat4time/aegis --dry-run
```

## Sigstore Attestations (Beta)

Aegis releases include Sigstore attestations for npm packages, verifiable against the GitHub Actions OIDC identity.

### Install cosign

```bash
brew install cosign  # macOS
# or: go install github.com/sigstore/cosign/cmd/cosign@latest
# or: curl -sSL https://raw.githubusercontent.com/sigstore/cosign/main/release/install.sh | sh
```

### Verify npm Package Attestation

Download the Sigstore attestation bundle from the release assets, then verify:

```bash
# Download release assets
gh release download v0.6.0-preview --pattern '*.sigstore' --pattern 'checksums.txt' --dir /tmp

# Verify the attestation against the npm registry tarball
cosign verify-blob-attestation \
  --certificate-identity-regexp 'https://github.com/OneStepAt4time/aegis/.github/workflows/release\\.yml@' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --bundle /tmp/package.sigstore \
  "https://registry.npmjs.org/@onestepat4time/aegis/-/aegis-0.6.0-preview.tgz"
```

### What the Attestation Proves

The Sigstore attestation binds the npm tarball SHA256 digest to the GitHub Actions workflow run that published it. Verification succeeds only if:
- The bundle was signed by GitHub Actions OIDC (GITHUB_TOKEN)
- The workflow identity matches `https://github.com/OneStepAt4time/aegis/.github/workflows/release.yml@refs/tags/v*`
- The digest in the predicate matches the downloaded tarball

### Container Images (not yet implemented)

Container image signing will be added once the container build pipeline is in place.

## Verifying the GitHub Release

### Check the GitHub Actions Workflow

All releases are built via GitHub Actions. Verify the workflow ran successfully:

1. Go to the release page: `https://github.com/OneStepAt4time/aegis/releases/tag/vX.Y.Z`
2. Click **Actions** → look for the `Release` workflow
3. Verify all jobs passed (build, test, attest)

### SDK Release Automation

Normal releases follow `develop` → `release/<version>` → `main` → `v*` tag.
Release Please prepares version and changelog state on the short-lived
`release/<version>` branch. It does not create GitHub Releases or publish
artifacts; `.github/workflows/release.yml` owns all public publishing at tag
time.

Pushing a `v*` tag runs `.github/workflows/release.yml`. Real publishing is
production-only: the release preflight fails before publish jobs if the tag
commit is not reachable from `origin/main`. Use `.github/workflows/release-dry-run.yml`
on `develop`, `release/**`, and release PRs to validate release readiness
without publishing.

In addition to the root
`@onestepat4time/aegis` npm package, the workflow publishes:

- `@onestepat4time/aegis-client` from `packages/client` to npm.
- `ag-client` from `packages/python-client` to PyPI.

The release workflow regenerates the root OpenAPI contract, regenerates each SDK
from that contract, builds the SDK package, and then publishes it. npm packages
use provenance and public access. Stable tags publish npm packages with the
`latest` dist-tag; prerelease tags using `preview`, `alpha`, `beta`, or `rc`
publish with the matching npm dist-tag.

The validation gates are:

- `npm run openapi:check`
- `npm run sdk:ts:check`
- `npm run sdk:py:check`
- the normal release build and test steps
- the release preflight job, which checks the packaged npm tarball, checksum
  metadata, local Sigstore attestation generation/verification, release
  version/dist-tag parsing, main-branch tag reachability, and Helm gh-pages
  clone/index logic before npm publish jobs run
- the release dry-run workflow on `develop` and release PRs, which packs and
  smoke-installs local artifacts, builds SDK packages, packages Helm charts,
  and validates Sigstore predicate generation without publishing public
  artifacts
- the Release Please dry-run path on `release/**`, which verifies that the
  requested release branch can produce the expected version/changelog update

PyPI publishing uses trusted publishing via GitHub OIDC; no PyPI token is stored
in the repository. Maintainers must configure the `ag-client` project
on PyPI with a trusted publisher for repository `OneStepAt4time/aegis`, workflow
`.github/workflows/release.yml`, and environment `pypi`.

PyPI package versions must be PEP 440-compatible, so the Python SDK release job
normalizes Aegis tag versions before writing `packages/python-client/pyproject.toml`
and `packages/python-client/src/aegis_python_client/__init__.py`. The root npm
package and TypeScript SDK keep the original tag version.

| Aegis tag version | Python SDK version |
|-------------------|--------------------|
| `X.Y.Z` | `X.Y.Z` |
| `X.Y.Z-preview` | `X.Y.Z.dev0` |
| `X.Y.Z-alpha` | `X.Y.Za0` |
| `X.Y.Z-beta` | `X.Y.Zb0` |
| `X.Y.Z-rc` | `X.Y.Zrc0` |

Numeric suffixes on `alpha`, `beta`, and `rc` prerelease tags are preserved,
for example `X.Y.Z-rc.1` becomes `X.Y.Zrc1`.

Planned preview releases use `X.Y.Z-preview`. Numbered preview releases such as
`X.Y.Z-preview.1` are recovery-only. The release workflow rejects numbered
preview tags unless the tag is annotated and the annotation contains:

```text
recovery-release: true
```

### Release Branch Lifecycle

Release branches are created by the Create Release Branch workflow, not by
manual local git commands. The workflow creates `release/<version>` from
`origin/develop` and dispatches Release Please with an explicit `release-as`
version so planned previews remain `X.Y.Z-preview`.

Only one active release branch is allowed for normal releases. Release branches
must be promoted or abandoned within 48 hours; if stabilization takes longer,
delete the branch and cut a fresh one from `develop`. After a successful tag
release, the release workflow deletes the matching release branch when present;
then sync `main` back to `develop` so changelog, manifest, and version files
remain aligned.

### Hotfix Releases

Emergency hotfixes may target `main` directly only with maintainer approval.
After a hotfix tag publishes successfully, backport the fix to `develop` so the
next normal release branch includes it. If a preview artifact was already
published and is unusable, use the recovery path: fix the issue, create an
approved annotated recovery tag with a numbered preview suffix, and include
`recovery-release: true` in the tag annotation.

### Partial Preview Release Recovery

If a preview release partially publishes, first rerun the failed release
workflow. Do not bump the preview version solely to recover a rerun until the
idempotent rerun path has been attempted and a maintainer decides a replacement
version is unavoidable.

The root npm package and TypeScript SDK npm publish jobs are intentionally late
and idempotent: they check whether the exact version already exists on npm and
skip with a notice when it does. npm versions are immutable, so these jobs must
remain guarded by the preflight checks and must never publish a new version just
to recover an otherwise rerunnable preview release.

### Verify the Author

Release commits are signed by the Aegis GitHub Bot (`github-actions[bot]`). Check the commit signature:

```bash
git show --show-signature <release-commit-sha>
```

## Reporting Suspicious Releases

If you find a release that appears tampered with:

1. **Do not install it**
2. Check the [security policy](../SECURITY.md)
3. Report to: `security@onestepat4time.com`
4. Or file a private security advisory on GitHub

## Release Transparency

All Aegis releases are recorded in the public GitHub release changelog. The `CHANGELOG.md` in the repository is auto-generated by release-please and lists every change since v0.1.0.

## Version Numbering

Aegis uses semantic versioning: `MAJOR.MINOR.PATCH-preview`

| Version | Meaning |
|---------|---------|
| `0.6.0-preview` | Pre-release, v0.6.0 with preview qualifier |
| `0.5.3` | Stable release |
| `1.0.0` | First stable major release |

The `preview` suffix indicates the API may change. Production deployments should pin to exact versions.
