4.5 KiB
4.5 KiB
Post-Deployment Verification Checklist
Use this after every deploy (staging and production).
Preconditions
- Deployment completed successfully.
- Migrations completed successfully.
- Correct environment flags:
AUTH_DISABLED=falseALLOW_INSECURE_AUTH_FOR_DEV=false
- Test DB preflight (for DB-backed suites):
TEST_DATABASE_URLpoints to a reachable PostgreSQL instance.TEST_DATABASE_URLdatabase name is notskymoneyand is clearly test-only (for exampleskymoney_test).bash ./scripts/validate-test-db-target.shpasses before DB-backed suites run.- Example quick check:
echo "$TEST_DATABASE_URL"
Expected:
- single valid URL value
- host/port match the intended test database (for local runs usually
127.0.0.1:5432)
- Compose/DB safety preflight:
COMPOSE_PROJECT_NAME=skymoneyis set for deploy runtime.docker-compose.ymlvolumepgdatais pinned toskymoney_pgdata.scripts/validate-prod-db-target.shpasses for current.env.scripts/guard-prod-volume.shpasses (or explicit one-time rebuild override is documented).- deploy runbook acknowledges forbidden destructive commands in prod:
prisma migrate resetprisma migrate devprisma db push --accept-data-lossdocker compose down -v/docker-compose down -v
Database recoverability and safety checks
0) Capture current container and volume bindings
docker ps --format '{{.Names}}'
docker inspect <postgres-container> --format '{{json .Mounts}}'
docker volume ls | grep -E 'pgdata|skymoney|postgres'
PROD_DB_VOLUME_NAME=skymoney_pgdata ALLOW_EMPTY_PROD_VOLUME=0 DOCKER_CMD="sudo docker" bash ./scripts/guard-prod-volume.sh
Expected:
- production Postgres uses
skymoney_pgdata. - no unexpected new empty volume silently substituted.
0.1) Validate latest backup artifact exists and verifies
ls -lt /opt/skymoney/backups | head
LATEST_DUMP="$(ls -1t /opt/skymoney/backups/*.dump | head -n 1)"
sha256sum -c "${LATEST_DUMP}.sha256"
Expected:
- latest dump and checksum exist.
- checksum verification returns
OK.
0.2) Restore drill into isolated test DB (same VPS)
RESTORE_DB="skymoney_restore_test_$(date +%Y%m%d%H%M)" \
BACKUP_FILE="$LATEST_DUMP" \
RESTORE_DATABASE_URL="postgres://<user>:<pass>@127.0.0.1:5432/${RESTORE_DB}" \
DATABASE_URL="postgres://<admin-user>:<admin-pass>@127.0.0.1:5432/skymoney" \
./scripts/restore.sh
Expected:
- restore completes without manual edits.
- key tables readable in restored DB.
A01 smoke checks
Replace ${API_BASE} with your deployed API base URL.
1) Protected route requires auth
curl -i "${API_BASE}/dashboard"
Expected:
- HTTP
401 - response body includes
UNAUTHENTICATED
2) Spoofed identity header is ignored
curl -i -H "x-user-id: spoofed-user-id" "${API_BASE}/dashboard"
Expected:
- HTTP
401
3) Admin rollover is not publicly callable
curl -i -X POST "${API_BASE}/admin/rollover" \
-H "Content-Type: application/json" \
-d '{"dryRun":true}'
Expected:
- HTTP
401or403(must not be publicly callable)
A09 smoke checks
4) Security events are emitted for failed auth attempts
Trigger a failed login attempt:
curl -i -X POST "${API_BASE}/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"nonexistent@example.com","password":"WrongPass123!"}'
Expected:
- HTTP
401 - API logs include a structured
securityEventforauth.loginwithoutcome=failure - log entry includes
requestId
A10 smoke checks
5) Production origin configuration is public and non-local
Verify production env/config:
APP_ORIGINuses public HTTPS host (not localhost/private IP ranges)
Expected:
- API boots successfully with production env validation.
Automated regression checks
Run in CI against a prod-like environment:
cd api
npm test -- tests/auth.routes.test.ts tests/access-control.account-delete.test.ts tests/access-control.admin-rollover.test.ts
SECURITY_DB_TESTS=0 npx vitest run -c vitest.security.config.ts
SECURITY_DB_TESTS=1 npx vitest run -c vitest.security.config.ts
Expected:
- all tests pass
Note:
- A06/A07 runtime suites require PostgreSQL availability.
SECURITY_DB_TESTS=0runs non-DB security controls only.SECURITY_DB_TESTS=1includes DB-backed A06/A07/forgot-password suites.
Sign-off
- Record outputs in
evidence-log-template.md. - Review open residual risks in
residual-risk-backlog.md. - Record backup + restore drill evidence.
- Mark release security check as pass/fail.