55e0a3cde6
The image builds were never exercised: the docker job needs lint, and lint was failing, so nothing downstream of it ever ran. Four defects had accumulated behind that gate, each fatal on its own. - pnpm creates no node_modules for a package without dependencies, and @source/shared has none. Three COPY lines named that path and failed. - The production stage copied apps/api/dist, which tsc never wrote: tsconfig.base.json sets noEmit and no package overrides it. Rather than turn emit on — every @source/* package points main at its TypeScript source, and @source/proto derives daemon.proto's location from a /src/index.ts module URL — the stage now runs the sources through tsx, exactly as the migrate stage has always done. - tsx lives in apps/api/node_modules/.bin under pnpm's isolated layout, so the command only resolves from the package directory. - Both healthchecks probed localhost, which musl resolves to ::1 while the servers bind IPv4. Every probe was refused, so the containers sat unhealthy forever — and `docker compose up --wait`, which is how a panel installs this stack, waits for healthy. Also fixed the postgres healthcheck in both compose files. pg_isready without -h asks over the unix socket, which answers during the image's init phase before the server listens on TCP; the migrate container then started and died with ECONNREFUSED against a container Compose had just called healthy. Verified by running the full stack from docker-compose.panel.yml with locally built images: migrations and seed complete, api, web, daemon, postgres and redis all report healthy, and /api/health answers 200 through the web container's proxy.