scripts/apply-db-init.sh implements the boot-time runner that walks
db-init/*.sql in numeric-prefix order, applies each via psql, and
records successful applications in a migrations_applied guard table
so re-runs are no-ops.
All 7 acceptance criteria pass live against the dev compose stack:
empty dir, missing env var, apply, idempotent re-run, checksum
mismatch, filename collision, broken SQL.
Two retroactive Dockerfile corrections folded in (exposed by the
first live-test attempt of 1.2's script):
1. apk add bash. The directus/directus:11.17.4 base is Alpine and
ships ash via BusyBox, not bash. The script uses bash-specific
features (associative arrays, [[ ]], mapfile, BASH_REMATCH) and
fails at line 69 in sh.
2. .gitattributes added at repo root forcing LF on *.sh, *.sql,
*.yaml, *.yml. Without it, Windows checkouts with core.autocrlf=true
(the Git-for-Windows default) silently inject CRLF, causing
"bad interpreter: /usr/bin/env bash^M" inside the Linux container.
This failure mode only manifests in the container.
Both corrections are documented in 01-project-scaffold.md's Done
section; 02-db-init-runner.md's Done section captures the live-test
results, the corrected docker compose run --entrypoint commands, and
the gotcha about compose env defaults masking missing-env-var tests.
ROADMAP marks 1.2 done; 1.3 next.