Files
a8d8cb7afb feat(telefonia): o módulo SIP vira profile do compose desligado por padrão
Decisão do dono (doc 27 da triagem): a telefonia por SIP entra como módulo
opcional, desligado por padrão — no molde do `wacalls`.

- docker-compose.voip.yml sai; `asterisk` e `voice-agent` passam a viver em
  docker-compose.prod.yml com `profiles: ["telefonia"]`. Medido: sem o
  profile, `config --services` devolve os mesmos 7 de hoje; com ele, entram
  os dois.
- O Asterisk é peça UPSTREAM e passa a ser pinado por DIGEST, não por tag: no
  registry do mantenedor nenhuma tag é imutável — a mesma `20.20.1` tem
  digests diferentes em 19/08, 26/08, 02/09, 09/09 e 16/09 (medido em
  18/09/2026 na API do Docker Hub). O digest é o da `20-alpine` de 16/09
  (= 20.20.1_alpine-3.24-e9d725f), multi-arch, com pull_policy `missing`.
- A ARI (TCP 8088) DEIXA de ser publicada: ela é o controle total das
  chamadas. Sobram as duas portas UDP que o tronco do provedor precisa
  alcançar (5060 e a faixa de RTP).
- tests/unit/portas-do-compose: `asterisk` entra na exceção de UDP, com a
  razão escrita; a regra de só-UDP é o que reprova a 8088 colada por hábito.
  Sabotagem medida: publicar 8088/tcp → 1 caso vermelho.
- tests/unit/packaging: o parser passa a cobrar 10 serviços; `voice-agent`
  entra em NOSSOS (imagem publicada, nunca build-only) e `asterisk` fica de
  fora (upstream, não se republica); Dockerfile.voice-agent entra na prova de
  procedência OCI, e o workflow passa a ser cobrado pelas QUATRO imagens.
  Sabotagem medida: asterisk em `:latest` → 1 caso vermelho.
- Kit (DoD 15): `gravar_imagens` e o install.sh passam a gravar
  VOICE_AGENT_IMAGE/PULL_POLICY na MESMA versão das outras três, e o
  update.sh a exporta. Sem isso, quem ligasse a telefonia depois de atualizar
  rodaria o `stable` móvel do default do compose enquanto o resto da
  instalação está pinado numa versão. Gravar não liga nada: imagem de profile
  inativo não é puxada.
- .env.example: o passo a passo para ligar (pjsip.conf/ari.conf,
  COMPOSE_PROFILES=telefonia) e as variáveis do contêiner de voz (ARI_*,
  AUDIOSOCKET_PORT, OPENAI_REALTIME_MODEL), que são do contêiner e não do
  app — por isso não entram em lib/env.ts.
- tests/e2e/trunk-sip-config.spec.ts entra em SPECS_PARTE_3 (estava fora do
  CI, o que reprova e2e-cobertura-completa).
- .changes: fragmento `capacidade_nova` do módulo.

Co-authored-by: SnoopyHuman <SnoopyHuman@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 18:50:00 -03:00
..