Verified live via WSL Docker (docker compose up --wait): every other F0
service came up healthy, but web stayed unhealthy. Root cause was two
compounding issues, both invisible to static review:
1. Docker auto-sets HOSTNAME to the container ID; Next's standalone
server.js honors that env var and binds only to it instead of all
interfaces. Fixed by explicitly setting ENV HOSTNAME=0.0.0.0 in the
Dockerfile, after Docker's automatic assignment.
2. Even bound to 0.0.0.0 (IPv4), the healthcheck's `wget http://localhost`
resolved localhost to ::1 (IPv6) first inside the container, where
nothing was listening. Fixed by pointing the healthcheck at
127.0.0.1 explicitly instead of localhost.
Full stack (db, redis, migrate, auth, storage, protocols, web) now
reaches healthy end-to-end under docker compose up --wait.
Merges the F0 milestone from PLAN.md: monorepo scaffolding, initial Postgres
schema migration, the Go protocols domain layer with unit tests, health-checked
auth/storage/webmail service skeletons, local docker-compose.yaml, language
lint, and CI workflow.
Stands up the LambdaMail monorepo per PLAN.md's F0 milestone: local dev
scaffolding (.env.example, Makefile, .gitignore excluding PLAN.md/docs/
.superpowers/), the full initial Postgres schema as a golang-migrate
migration, the complete Go domain layer for services/protocols (value
objects, entities, domain events - zero external imports beyond
github.com/google/uuid) with unit tests, health-checked service skeletons
for auth/storage (TypeScript) and webmail (Next.js), a local
docker-compose.yaml wiring all services together, a language-enforcement
lint script, and a GitHub Actions CI workflow.
Built via 11 sequential tasks under subagent-driven development, each with
an independent implementer + reviewer cycle. Fixes applied during review:
DomainName.IsPunycode() added to satisfy the promised interface; ioredis
default-import typing under NodeNext; next.js bumped 15.0.3->15.5.21 to
resolve high/critical CVEs; lang-lint.mjs corrected to not flag its own
banned-terms list; web service healthcheck added so compose --wait
actually waits on it; webmail Dockerfile's missing public/ directory:
protocols go.mod version aligned with CI's Go 1.22 pin.
Known follow-ups for later phases (not blocking F0): go-arch-lint isn't
wired into CI yet; live docker compose up and migration apply have not
been exercised in this dev environment (no Docker/psql available here)
and will get their first real run in CI, which does have Docker.