← story.propek
STORY 9.8
LGPD Exclusao de Dados Pessoais
Epic: Epic 9 — CRM Database Foundation
DONE
ACCEPTANCE CRITERIA (51/51)
AC1.1: Script em `apps/crm/scripts/lgpd-delete.js` executavel via `node apps/crm/scripts/lgpd-delete.js --customer-id {id}`
AC1.2: Le connection string do banco de variaveis de ambiente
AC1.3: Aceita flags CLI: `--customer-id {id}`, `--admin-token {token}`, `--confirm`, `--dry-run`, `--verbose`, `--help`
AC1.4: Mostra help com `--help`
AC1.5: `--customer-id` e OBRIGATORIO — script aborta sem ele
AC2.1: Flag `--admin-token {token}` e OBRIGATORIA para executar a exclusao
AC2.2: Token admin armazenado como variavel de ambiente `LGPD_ADMIN_TOKEN` no servidor
AC2.3: Script compara token fornecido com `LGPD_ADMIN_TOKEN` — se diferente, recusa com: "Exclusao requer autorizacao do administrador. Token invalido."
AC2.4: Sem `--admin-token`, script recusa com: "Exclusao requer autorizacao do administrador. Use --admin-token {token}"
AC2.5: Toda tentativa de exclusao (aprovada OU recusada) e registrada no `crm_audit_log` com timestamp, customer_id, resultado (approved/denied), e IP
AC2.6: Token NUNCA e logado ou exibido no terminal (mascarado como `***...***`)
AC3.1: Campos anonimizados na tabela `customers`:
AC3.2: Campo `metadata` atualizado: adicionar `{"lgpd_deleted": true, "lgpd_deleted_at": "ISO_TIMESTAMP", "lgpd_deleted_by": "admin"}`
AC3.3: Campos NAO anonimizados (mantidos para estatisticas): `id`, `customer_type`, `created_at`, `updated_at`, `metadata` (exceto dados pessoais dentro do JSONB)
AC3.4: Dentro de `metadata`, remover: `kommo_id`, `kommo_fields` (dados pessoais do Kommo)
AC3.5: phone_number placeholder usa formato `+00000{customer_id}` para manter UNIQUE constraint
AC4.1: Tabela `deals`: manter deals do customer, mas NAO anonimizar (deals nao tem dados pessoais diretos — apenas customer_id como FK)
AC4.2: Tabela `deal_stage_log`: manter intacto (nao tem dados pessoais)
AC4.3: Tabela `follow_ups_crm`: anonimizar campo `notes` onde mencionar dados pessoais → substituir por `'[LGPD REMOVED]'`
AC4.4: Tabela `attendant_notes`: anonimizar campo `note_text` → substituir por `'[LGPD REMOVED]'`
AC4.5: Tabela `conversations` (bot): marcar `metadata` com `lgpd_deleted: true` (NAO deletar conversas — bot precisa do historico de contexto)
AC4.6: Tabela `messages` (bot): NAO anonimizar individualmente (volume alto, baixo risco — mensagens ja sao efemeras)
AC5.1: Sem `--confirm`, script mostra o que SERIA anonimizado e para (modo preview)
AC5.2: Preview mostra: nome do cliente, numero de deals associados, numero de follow-ups, numero de notas
AC5.3: Com `--confirm`, executa a anonimizacao
AC5.4: Confirmacao adicional no terminal: "Tem certeza que deseja anonimizar os dados de {nome}? (y/N)"
AC5.5: Apos execucao, exibe resumo: campos anonimizados, tabelas afetadas, audit log entry ID
AC6.1: Com `--dry-run`, script NAO escreve no banco
AC6.2: Dry-run mostra exatamente o que seria anonimizado em cada tabela
AC6.3: Dry-run NAO requer `--admin-token` (apenas visualizacao)
AC6.4: Dry-run gera relatorio em `apps/crm/data/lgpd-delete-dryrun-{timestamp}.md`
AC7.1: Toda exclusao registrada em `crm_audit_log` com action = 'LGPD_DELETE'
AC7.2: `old_values` contem snapshot dos dados pessoais ANTES da anonimizacao (para auditoria interna)
AC7.3: `new_values` contem os valores anonimizados
AC7.4: `changed_by` = 'admin:lgpd_delete'
AC7.5: Tentativas negadas (token invalido) tambem registradas com action = 'LGPD_DELETE_DENIED'
AC8.1: Criar coluna `lgpd_consent_at` em `customers` (se nao existir) — TIMESTAMP, nullable
AC8.2: Criar coluna `lgpd_consent_source` em `customers` (se nao existir) — VARCHAR(50), nullable (valores: 'whatsapp_bot', 'crm_manual', 'import')
AC8.3: Para clientes importados do Kommo: `lgpd_consent_source = 'import'`, `lgpd_consent_at = NOW()` (consentimento implicito pela relacao comercial pre-existente)
AC8.4: Migration SQL para adicionar colunas e atualizar registros existentes
AC8.5: Script de exclusao verifica se `lgpd_consent_at` existe antes de prosseguir (warning se NULL)
AC9.1: Usa parameterized queries ($1, $2) — NUNCA interpolacao SQL
AC9.2: Usa `crm_user` para conexao ao banco
AC9.3: Bot WhatsApp continua operando durante exclusao
AC9.4: Zero dependencias externas alem de Node.js stdlib + pg
AC9.5: Token admin NUNCA logado ou exibido
AC9.6: Operacao e atomica (transacao SQL) — se falhar em qualquer ponto, rollback total
AC10.1: Log estruturado em stdout: `[TIMESTAMP] [LEVEL] mensagem`
AC10.2: Relatorio de exclusao salvo em `apps/crm/data/lgpd-delete-report-{timestamp}.md`
AC10.3: Relatorio inclui: customer_id, dados anonimizados, tabelas afetadas, audit log entry, timestamp
AC10.4: Relatorio NAO inclui os dados pessoais originais (seguranca)
TIMELINE
25/03/2026
feat: CRM Phase 3 — Kommo Sync + LGPD Exclusion [Story 9.7, 9.8] [Story 6.1-sales-intelligence-bot]
351a453
ARQUIVOS (4)
apps/crm/scripts/lgpd-delete.js CREATE
apps/crm/migrations/029_lgpd_consent_columns.sql CREATE
apps/crm/data/lgpd-delete-report-*.md CREATE
docs/stories/active/story-9.8-lgpd-exclusao.md UPDATE
RETROSPECTIVA
Qualidade: ★★★☆☆
Incluir @qa no proximo ciclo
Rodar @cyber-chief antes do push