feat(infra): apps/api e apps/frontend como services systemd

Fecha um risco documentado desde a PHASE 01: os dois processos de host
(fora do Docker) não sobreviviam a um reboot da VM, precisando ser
religados manualmente toda vez. Agora são b2bcall-api.service e
b2bcall-frontend.service (infrastructure/systemd/), enabled, sobrevivem a
reboot como os containers Docker já sobreviviam via restart:
unless-stopped.

Achado real resolvido antes de instalar: sem porta fixa, os dois
disputavam a 3000 por padrão — quem perdesse crashava com EADDRINUSE em
vez de cair pra 3001. Fixado API_PORT=3000 (.env) e PORT=3001
(Environment= direto na unit do frontend — confirmado que colocar em
apps/frontend/.env.local não funciona, o CLI do Next.js decide a porta
antes de aplicar esse arquivo). A ordem de start deixa de importar.

Rodam em modo dev (pnpm dev), não build de produção — decisão deliberada
documentada no README, virar produção é escopo maior.

Testado ponta a ponta: units instaladas e habilitadas, subiram nas portas
certas sem fallback nem crash, journalctl com logs limpos, smoke test de
regressão nas 19 telas do tenant + platform via os processos
supervisionados, todas 200. Achado incidental: as rotas do Next.js dev
levam 10-15s pra compilar na primeira visita — explica os TimeoutError
intermitentes do Puppeteer vistos ao longo da sessão, não é um bug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
2026-08-30 00:33:44 -03:00
parent e9dc973aee
commit 4480e9265e
4 changed files with 162 additions and 11 deletions

76
TODO.md
View File

@@ -1396,6 +1396,59 @@ secao 134-139, 168)
ninguém com `users.manage`) — não implementado, mesma classe de
risco documentada em outras ações administrativas desta sessão
## PHASE 38 — Infraestrutura: `apps/api`/`apps/frontend` como services
systemd (fecha um risco documentado desde a PHASE 01)
- [x] `infrastructure/systemd/b2bcall-api.service` e
`b2bcall-frontend.service` (+ `README.md` com instalação/comandos
úteis) — os dois processos de host (fora do Docker) agora
`enabled`, sobrevivem a reboot como os containers já sobreviviam
via `restart: unless-stopped`.
- [x] **Achado real, resolvido antes de instalar as units**: sem porta
fixa, `apps/api` e `apps/frontend` disputavam a 3000 por padrão —
quem perdesse a corrida crashava (`EADDRINUSE`, Nest/Fastify sem
fallback) em vez de cair pra 3001 como o Next.js faz sozinho. Fixado
`API_PORT=3000` em `.env` e `PORT=3001` via `Environment=` direto na
unit do frontend — a ordem de start deixa de importar, cada um já
nasce na porta certa.
- [x] **Achado real, descoberto testando**: `PORT=3001` em
`apps/frontend/.env.local` **não funciona** — o CLI do `next dev`
decide a porta antes desse arquivo ser aplicado (confirmado: com
`.env.local` sozinho, ainda aparecia "Port 3000 is in use, using
3001" mesmo com `.env.local` correto). Só `Environment=`/uma
variável de ambiente real do processo funciona. Documentado no
README pra não recair no mesmo engano depois.
- [x] Rodam em modo dev (`pnpm dev`), não build de produção — decisão
deliberada (`README.md` explica: mudar pra `next build`/`tsc &&
node dist` é escopo de "ir pra produção", não de "sobreviver a
reboot"), documentada explicitamente em vez de fingir que já é
produção.
- [x] Testado ponta a ponta: parado os processos manuais, instalado e
habilitado as duas units, `systemctl start` na ordem api→frontend
(a ordem já não importa mais, mas testado assim mesmo) — os dois
subiram na porta certa sem nenhum fallback nem crash, `journalctl
-u` confirma logs limpos com `SyslogIdentifier`, smoke test de
regressão nas 19 telas do tenant + platform via os processos
supervisionados por systemd, todas 200.
- [x] **Achado incidental, explica uma flakiness recorrente do próprio
processo de teste desta sessão inteira**: `journalctl` confirmou
rotas do Next.js dev levando 10-15s pra compilar na primeira visita
(`Compiled /platform/billing/tarifas in 11.9s`) — a causa real dos
vários `TimeoutError` de navegação do Puppeteer vistos ao longo de
várias fases anteriores, sempre contornados com um retry simples.
Não é um bug, é o modo dev do Next.js funcionando como esperado;
registrado na memória do projeto pra não investigar de novo à toa
numa sessão futura.
- [ ] Não testado com um reboot de verdade da VM (deliberadamente evitado
— reboot é uma ação disruptiva demais pra essa sessão confirmar
sozinha); `systemctl is-enabled` confirma que as units estão
registradas pra iniciar no boot, o que é a garantia que o systemd
oferece, mas o cenário completo (Docker + Postgres/Redis prontos +
as duas units subindo depois) nunca foi observado de ponta a ponta
numa reinicialização real
- [ ] `apps/api`/`apps/frontend` continuam sem HTTPS/domínio próprio
(nginx, pendência original da PHASE 01) — o acesso de teste
continua direto na porta 3001 da VM
---
## Riscos conhecidos
@@ -1408,14 +1461,15 @@ secao 134-139, 168)
- **RAM da VM aumentada pra 8GB em 2026-08-29** — resolve a preocupação acima, mas
ainda não tem swap generoso nem monitoramento de pico durante um build de frontend +
todos os workers rodando junto; reavaliar se o Next.js dev server crescer muito.
- **`apps/api` e `apps/frontend` rodam direto no host** (`pnpm dev`), fora do
docker-compose — só Postgres/Redis/FreeSWITCH/fs-config/fs-events/predictive-dialer/
ai-worker são containers. Depois de qualquer reboot da VM (como o desta sessão, pra
aplicar a RAM nova) os containers voltam sozinhos (restart policy do compose), mas
os dois processos de host **não voltam** — precisam ser religados manualmente:
`apps/api` precisa de `set -a && source .env && set +a` antes (não lê `.env`
sozinho, ao contrário dos containers) e deve subir **antes** do frontend, porque os
dois usam a porta 3000 por padrão (`API_PORT` não setado, `next dev` sem `-p`) — o
segundo a subir cai sozinho pra 3001. `B2BCALL_API_URL` do frontend
(`apps/frontend/.env.local`) assume que a API ficou com a 3000, então a ordem
importa. Sem um processo supervisor (pm2/systemd) isso vai se repetir a cada reboot.
- ~~`apps/api` e `apps/frontend` rodam direto no host, sem supervisor, não
sobrevivem a reboot~~ **RESOLVIDO na PHASE 38** (2026-08-30): os dois agora são
services systemd (`b2bcall-api.service`/`b2bcall-frontend.service`,
`infrastructure/systemd/`, `enabled`) — sobrevivem a reboot como os containers
Docker já sobreviviam. `API_PORT=3000` (`.env`) e `PORT=3001` (`Environment=` da
unit do frontend, não `.env.local` — não funciona lá, o CLI do Next.js decide a
porta antes de aplicar esse arquivo) fixam as duas portas, então a ordem de start
não importa mais (achado real: sem isso, os dois competiam pela 3000 por padrão, e
quem perdesse crashava com `EADDRINUSE` em vez de cair pra 3001). Detalhes e
comandos úteis (`systemctl status`/`restart`, `journalctl -f`) em
`infrastructure/systemd/README.md`. Continuam rodando em modo dev (`pnpm dev`), não
build de produção — decisão deliberada, ver o README.