Plano de Integração — chatskills-quiz-ai-gen (8 horas)

Documento executivo · v1.0 · 2026-05-14

Substituição do workflow n8n QuizAIGen-Core-v1 pelo microserviço Python chatskills-quiz-ai-gen, com paridade funcional 1:1, sem mudanças no backend de produção.


1. Resumo executivo

Item Valor
Esforço total 8 horas (1 dia útil)
Janela recomendada Terça ou quarta, 09:00–18:00 (evita segunda/sexta)
Equipe mínima 1 dev backend + 1 QA (parcial, 2h) + 1 DevOps (parcial, 1h)
Risco Baixo — rollback é trocar 1 URL no produtor
Indisponibilidade prevista Zero (rollout paralelo, switch atômico)
Custo OpenAI estimado por quiz ~$0.015 (text gpt-4.1-mini) + $0.040 (image gpt-image-1) = **$0.055/quiz**

Critérios de sucesso (Definition of Done)


2. Pré-requisitos (T-1 dia)

A ser checado antes do dia D para não consumir as 8 horas:

# Item Responsável Verificação
1 Acesso ao repositório chatskills Dev git clone funciona
2 Python 3.12+ instalado Dev python --version
3 Docker + Docker Compose disponíveis DevOps docker compose version
4 .env populado para staging DevOps secrets em cofre
5 OpenAI API key com saldo ≥ $20 PM dashboard.openai.com
6 CHATSKILLS_JOB_TOKEN rotacionado (token antigo está no JSON do n8n) DevOps novo token testado
7 CHATSKILLS_API_KEY + API_SECRET rotacionados DevOps novo par testado
8 URL de staging do ChatSkills disponível DevOps curl /health no staging
9 3 PDFs de teste preparados em tests/fixtures/ (texto OK, scan/sem texto, corrompido) QA arquivos commitados
10 Acesso ao painel admin do ChatSkills (validar quiz criado) QA login funciona

Se algum item acima estiver vermelho no início do dia D, abortar a integração e reagendar.


3. Cronograma hora-a-hora

Hora 1 (09:00–10:00) — Setup local & boot do serviço

Objetivo: ambiente de dev funcionando, testes passando, app rodando localmente.

Passo Comando Tempo Critério
1.1 git clone do repo e cd chatskills-quiz-ai-gen 5 min repo presente
1.2 python -m venv .venv && .venv\Scripts\activate 2 min venv ativo
1.3 pip install -r requirements.txt 5 min sem erros
1.4 copy .env.example .env e preencher com credenciais de staging 10 min .env populado
1.5 pytest -v 5 min 25/25 PASSED
1.6 uvicorn app.main:app --reload --port 8001 1 min logs service_starting
1.7 curl http://localhost:8001/health 1 min {"status":"ok"}
1.8 curl http://localhost:8001/docs 1 min Swagger UI abre

Checkpoint H1: ambiente verde, suite de testes verde, serviço respondendo.


Hora 2 (10:00–11:00) — Smoke test local com PDF real

Objetivo: validar end-to-end com OpenAI real e callback para staging do ChatSkills.

Passo Ação Tempo Critério
2.1 Preparar PDF real de 1–3 páginas em tests/fixtures/sample.pdf (ex.: o PDF "ETAPA 1 — A STAGE.pdf" usado no n8n) 5 min arquivo presente
2.2 Disparar webhook via curl (ver bloco abaixo) 1 min 202 retornado
2.3 Acompanhar logs no terminal do uvicorn 5 min sequência: uploadFile→extractFile→workingWithInstructions→generatingImage→generatingQuiz
2.4 Validar PUTs de status chegando no staging do ChatSkills (logs do backend ou DB) 10 min 7–9 PUTs visíveis
2.5 Validar quiz criado no painel admin do ChatSkills (staging) 10 min quiz com 5 perguntas + ícone PNG aparece
2.6 Inspecionar o quiz: 5 perguntas, cada uma 5 opções, exatamente 1 correta 10 min schema OK
2.7 Comparar qualidade da geração com output histórico do n8n (mesmo PDF) 15 min linguagem/dificuldade equivalentes
2.8 Documentar jobId de teste para audit trail 4 min anotado

Comando de smoke:

curl -u $BASIC_AUTH_USER:$BASIC_AUTH_PASS \
  -X POST http://localhost:8001/webhook/quiz/upload \
  -F "file=@tests/fixtures/sample.pdf;type=application/pdf" \
  -F "jobId=smoke-h2-$(date +%s)" \
  -F "color=#5D3FD3" \
  -F "difficulty=easy" \
  -F "userId=4OJMRrYdAIdzSNr5pcPmjfT3eA82" \
  -F "groupId=fdafdc37-31ca-4a90-a613-d2dd65edb565"

Checkpoint H2: quiz gerado e visível no ChatSkills staging. Se falhar, ir para hora 8 (rollback).


Hora 3 (11:00–12:00) — Testes de cenários de erro

Objetivo: confirmar que os 4 caminhos de erro produzem os eventStatus=ERROR corretos.

# Cenário Input eventStatus esperado Critério
3.1 Auth ausente sem -u n/a 401 retornado
3.2 Auth errado -u tester:wrong n/a 401 retornado
3.3 Campos faltando sem groupId n/a 422 retornado
3.4 Arquivo não-PDF file=@README.md uploadFile=ERROR mensagem "Nenhum arquivo PDF válido"
3.5 PDF corrompido bytes %PDF mas conteúdo lixo uploadFile=ERROR (PDF inválido) erro logado, sem chamada OpenAI
3.6 PDF scan sem texto PDF imagem-only textEmpty=ERROR "texto extraído do PDF está vazio"
3.7 OpenAI fora do ar (text) desconectar internet ou trocar OPENAI_API_KEY por inválida workingWithInstructions=ERROR erro propagado
3.8 OpenAI fora do ar (image) mock indisponível generatingImage=ERROR mas pipeline continuageneratingQuiz=DONE sem ícone quiz criado sem imagem

Time-box: 7 min por cenário (~55 min). Documentar resultados em planilha.

Checkpoint H3: todos os erros produzem o evento certo. Nenhum erro deixa o pipeline em estado indefinido.


Hora 4 (12:00–13:00) — Almoço / buffer

Buffer para cobrir atrasos das horas 1–3. Se tudo estiver no prazo, almoço de 1h.


Hora 5 (13:00–14:00) — Build, push e deploy em staging

Objetivo: containerizar e subir em ambiente de staging.

Passo Comando Tempo
5.1 docker compose -f docker/docker-compose.yml build 8 min
5.2 Testar container localmente: docker compose up -d + curl localhost:8001/health 5 min
5.3 docker compose logs -f para confirmar boot limpo 2 min
5.4 Tag da imagem: docker tag chatskills-quiz-ai-gen:local <registry>/chatskills-quiz-ai-gen:v1.0.0 1 min
5.5 Push para registry: docker push <registry>/chatskills-quiz-ai-gen:v1.0.0 5 min
5.6 Provisionar serviço em staging (ECS/Kubernetes/VPS — conforme infra do chatskills) 20 min
5.7 Configurar .env em staging via cofre de secrets 10 min
5.8 Validar curl https://quiz-ai-gen-staging.chatskills.com.br/health 5 min
5.9 Configurar reverse proxy / DNS interno se aplicável 4 min

Checkpoint H5: serviço acessível em URL pública de staging com HTTPS.


Hora 6 (14:00–15:00) — Switch do produtor (staging) + carga sintética

Objetivo: apontar o produtor de staging para o novo serviço e validar sob carga leve.

Passo Ação Tempo
6.1 No produtor (mobile dev/backend de staging), trocar URL de https://n8n.chatskills.com.br/webhook/quiz/upload para https://quiz-ai-gen-staging.chatskills.com.br/webhook/quiz/upload 10 min
6.2 Disparar 10 quizzes em sequência via produtor real 15 min
6.3 Disparar 5 quizzes em paralelo (xargs -P 5) — validar BackgroundTasks aguenta concorrência 10 min
6.4 Coletar métricas: latência do 202 (deve ser < 500ms), tempo total até generatingQuiz=DONE (esperado: 15–40s, dominado pela imagem) 10 min
6.5 Validar 100% dos quizzes aparecem corretos no admin 10 min
6.6 Comparar custo OpenAI consumido com previsão (~$0.055 × 15 = $0.83) 5 min

Comando de carga sintética:

seq 1 5 | xargs -P 5 -I {} curl -u $USER:$PASS \
  -X POST https://quiz-ai-gen-staging.chatskills.com.br/webhook/quiz/upload \
  -F "file=@sample.pdf" -F "jobId=load-{}" -F "color=#5D3FD3" \
  -F "difficulty=easy" -F "userId=u1" -F "groupId=g1"

Checkpoint H6: 15/15 quizzes processados corretamente em staging. Sem erro 5xx. Latência aceitável.


Hora 7 (15:00–17:00) — Cutover para produção (gradual)

Objetivo: mover o tráfego de produção do n8n para o novo serviço, com janela de observação curta entre cada passo.

Esta hora consome 2 blocos (15:00–17:00 = 2h) porque exige observação ativa entre etapas. Se o time só puder dedicar 8 horas totais, encolher H1+H4 para liberar este tempo.

Passo Ação Tempo Observação
7.1 Deploy do mesmo container em produção (push + provision) 20 min mesma imagem v1.0.0
7.2 .env de produção com tokens reais (rotacionados) em cofre 10 min nunca commit
7.3 Validar GET /health em produção 5 min 200 OK
7.4 Canary 10%: feature flag ou roteador que envia 10% do tráfego para o novo serviço, 90% segue no n8n 20 min monitorar 20 min
7.5 Observar 30 minutos: logs estruturados (filtro por jobId), taxa de erro, latência p50/p95 30 min erro < 1%
7.6 Se canary saudável: subir para 100% 5 min toggle 100%
7.7 Observar 30 minutos sob carga real total 30 min sem alerta

Gatilhos de rollback automático durante esta hora:

Comando de rollback (~30 segundos): ver hora 8.

Checkpoint H7: 100% do tráfego em produção, ≥ 30 minutos saudável.


Hora 8 (17:00–18:00) — Observabilidade, documentação e handoff

Objetivo: deixar o sistema observável e a equipe equipada para operar.

Passo Ação Tempo
8.1 Configurar log aggregator (Datadog/Grafana Loki/CloudWatch) com filtro por service=chatskills-quiz-ai-gen 15 min
8.2 Criar dashboard mínimo: req/min, erro 5xx, tempo total do pipeline, custo OpenAI estimado 15 min
8.3 Criar 1 alerta: > 5 erros em 5 minutos → notificação 10 min
8.4 Atualizar runbook interno com: como ver logs, como rebootar container, como rollback 10 min
8.5 Marcar workflow Core no n8n como inativo mas não deletado (fallback por 7 dias) 2 min
8.6 Comunicar conclusão para stakeholders (Slack/email com link do dashboard) 5 min
8.7 Agendar review pós-7-dias para desativar definitivamente o n8n 3 min

Checkpoint H8 — sistema entregue.


4. Plano de rollback (qualquer hora)

Se algo der errado em qualquer momento, o rollback é trivial:

Rollback durante H1–H6 (staging)

Rollback durante H7 (canary/produção)

  1. No produtor: voltar URL para https://n8n.chatskills.com.br/webhook/quiz/upload
  2. Confirmar que o workflow n8n Core está com active: true
  3. Disparar 1 quiz teste para validar que voltou ao n8n
  4. Tempo total de rollback: < 2 minutos

Rollback pós-cutover (dias seguintes)


5. Matriz de testes consolidada

ID Categoria Tipo Cenário Status esperado Cobertura
T01 Unitário Modelo Quiz com 5 perguntas válidas parsed OK test_models_quiz.py
T02 Unitário Modelo Quiz com 4 perguntas ValidationError idem
T03 Unitário Modelo Quiz com 4 opções ValidationError idem
T04 Unitário Modelo Quiz com 0 correctas ValidationError idem
T05 Unitário Modelo Quiz com 2 correctas ValidationError idem
T06 Unitário Modelo Quiz com título vazio ValidationError idem
T07 Unitário Modelo Serialização round-trip bytes idênticos idem
T08 Unitário PDF PDF válido com texto string não-vazia test_pdf_extractor.py
T09 Unitário PDF bytes vazios ValueError idem
T10 Unitário PDF bytes inválidos ValueError idem
T11 Unitário Quiz Gen OpenAI retorna JSON válido Quiz parsed test_quiz_generator.py
T12 Unitário Quiz Gen OpenAI retorna lixo QuizValidationError idem
T13 Unitário Quiz Gen OpenAI retorna schema inválido QuizValidationError idem
T14 Unitário Quiz Gen Quiz sem color/difficulty → fallback preenchido a partir do input idem
T15 Unitário Icon Gen OpenAI retorna b64 válido bytes PNG test_icon_generator.py
T16 Unitário Icon Gen OpenAI falha 2× None retornado idem
T17 Integração Webhook sem auth 401 test_webhook.py
T18 Integração Webhook senha errada 401 idem
T19 Integração Webhook request válido 202 + payload correto idem
T20 Integração Webhook campos faltando 422 idem
T21 Integração Webhook healthcheck 200 idem
T22 E2E (mocked) Pipeline happy path completo sequência de status correta + POST final test_pipeline.py
T23 E2E (mocked) Pipeline PDF inválido uploadFile=ERROR idem
T24 E2E (mocked) Pipeline texto vazio textEmpty=ERROR idem
T25 E2E (mocked) Pipeline imagem falha → continua generatingImage=ERROR mas POST final ocorre idem
T26 Manual Staging PDF texto real quiz visível no admin hora 2
T27 Manual Staging PDF scan textEmpty=ERROR hora 3
T28 Manual Staging PDF corrompido uploadFile=ERROR hora 3
T29 Manual Staging OpenAI indisponível erro propagado hora 3
T30 Manual Staging 10 sequenciais 100% sucesso hora 6
T31 Manual Staging 5 paralelos 100% sucesso hora 6
T32 Manual Produção canary 10% erro < 1% por 30 min hora 7
T33 Manual Produção 100% por 30 min sem alerta hora 7

Cobertura: 25 automatizados + 8 manuais = 33 verificações.


6. Riscos & mitigações

Risco Probabilidade Impacto Mitigação
OpenAI rate-limit em produção Média Alto max_attempts=2 no icon gen; chat já tem retry interno do SDK; monitorar 429
BackgroundTasks não dá conta de pico Baixa Médio v2: migrar para arq+Redis. Para volume atual (~dezenas/dia), suficiente
Token rotacionado mas n8n ainda usa antigo Baixa Alto Rotação só após desativação do n8n (passo 8.5) ou suportar ambos por 7 dias
Quiz gerado tem qualidade pior que n8n Baixa Médio Prompt copiado verbatim — qualidade idêntica garantida
Custo OpenAI dispara Baixa Médio Alerta de gasto diário > $50 no dashboard OpenAI
Latência total inaceitável Baixa Médio Maior custo de tempo é gpt-image-1 (10-30s) — mesmo do n8n. Sem regressão

7. Indicadores pós-cutover (primeira semana)

Monitorar diariamente nos 7 dias após o switch:

Métrica Meta Ação se exceder
Taxa de erro (5xx) < 1% Investigar logs, considerar rollback
p95 latência do 202 < 1s Verificar saturação do worker
Tempo total p95 (202 → ai-create POST) < 60s Investigar OpenAI
Erros generatingImage=ERROR < 5% Investigar prompt/quota
Custo OpenAI diário < $20 (ajustar conforme volume real) Avaliar caching ou redução de retry

8. Aprovações necessárias

Etapa Aprovador Antes de quê
Provisionar serviço em staging (H5) DevOps lead criar recursos
Cutover canary 10% (H7.4) Tech lead mudar produtor de prod
Cutover 100% (H7.6) Tech lead + Product switch total
Desativar n8n permanentemente (D+7) Tech lead deletar workflow

9. Anexos


Documento mantido sob versionamento em chatskills-quiz-ai-gen/docs/. Atualizar após cada cutover real.