Files
DeskcommCRM/docker/scheduler
Rafael MelgaçoandClaude Opus 5 6eb0b2d2ee fix(packaging): os 11 defeitos de gravidade alta que a revisão adversarial achou
Rodei 6 lentes independentes sobre o próprio diff, cada achado passando por um
cético que tinha de REPRODUZIR o cenário. 27 confirmados de 38, e 11 altos. Os
que quebravam de verdade:

**A transição pareava o app de uma release com o worker do topo da main.** Numa
VPS que atualiza pela primeira vez, quem executa é o update.sh VELHO — o do
disco. Ele faz `git checkout` (que já troca o compose pelo novo) e só sabe
gravar APP_IMAGE. Worker e scheduler caíam no default do compose, que era
`:latest` = topo da main. Ou seja: a entrega que existe para consertar "o worker
nunca era atualizado" faria o parque rodar código NÃO LANÇADO no runtime do
agente de IA, sobre o banco da release. O default virou `:stable` (a última
release) — conserto de uma linha, sem tocar em script, para uma corrida que
nenhum script novo pode vencer.

**`dc pull` sem guarda abortava a instalação NOVA.** Dar `image:` a um serviço
que era build-only muda o `pull` de "Skipped" para FALHA quando a referência não
resolve — e há três motivos reais para não resolver logo após um release: pacote
novo no GHCR nasce PRIVADO, a tag git existe minutos antes das imagens, e o
registro pode cair. O install morria no passo 9, com banco provisionado e .env
escrito. Ganhou a mesma guarda que o update já tinha.

**O pin do WAHA não chegava a ninguém.** `install.sh:1338` gravava
`WAHA_IMAGE=devlikeapro/waha` — sem tag — por cima do default pinado do compose.
O pin existia e era inalcançável.

**Toda tag `v*` também movia `latest`.** `enable={{is_default_branch}}` é
verdadeiro num push de tag, então o canal oscilava entre "topo da main" e
"última release" — apagando a distinção de que a doutrina inteira depende.
`latest` agora exige `ref_type == 'branch'`, e `stable` exige tag `v*`.

**O rollback podia matar todos os crons.** Numa instalação legada, `dc images -q
scheduler` devolve o ID do `alpine:3.20` antigo, cujo crontab vinha de um
`command:` que este compose não tem mais. Gravar esse ID deixaria o contêiner
rodando o CMD do alpine puro: sai na hora, `restart: unless-stopped` recoloca,
crashloop silencioso. Agora só entram no rollback os serviços cujo .env já tem a
chave — isto é, instalações que já passaram pelo update novo.

**A doutrina afirmava o que não era.** Dizia que `build-and-push` já era check
obrigatório (a branch protection diz `verify, build-and-size, invariants, e2e`),
citava dois arquivos de teste que não existem, e creditava ao update-guard uma
prova que é do test-validators. Cometi, dentro da doutrina, exatamente o defeito
que ela existe para impedir. Agora a pendência está escrita como pendência, com
a medição e o motivo de a ativação não poder vir antes do merge.

**O único artefato executável novo não tinha gate** — e escondia uma injeção: o
heredoc interpolava o INTERNAL_SECRET dentro de aspas duplas, então uma crase no
segredo virava substituição de comando a cada minuto. Medido, com o valor real
que saía: `segrafaelmelgacoredo/Users/rafaelmelgaco…`, com `whoami` EXECUTADO.
O valor passou para aspas simples com escape, e tests/shell/scheduler-entrypoint.test.sh
monta o header com um `sh` de verdade e compara byte a byte — sabotar de volta
para aspas duplas reprova.

De quebra: `SCHEDULER_APP_ORIGIN` era controle decorativo (o entrypoint lia, o
compose não repassava, nenhum template documentava) e saiu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RKm2XcTcfgi1vdMcDYSRWa
2026-08-13 12:12:24 -03:00
..