Incidentes de produção com Claude Code: detecção, rollback, RCA e prevenção
Guia prático para incidentes com Claude Code: segredos, exclusões, BD, custos, rollback, RCA e prevenção.
Claude Code acelera o trabalho porque consegue ler arquivos, alterar código e executar comandos. Em um repositório de produção, essa velocidade também muda o risco: uma aprovação apressada pode expor um segredo, apagar arquivos, sobrescrever main, rodar uma migração perigosa ou gerar milhares de chamadas de API.
Este artigo não descreve o incidente privado de uma empresa real. Ele reúne cenários compostos de exercícios do ClaudeCodeLab, revisões de repositório e operações de conteúdo. Horários e valores são exemplos, mas os padrões são úteis para treinar antes de uma crise.
Incidente é qualquer evento que afeta usuários, dados, segurança, custo ou disponibilidade. Conter significa impedir que o dano aumente. RCA é análise de causa raiz. Rollback é voltar para a última versão segura.
Confira a sintaxe atual na documentação oficial de Claude Code settings e hooks. Aqui usamos essas peças em um fluxo: detectar, conter, diagnosticar, reverter, comunicar, fazer postmortem e prevenir recorrência.
Fluxo de resposta
| Fase | Objetivo | Pedido útil ao Claude Code |
|---|---|---|
| Detectar | Entender mudança e impacto | Resumir alertas, logs, diff, deploys e comandos recentes |
| Conter | Parar o dano | Sugerir revogação de chave, pausa de job, flag OFF ou endpoint desligado |
| Diagnosticar | Isolar a causa direta | Comparar a última versão saudável com a mudança suspeita |
| Rollback | Voltar ao estado seguro | Listar alvo, risco de dados e comandos de verificação |
| Comunicar | Alinhar as pessoas | Redigir status, impacto, próxima atualização e responsável |
| Postmortem | Transformar falha em aprendizado | Preencher RCA, linha do tempo, detecção perdida e ações |
| Prevenir | Dificultar repetição | Adicionar permissões, hooks, CI, alertas e revisão |
Para segredos, cobrança, dados pessoais e escritas em banco, contenha primeiro e investigue depois.
Sete padrões concretos
| Padrão | O que acontece | Primeiro passo | Falha comum |
|---|---|---|---|
| Vazamento de segredo | .env, logs ou imagens expõem chave | Revogar, rotacionar, revisar logs | Limpar git e esquecer logs de CI |
| Exclusão perigosa | rm -rf remove arquivos necessários | Parar, verificar backup, listar arquivos sem versionamento | git checkout . não restaura arquivos não rastreados |
| Force push | main sobrescreve commits do time | Parar push, verificar reflog, criar branch de recuperação | Confundir --force-with-lease com --force |
| Migração de BD | Drop, update em massa ou lock derruba produção | Pausar escritas, salvar estado, restaurar com cuidado | Rodar SQL não testado em produção |
| API em loop | Retentativas elevam custo | Matar processo, pausar fila, checar limites | ”Retry” vira loop infinito |
| Dependência quebrada | Deploy sobe com 503 | Reativar deploy anterior, revisar lockfile | npm update sobe versão major |
| Auth ausente | Endpoint admin fica público | Desligar endpoint, revisar logs de acesso | ”Admin” não vira requisito de autenticação |
Três casos de incidente
Em vazamento de chave, a detecção pode vir do secret scanning do GitHub, alerta de nuvem ou tela de cobrança. A primeira ação é revogar. Depois, revisar repositório, PR, logs de CI, chat e monitoramento.
git status --short
git diff --cached --name-only
git log --all -- .env .env.local
git grep -n "sk-" -- ':!node_modules' ':!dist'
Em migração de banco, pare escritas antes de explicar. Código volta rápido; dados apagados dependem de backup, WAL, auditoria ou sincronização externa.
psql "$DATABASE_URL" -c "select now();"
psql "$DATABASE_URL" -c "\d users"
pg_dump "$DATABASE_URL" --schema-only > schema_before_repair.sql
Em retentativas de API, coloque limite explícito no batch. Salve como incident-budget-runner.mjs.
#!/usr/bin/env node
import { spawn } from "node:child_process";
const command = process.argv.slice(2);
const maxAttempts = Number(process.env.MAX_ATTEMPTS || 3);
const maxCostCents = Number(process.env.MAX_COST_CENTS || 200);
const costPerAttempt = Number(process.env.COST_PER_ATTEMPT_CENTS || 0);
if (command.length === 0) {
console.error("uso: node incident-budget-runner.mjs <comando> [...args]");
process.exit(2);
}
let estimatedCost = 0;
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
const child = spawn(command[0], command.slice(1), {
stdio: "inherit",
shell: process.platform === "win32"
});
const exitCode = await new Promise((resolve) => {
child.on("exit", (code) => resolve(code ?? 1));
});
estimatedCost += costPerAttempt;
if (exitCode === 0) process.exit(0);
if (estimatedCost >= maxCostCents) {
console.error(`parado: custo estimado ${estimatedCost} centavos`);
process.exit(1);
}
const delayMs = Math.min(1000 * 2 ** (attempt - 1), 10_000);
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
console.error(`falhou após ${maxAttempts} tentativas`);
process.exit(1);
Guardrails para Claude Code
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(git push --force *main*)",
"Bash(git push -f *main*)",
"Bash(rm -rf /*)",
"Bash(rm -rf ~*)"
],
"ask": [
"Bash(git push*)",
"Bash(rm*)",
"Bash(npm install*)",
"Bash(*migrate*)",
"Bash(*deploy*)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-danger.sh"
}
]
}
]
}
}
#!/usr/bin/env bash
set -euo pipefail
payload="$(cat)"
command="$(node -e 'const fs = require("fs"); const raw = fs.readFileSync(0, "utf8") || "{}"; const json = JSON.parse(raw); console.log(json.tool_input?.command || "");' <<< "$payload")"
blocked='(rm[[:space:]]+-rf[[:space:]]+(/|~)|git[[:space:]]+push[[:space:]].*(-f|--force)([[:space:]]|$)|DROP[[:space:]]+TABLE|TRUNCATE[[:space:]])'
if [[ "$command" =~ $blocked ]]; then
echo "Comando perigoso bloqueado: $command" >&2
exit 2
fi
exit 0
Comunicação e postmortem
## Atualização de incidente
- Status: investigando / contido / validando recuperação
- Impacto: funcionalidade, usuários, início
- Ação atual: job parado, deploy revertido, logs em revisão
- Próxima atualização: YYYY-MM-DD HH:mm
- Responsável:
# Postmortem: [título]
## Resumo
- Início:
- Detecção:
- Resolução:
- Impacto:
- Severidade: P0/P1/P2/P3
## Linha do tempo
| Hora | Evento |
| --- | --- |
| HH:mm | |
## Causa
- Causa direta:
- Causa raiz:
- Por que a detecção atrasou:
## Prevenção
| Ação | Responsável | Prazo |
| --- | --- | --- |
| | | |
A referência externa mais útil é Postmortem Culture do Google SRE.
Leituras e CTA
Leia também boas práticas de segurança, guia de permissões, guia de custos de API e workflow de verificação.
Se você trabalha sozinho, comece pela cheatsheet gratuita. Para modelos reutilizáveis, veja produtos ClaudeCodeLab. Para equipes, treinamento e consultoria Claude Code ajuda a organizar CLAUDE.md, permissões, hooks, revisão e simulados.
Ao testar estes modelos em exercícios do ClaudeCodeLab, a maior melhoria foi escrever a contenção antes do diagnóstico. Validar JSON, Bash e Node antes de publicar também removeu erros simples. Um ensaio de 20 minutos mostra alertas ausentes, backups não testados e permissões amplas demais.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Como pedir ao Claude Code para mexer em um único arquivo
Do desastre em que um 'deixa melhor' alterou 40 linhas nasceu um template de prompt que limita o escopo, valida e permite reverter.
Recuperar de negações de permissão no Claude Code sem enfraquecer guardrails
Transforme um comando negado em plano seguro com motivo, alternativa, provas e critérios de nova tentativa.
Claude Code Harness Smoke Test: prova de 15 minutos antes de confiar em um agente
Um smoke test para escopo, áreas bloqueadas, comandos de prova, URL pública e CTAs de receita no Claude Code.