Repository navigation
Closed
Labels
area:infraInfra: CI, Docker, imagem multi-arch, releases, templates de deployInfra: CI, Docker, imagem multi-arch, releases, templates de deploy
Milestone
Description
Contexto
Este é o gate de aceite do milestone v0.1: a imagem construída a partir da main, com todas as issues de código fechadas, passa por smoke, e2e, contratos e pela matriz mínima de harnesses no Docker Desktop local (desktop-linux, arm64), seguindo o procedimento de .claude/agents/qa-docker.md. Também fica registrada a linha de base (tempo de build, tamanho da imagem, bases) para comparar com os upgrades do v0.2.
Escopo
- Build de
docker/Dockerfile→thinker:qa-<id>(arm64 nativo; amd64 via buildx, ao menos o build). Registrar tempo, tamanho, imagens base e versão do Postgres. - Compose isolado (
thinker-qa-<id>), com segredos descartáveis e health. - Boot negativo: sem
THINKER_ENCRYPTION_KEYfalha; com a chave igual aoBETTER_AUTH_SECRETfalha (THINKER_ENCRYPTION_KEY obrigatória e separada do BETTER_AUTH_SECRET #27). - Smoke:
- o dashboard serve HTML;
- o setup do primeiro admin funciona; depois, o cadastro público é recusado (Fechar o cadastro público depois do primeiro admin #29);
- criar agente e chave
thk_; /v1/models;- chat via provedor mock em
/v1/chat/completions,/v1/messagese/v1/responses, com e sem streaming; - cabeçalhos
x-thinker-*; - gravação criada e cifrada; log de retenção de 30 dias (Gravações de requisição: retenção padrão de 30 dias #28).
- Sem phone-home, verificado na rede (não basta ler os logs: falhas de saída são engolidas, ex.:
provider-param-spec.service.ts:113herdado):- stack numa rede Docker
internal: true(sem rota para fora), com o provedor mock e o Postgres na mesma rede; - o container do Thinker usa como DNS um sidecar que registra todas as consultas (ex.: CoreDNS com o plugin
log, ou dnsmasq com--log-queries) e responde NXDOMAIN para nomes externos; - um sidecar de captura no namespace de rede do Thinker (
network_mode: service:thinker, ex.:tcpdump -nnonicolaka/netshoot) registra tentativas de conexão para fora da sub-rede, inclusive para IPs literais; - janela de observação: do boot até pelo menos 10 minutos depois, com o smoke rodando dentro dela. Os jobs agendados (cron diário e horário) ficam cobertos pela conferência estática de README e documentação do usuário em PT-BR #33; se o tempo permitir, a janela cruza o minuto :34 de uma hora (o antigo cron do
modelparams.dev); - duas rodadas, com os destinos aprovados no ADR 0003 (Catálogos externos de modelos e preços versus a regra de não fazer phone-home #11) e a chave implementada em Catálogos públicos: chave THINKER_CATALOG_SYNC e OpenCode Go só com provedor cadastrado #39:
- padrão, sem provedor OpenCode Go cadastrado: só podem aparecer
openrouter.aiemodels.dev, e nenhum outro, nemraw.githubusercontent.com; - com
THINKER_CATALOG_SYNC=false: nenhuma consulta DNS nem conexão externa;
- padrão, sem provedor OpenCode Go cadastrado: só podem aparecer
- nenhum acesso a
modelparams.dev,*.manifest.build,api.github.com,raw.githubusercontent.com/mnfstou Sentry em nenhuma rodada; - todo destino observado está na lista de
docs/usuario/privacidade.md(README e documentação do usuário em PT-BR #33). Anexar ao relatório o log de DNS e o resumo da captura.
- stack numa rede Docker
- e2e:
packages/backend/testcontra o Postgres da mesma imagem do compose;contracts/gatewaycontra o container (THINKER_BASE_URL). - Matriz mínima de harnesses, com mock e sem credenciais reais: Claude Code (
ANTHROPIC_BASE_URL+thk_), Codex/OpenCode, snippet OpenClaw/Hermes, SDKs OpenAI e Anthropic. - CLI
thinker(CLI thinker #23):login,agent list. - Guard de nomes legados em modo bloqueante:
node scripts/check-legacy-names.js --strictsem nenhuma ocorrência fora da allowlist (depois de Guia do desenvolvedor do Thinker #32 e README e documentação do usuário em PT-BR #33). - Relatório como comentário nesta issue; cada falha vira uma issue de bug no milestone v0.1, com o label da área.
Fora de escopo
- Corrigir código (o
qa-dockersó reporta). - Publicar a imagem (Release 0.1.0 e primeira imagem no Docker Hub #35).
Critérios de aceite
- Todos os passos com pass (ou skip justificado), sem bug bloqueante aberto no milestone.
Dependências
- Catálogos externos de modelos e preços versus a regra de não fazer phone-home #11 (ADR 0003): os destinos aprovados para o teste de egresso.
- Catálogos públicos: chave THINKER_CATALOG_SYNC e OpenCode Go só com provedor cadastrado #39: a chave
THINKER_CATALOG_SYNCe o gate do OpenCode Go, que as duas rodadas verificam. - CLI thinker #23, Nó n8n do Thinker #24, Rebranding do dashboard #25, Docker, Compose e instalador do Thinker #26, THINKER_ENCRYPTION_KEY obrigatória e separada do BETTER_AUTH_SECRET #27, Gravações de requisição: retenção padrão de 30 dias #28, Fechar o cadastro público depois do primeiro admin #29, Release, Changesets 0.1.0 e publicação no Docker Hub #31
- Guia do desenvolvedor do Thinker #32, README e documentação do usuário em PT-BR #33: o guard de nomes legados só pode bloquear depois que o guia e a documentação forem reescritos; a lista de privacidade vem de README e documentação do usuário em PT-BR #33.
Agente responsável
qa-docker
Metadata
Metadata
Assignees
Labels
area:infraInfra: CI, Docker, imagem multi-arch, releases, templates de deployInfra: CI, Docker, imagem multi-arch, releases, templates de deploy
Activity
patrickbrandao commentedon Oct 11, 2026
Herdado da revisão do PR #52: o e2e
proxy-no-plan-gatefaz stub de fetch só paraapi.openai.come deixa os outros hosts irem para a rede real. Garantir que a suíte não faça egress real, o que se encaixa no teste de ausência de egress desta issue.patrickbrandao commentedon Oct 11, 2026
Robustez do guard de egress (nits da revisão do PR #70), para considerar no teste de rede desta issue:
egress-recorder.cjsnão registradns.resolve4nem conexões diretas a IP. Hoje nenhum código usa isso, mas a verificação no nível de rede (DNS e captura de pacotes) cobre.postgresnuma rede compose), e o boot falha de um jeito confuso.patrickbrandao commentedon Oct 11, 2026
Observação dos QAs de 2026-10-11 (#103, #104): no primeiro boot com volume novo, o log mostra uma linha ERROR
[Better Auth]: Database schema mismatch / Missing tablesantes de o Better Auth rodar a própria migração; setup e login funcionam logo depois. Verificar no baseline se dá para evitar o falso erro (rodar a migração antes da checagem ou rebaixar para info).patrickbrandao commentedon Oct 14, 2026
qa-docker: baseline v0.1 (run qdb081a) - PASS on every step executed
Tested SHA:
3b7ab345e190768b1f2b87f1a8f90aaef503d10a(origin/main). Docker Desktopdesktop-linux, arm64. Mock provider only,THINKER_CATALOG_SYNC=false, no real external host contacted by Thinker.thinker:qa-qdb081a)docker/install.sh --yes(compose served from a local HTTP server throughTHINKER_INSTALLER_SOURCE, local image viaTHINKER_VERSION, run-scoped project)docker compose logs thinker | grep 'setup token', wrong token 403, first admin 201, public sign-up then refused (SIGNUP_DISABLED)thk_key, custom provider (mock), default tier,model: auto(M101 before the tier,pongafter,x-thinker-*headers)tools/list(18 tools) andthinker_agent_listMRE1envelope, no plaintext); log "retention 30 days, storage filesystem"THINKER_CATALOG_SYNC=falsetest:e2e:docker, postgres:16-alpine pinned)install.sh --upgrade(same version): login, setup status (needsSetup:false), agent, key andautochat all intact; no new setup tokenEgress (network level)
Isolated bridge (
internal: true, 10.77.77.0/24) with Postgres, mock, a DNS sink as the Thinker container's resolver (logs every query, answers NXDOMAIN) and anicolaka/netshoottcpdump sidecar in the Thinker network namespace. Window: boot 15:28:47Z to 15:39:43Z (about 11 min, crossing :34; smoke ran at about 15:29).ip route: only 10.77.77.0/24).Docs
Nothing wrong found in
docs/usuario/instalacao-docker.mdandprimeiros-passos.mdwhen followed literally. Notes: thesetup tokengrep works on the colored logs; the browser/curl Origin must equalBETTER_AUTH_URL(localhost, not127.0.0.1), which the docs already say.Observations (no failure)
node scripts/check-legacy-names.js --strict, but that script does not exist on main (scripts/has no such file, nothing in CI). The strict guard step was not run; the manual grep above stands in for it.WARN [Better Auth]: Rate limiting could not determine a client IP and is falling back to a single shared per-path bucketfor requests from the host through Docker Desktop with the compose defaultTRUST_PROXY=loopback. Harmless here, but all clients behind that path share one auth bucket.Baseline
Base images (pinned in the Dockerfile):
node:24-alpine@sha256:ebfe2f90...e2f905ec1c1(deps/build),node:24-slim@sha256:d6aa754f...87f7b20(prod-deps), runtimegcr.io/distroless/nodejs24-debian13:nonroot@sha256:9eeb7f58...3fa278e. Postgres16.15(postgres:16-alpine@sha256:721873c3...6080ea).Not covered in this run (outside the requested scope)
Negative boot (#27), harness matrix, CLI (
login,agent list), default-sync egress round.Teardown: both Compose projects removed with
down -vafter checking labels; no run-labelled volume, container or network left; worktree removed.patrickbrandao commentedon Oct 15, 2026
A baseline passou na main 3b7ab34: veja o relatório acima. A release 0.1.0 foi gerada a partir de cda88cb, que só acrescenta o #169 (docs).