Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.production.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ APERIO_METRICS_TOKEN=replace-me-with-a-long-random-metrics-token

# The release image is signed and published to GHCR. Prefer the immutable
# digest from the release-receipt artifact after the first pull/verification.
APERIO_IMAGE_REF=ghcr.io/writer/aperio:v0.1.0
APERIO_IMAGE_REF=ghcr.io/writer/aperio:v0.1.1
APERIO_EVENT_BUS=nats
APERIO_NATS_STREAM=CEREBRO_EVENTS
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
with:
go-version: "1.26.6"
- run: npm ci
- run: npm run db:generate
- run: npm run db:validate
- run: npm run typecheck
- run: npm run audit:prod
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to Aperio are recorded here. Release entries are tied to a s

## [Unreleased]

## [0.1.1] - 2026-08-21

- Fixed release validation to generate the Prisma client before typechecking.
- Republished the `0.1.0` feature set after the `v0.1.0` workflow stopped
before image publication.

## [0.1.0] - 2026-08-21

- Added tenant-scoped, hashed API tokens with read, write, and admin scopes,
Expand Down
10 changes: 5 additions & 5 deletions deploy/compose/compose.production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ services:
retries: 12

migrate:
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.0}
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.1}
restart: "no"
environment:
DATABASE_URL: postgresql://${POSTGRES_USER:-aperio}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env.production}@postgres:5432/${POSTGRES_DB:-aperio}?schema=public
Expand All @@ -41,7 +41,7 @@ services:
condition: service_healthy

api:
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.0}
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.1}
restart: unless-stopped
init: true
command: ["api"]
Expand Down Expand Up @@ -73,7 +73,7 @@ services:
start_period: 15s

web:
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.0}
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.1}
restart: unless-stopped
init: true
command: ["web"]
Expand All @@ -95,7 +95,7 @@ services:
start_period: 15s

ingestion-worker:
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.0}
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.1}
restart: unless-stopped
init: true
command: ["ingestion-worker"]
Expand All @@ -113,7 +113,7 @@ services:
condition: service_healthy

siem-dispatcher:
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.0}
image: ${APERIO_IMAGE_REF:-ghcr.io/writer/aperio:v0.1.1}
restart: unless-stopped
init: true
command: ["siem-dispatcher"]
Expand Down
14 changes: 8 additions & 6 deletions docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The public repository owns source validation and image publication. Deployment c

```bash
npm ci
npm run db:generate
npm run db:validate
npm run typecheck
npm run audit:prod
Expand All @@ -23,18 +24,19 @@ Update [`CHANGELOG.md`](../CHANGELOG.md), confirm the image tag in [`.env.produc
## Publish

```bash
git tag -a v0.1.0 -m "Aperio v0.1.0"
git push origin v0.1.0
VERSION=v0.1.1
git tag -a "${VERSION}" -m "Aperio ${VERSION}"
git push origin "${VERSION}"
```

The workflow publishes `ghcr.io/writer/aperio:v0.1.0` and uploads a `release-receipt` artifact containing the image tag, immutable digest, source commit, and signing result. Download that artifact and record the digest before deployment:
The workflow publishes `ghcr.io/writer/aperio:${VERSION}` and uploads a `release-receipt` artifact containing the image tag, immutable digest, source commit, and signing result. Download that artifact and record the digest before deployment:

```bash
cosign verify \
--certificate-identity "https://github.com/writer/aperio/.github/workflows/release.yml@refs/tags/v0.1.0" \
--certificate-identity "https://github.com/writer/aperio/.github/workflows/release.yml@refs/tags/${VERSION}" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/writer/aperio:v0.1.0
docker buildx imagetools inspect ghcr.io/writer/aperio:v0.1.0
"ghcr.io/writer/aperio:${VERSION}"
docker buildx imagetools inspect "ghcr.io/writer/aperio:${VERSION}"
```

The public workflow does not dispatch into a private environment. The operator-owned deployment process must use the receipt digest, apply it through the private deployment system or the production Compose bundle, and retain the resulting deployment and user-path checks with the release record. For Compose, set `APERIO_IMAGE_REF` to the `image@sha256:...` value from the release receipt and capture `docker compose ... ps` plus the `/readyz` response after the migration service completes.
Expand Down
5 changes: 5 additions & 0 deletions tests/migration-ownership-guardrails.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,11 @@ test("validator and CI gates include contracts, audit, worker smoke, and secret
assert.match(reviewPreflight, /name: Droid Review Preflight/);
assert.match(reviewPreflight, /name: Droid Review Required/);
assert.doesNotMatch(reviewPreflight, /Factory-AI|pull-requests:\s*write/i);
assert.match(
release,
/npm ci[\s\S]*npm run db:generate[\s\S]*npm run db:validate[\s\S]*npm run typecheck/,
"release validation must generate the Prisma client before typechecking"
);
assert.match(release, /name: Upload release receipt/);
assert.match(release, /deployment: \"operator-owned\"/);
assert.doesNotMatch(release, /notify-infra-release|APERIO_INFRA_|target_environment|repository_dispatch/i);
Expand Down