Não existia nenhum artefato de deploy: sem Dockerfile, sem compose, sem pin de
Node. O runbook pedia `npm run start` e `npm run worker` à mão, o que não é um
ambiente reproduzível, e o worker dependia de `tsx`, uma devDependency, que
`npm ci --omit=dev` removeria.
- Dockerfile multistage. Web e worker saem da mesma imagem: mesmo código,
mesmas dependências, só o subcomando difere.
- `tsx` foi para `dependencies`. Conferido em diretório limpo: os 13 pacotes
externos que src e scripts usam existem no install de produção.
- A sobreposição das duas árvores de node_modules é segura e foi medida: 318
pacotes em produção contra 153 traçados, zero divergência de versão entre os
compartilhados, e 3 que existem só na traçada, que o COPY mescla sem
remover. O package.json do standalone não é sobrescrito.
- Entrypoint com subcomandos, que garante `node --import tsx` em todos os
scripts. Usar `node` direto convidaria de volta o defeito do SIGTERM.
- Healthcheck de liveness na web e de heartbeat no worker.
- Compose local reproduz a topologia com Postgres e Redis de verdade. Compose
de homologação não declara Postgres (é o banco gerenciado), usa Redis
isolado com senha e volume próprios, publica porta só em 127.0.0.1 e tem
nome de projeto, rede e volume exclusivos. Nenhum serviço de outro
aplicativo do ecossistema é declarado, tocado ou reiniciado.
- `.env.staging.example` sem segredo, `.nvmrc`, `engines` e `packageManager`.
- `config/staging-seed.json` e `.env.staging` no gitignore.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
O módulo usa a identidade Supabase, isola cada workspace e registra storage, TTL, runner e biblioteca XLSX como decisões ainda abertas.
Co-authored-by: Cursor <cursoragent@cursor.com>