← todos os projetos
/02Data Engineering · Risk & Compliance

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.

dossie (schema de saída)
document_id       string
score             double   -- 0 a 1
flagged_rules     array<string>
recommendation    string   -- approve | manual_review | reject
generated_at      timestamp
rule_version      string

Testabilidade

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ê

Lote de contrapartes
Fontes estruturadas + checagem de mídia (paralelo)
Sinais normalizados (schema único)
Regras configuráveis (veto + score)
Dossiê final (tabela)
O nome comercial real do produto foi omitido de propósito — esta é uma reformulação de portfólio sob uma ótica de processamento em lote.

Tecnologias

  • PySpark
  • Python
  • YAML
  • TypeScript
  • Zod
  • TanStack Start