staging deployment

# Staging Deployment

## Runtime shape

Staging runs on a single VPS with:

- Caddy (public `80/443`)
- API
- Portal
- Public site
- Redis

Managed services:

- PostgreSQL
- Cloudflare R2 (S3-compatible object storage)

MinIO is local-dev only and is not used in staging.

## Host routing

- `api.staging.<domain>` -> `api:8002`
- `app.staging.<domain>` -> `portal:3000`
- `staging.<domain>` -> `public-site:3000`

## Deployment

Use only:

```bash
docker compose --env-file .env.staging.compose --env-file .env.staging.runtime -f docker-compose.staging.yml up -d
```

Do not include local development compose files in staging.

Required files on staging:

- `.env.staging.compose`
- `.env.staging.api`
- `.env.staging.portal`
- `.env.staging.public`
- `.env.staging.runtime`

## Migration safety

Staging uses `prisma migrate deploy` via `pnpm --filter @styleauth/api prisma:migrate`.

Migrations must be additive and backwards-compatible because rollback only reverts app images, not the database schema.

## Deploy order

1. Pull images
2. Run `prisma migrate deploy`
3. `docker compose up -d`
4. Healthcheck (`/v1/health`)
5. Roll back image tags only if healthcheck fails