Redaction de PII antes de enviar payload pra IA
Pipeline de redaction de PII (CPF, CNPJ, IBAN, email, cartão, DNI...) aplicado antes de enviar payload pra LLM.
Por que existe
Mesmo sendo a Anthropic um subprocessador declarado e com Zero Data Retention, minimizar o que sai daqui é defesa em profundidade: reduz risco em DPIA, contém vazamento se o LLM for comprometido, e dá auditoria por chamada.
Como funciona
A biblioteca
src/lib/ai/redaction.ts aplica regex + validações em todo string antes do prompt:- CPF (BR) — formato 000.000.000-00 ou cru
- CNPJ (BR) — formato 00.000.000/0000-00 ou cru
- CEP (BR) — 00000-000
- Telefone BR — (11) 99999-1234, +55 ...
- DNI/NIE (ES) — 12345678Z, X1234567L
- Telefone ES — +34 612 345 678
- IBAN — ES91…, DE89…, etc.
- Email — qualquer endereço RFC simplificado
- Cartão de crédito — 13 a 19 dígitos com validação Luhn (evita falso positivo em DOCNUMs)
PII detectada é substituída por tags como
[REDACTED:CPF], [REDACTED:EMAIL] — o modelo entende o tipo do dado sem ver o valor.Onde está aplicado
| Endpoint | O que é redacted |
|---|---|
POST /api/ai/diagnose | Payload completo de mensagem (NFe, IDoc, EDI, JSON) |
POST /api/mapeamentos/interpret-log | log.message, log.details (jsonb) e error_detail |
POST /api/mapeamentos/suggest-mapping | Lista de campos source + dest e descrições |
POST /api/mapeamentos/suggest-format | Query e contexto de mensagem |
POST /api/mapeamentos/create-message-type | Lista de campos source + dest e descrições |
paraphraseDescriptions (lib) | Descrições de campos antes de parafrasear |
Auditoria
Cada chamada loga os contadores em
ai_usage_events.metadata.pii_redaction. Exemplo:{
"pii_redaction": {
"cpf": 2, "cnpj": 1, "email": 3, "phone_br": 1,
"cep": 0, "phone_es": 0, "iban": 0,
"credit_card": 0, "dni_es": 0, "nie_es": 0
}
}
Pra ver no /admin: filtrar
ai_usage_events por feature e somar metadata.Limitações conhecidas
- Não cobre dados em outros idiomas/países (ex: SSN US, MyNumber JP). Adicionar conforme demanda.
- Não cobre nomes/endereços livres — esses são contextuais demais pra regex; o pipeline mantém esses dados intactos.
- Toggle por tenant/integração ainda não existe (item #54 do roadmap). Hoje o pipeline está sempre ligado.
Veja também
pipeline-mensagens-fluxos— fluxos do retry e DLQ (onde a IA é chamada também passa pela redaction)ai-toggle-hierarchy— desligar IA por scopecertificado-digital-mtls— mTLS pra SEFAZ e similares
Histórico de versões
- 1.3.0
A URL de origem gravada como evidência de cada leitura OData (message_raw_batches) passa a manter os parâmetros técnicos não sensíveis — filtro, ordenação, paginação, expansão, seleção de campos, contagem e língua pedida (sap-language) — em vez de cortar a query inteira. Busca livre ($search) e qualquer outro parâmetro (token, chave de API, assinatura) nunca são gravados; a lista de parâmetros fica num único lugar do código. Quando o lote é expurgado, a query sai junto. A URL gravada na entrega ao destino não muda.
26/09/2026 · updated
- v1.1.0
Redação de PII com UMA regra para tudo que o produto grava ou loga como texto de diagnóstico (#82). A regra que nasceu no logAppError (app_errors, v1.0) mudou para src/lib/privacy/redact-for-storage.ts e ficou mais completa: além de e-mail, CPF/CNPJ, CEP, telefone, IBAN, cartão e DNI/NIE, sai o VALOR de query de toda URL no meio do texto (senha/token em query), o valor de chave sensível da lista única em JSON ("email":"…") e XML (<password>…</password>), segredos em chave=valor (password=, api_key=, id_token=) e cabeçalhos (Authorization, Cookie, X-Api-Key) e a credencial de Bearer/Basic. Ficam códigos HTTP, nomes de campo e de parâmetro, segmentos e códigos de erro — o que o diagnóstico por IA e a classificação usam. Destinos: (1) messages.error_detail e messages.dest_status_text — ponto único redactMessageWrite em toda escrita da tabela, com catraca que lê o código (AST) e reprova escrita que possa carregar as colunas sem passar por ele; (2) audit_events.metadata — logAuditEvent aplica a regra de metadata do app_errors (chave sensível, URL, texto livre), também na notificação dos owners; a trilha é imutável, então só as entradas novas saem redigidas; (3) logs estruturados — o pino passou a redigir texto livre (hook logMethod: objeto, mensagem, Error.message/stack; withContext), com identificadores técnicos (*_id, docnum, step) crus. As mensagens antigas são redigidas no release por scripts/messages-redact-text.mts.
25/09/2026 · updated
- 1.2.0
app_errors redigido no ponto único; /api/log-error com lista fechada; linhas existentes redigidas (PR #1151, release #1158).
25/09/2026 · updated
- 1.1.0
Dois vazamentos reais fechados: o prompt de ranqueamento de conflitos mandava valor de mensagem de cliente cru, e o generate-insights mandava nome de tenant e de parceiros. Governança de pii_class na interface e aviso no editor de mapeamento. Pseudônimo injetivo por HMAC com chave por tenant, porque máscara determinística NÃO é injetiva e somaria clientes distintos numa linha. Itens #481, #587.
19/09/2026 · updated
- 1.0.0
Pipeline server-side de redaction de PII antes de enviar payload pra LLM. Regex+Luhn cobre CPF, CNPJ, CEP, email, telefone BR/ES, IBAN, cartão de crédito, DNI/NIE espanhol. Substituições com tags tipadas [REDACTED:CPF] etc; opção de hash determinístico. Aplicado em todos os 6 entry points Anthropic (diagnose, interpret-log, suggest-mapping, suggest-format, create-message-type, paraphrase-descriptions). Stats por chamada em ai_usage_events.metadata.pii_redaction. 19 testes vitest. Documentado em /security e /help.
05/05/2026 · new