Checagem de Risco
Diligência em lote com PySpark
Problema
Antes de fechar negócio com um fornecedor, cliente ou terceiro, uma empresa precisa avaliar risco de compliance — mas os dados relevantes estão espalhados entre fontes públicas heterogêneas, mais uma checagem de reputação em mídia que não vem de nenhuma fonte estruturada. Rodar isso contraparte por contraparte não escala quando é preciso reavaliar uma carteira inteira de uma vez.
Stack
- PySpark
- Python
- YAML
- TypeScript
- Zod
- TanStack Start
Demo
Uma checagem individual, rodando de verdade
O pipeline PySpark abaixo é para lote (uma carteira inteira de contrapartes). Esta caixa é uma versão simplificada — uma contraparte por vez, sem Spark — usando apenas a BrasilAPI como fonte, exatamente para você conferir o resultado real de uma consulta, não uma simulação. Construída em TypeScript (TanStack Start + Zod), com 39 testes Vitest cobrindo validação de CNPJ, curadoria do dossiê, avaliação de regras e o cache de resultado — código em src/lib/risk-check-*.ts na raiz do repositório (fora de showcases/, por ser parte do próprio app).
Demo ao vivo
Digite um CNPJ real — a análise roda de verdade, contra a BrasilAPI
Escala
Por que PySpark, e não um script sequencial
Consultar uma contraparte por vez é aceitável para uma análise pontual, mas não escala para revisar uma carteira inteira periodicamente. O lote é distribuído entre partições do Spark, e a consulta a cada fonte roda em paralelo por partição — reaproveitando a mesma conexão HTTP para todas as linhas de uma partição, em vez de abrir uma conexão por linha.
Fontes
Sinais normalizados, venham de onde vierem
Fontes estruturadas
Cada fonte pública tem seu próprio formato e modo de falha:
- Paralelizadas via mapPartitions, não um loop sequencial
- Falha parcial não derruba as demais fontes
Checagem de mídia própria
Não é um bureau: varre a web por menções à contraparte e sinaliza correspondências contra uma lista configurável de palavras-chave. A intensidade do sinal é proporcional ao número de artigos corroborantes — uma menção isolada pesa menos que três reportagens independentes sobre o mesmo assunto.
Schema único de sinal
Fonte estruturada e checagem de mídia emitem o mesmo formato de sinal — o motor de regras nunca precisa saber de onde um sinal veio.
Regras como configuração
Veto automático separado de score ponderado — em YAML no pipeline PySpark (rules_config.example.yaml), em um objeto TypeScript comentado na demo acima (risk-check-rules.ts). Reponderar uma regra é mudança de configuração, não de lógica.
Resultado
Dossiê final: uma tabela, não um documento
A saída do pipeline é uma tabela pronta para um data warehouse ou dashboard de BI, sem exigir parsing de um documento para reaproveitar o resultado em outro sistema.
document_id string
score double -- 0 a 1
flagged_rules array<string>
recommendation string -- approve | manual_review | reject
generated_at timestamp
rule_version stringTestabilidade
Lógica de negócio testável sem cluster
Cada módulo separa a lógica pura (retry, normalização de texto, avaliação de regras) da integração com Spark (`mapPartitions`, `DataFrame`, UDFs) — a primeira nunca importa PySpark. Resultado: 29 testes cobrindo cada decisão de negócio (o que conta como "não encontrado" vs. "fonte fora do ar", saturação da intensidade de mídia, veto vs. score ponderado) rodam com pytest puro, em segundos, sem precisar subir Spark nem Java.
Arquitetura
Do lote ao dossiê
Tecnologias
- PySpark
- Python
- YAML
- TypeScript
- Zod
- TanStack Start