diff --git a/DEPLOYMENT_RUNBOOK.md b/DEPLOYMENT_RUNBOOK.md index 4bdf963..55e4205 100644 --- a/DEPLOYMENT_RUNBOOK.md +++ b/DEPLOYMENT_RUNBOOK.md @@ -50,6 +50,13 @@ git show HEAD:docker-compose.yml | grep -cE '^[[:space:]]*build:' # must be 0 # Every migration in the tree is committed — a build from a dirty tree bakes in extras. git status --porcelain -- backend/migrations/ # must print nothing + +# The Caddyfile PARSES. Nothing else checks it: the e2e stack mounts `e2e/Caddyfile.test`, +# so the production file is never executed until the real deploy — and a syntax error there +# is total. Caddy exits, `restart: unless-stopped` loops, 443 is dead for the whole event, +# and `docker compose up -d --force-recreate caddy` still exits 0 while it crash-loops. +docker run --rm -v "$PWD/Caddyfile:/etc/caddy/Caddyfile:ro" -e DOMAIN=example.com \ + caddy:2-alpine caddy validate --config /etc/caddy/Caddyfile # must end "Valid configuration" ``` | When | What | @@ -623,6 +630,18 @@ docker compose exec -T db sh -c \ 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "DELETE FROM _sqlx_migrations WHERE version = NN;"' ``` +> **A down migration is only valid PAIRED WITH A CODE ROLLBACK — it is not a standalone repair.** +> `Upload::create` sends an `ON CONFLICT ... WHERE` predicate that must match the live partial +> index exactly, and these queries are not compile-checked. Run **026**'s or **031**'s down against +> the current binary and every upload carrying a `client_upload_id` — i.e. every upload from the +> shipped client — becomes a runtime 500. Roll the image back first, then the migration. +> +> **026's down can also fail outright, and that is expected.** It restores a wider unique index, so +> it aborts with `could not create unique index ... is duplicated` on any database where a guest +> ever deleted a photo and re-uploaded it. The transaction rolls back cleanly and the narrow index +> survives intact — no half-state — but you cannot go below 026 on a database that has seen real +> use. Verified against a live Postgres. + Migration **014** is the only destructive one on the way up, and the only one with a rehearsal harness — `backend/scripts/rehearse-014.sh`. Run it once against a real dump before the event.