Checagem de Risco e Crédito
ETL de métricas de compliance e crédito para dentro do ERP e do CRM
Problema
Quem aprova ou bloqueia uma contraparte é o time de compras, crédito ou comercial. Esse time não trabalha dentro de uma ferramenta de compliance; trabalha dentro do ERP e do CRM. O dado de risco, porém, vive fora: bureaus por API REST, provedores expostos como servidores MCP, e checagem de reputação em mídia sem fonte estruturada. Este pipeline é o ETL que fecha esse vão: extrai das fontes, aplica regras de compliance e modelos de crédito, e carrega o resultado como atributos de risco no cadastro que o negócio já usa, para uma carteira inteira de uma vez.
Stack
- PySpark
- Python
- Pandas
- MCP
- REST
- pytest
Posicionamento
Análise que chega onde o analista trabalha
A saída não é um PDF que alguém precisa abrir. O pipeline grava atributos tipados (situação, faixa de risco, score de crédito, regras sinalizadas) diretamente no cadastro do fornecedor no ERP ou da conta do cliente no CRM. O analista vê BLOQUEADO, EM_ANÁLISE ou LIBERADO na mesma tela de sempre, sem trocar de sistema e sem pedir parecer por e-mail.
Extract: REST + MCP na mesma camada
Bureaus tradicionais entram por HTTP, e provedores que publicam servidores MCP entram por tools/call, com o Accept de Streamable HTTP que o SDK oficial exige (sem ele, 406). As duas fontes implementam o mesmo protocolo RiskDataSource, e a regra nunca sabe de onde veio o dado.
Transform: regras por campo + crédito
Motor de compliance declarativo (veto ou score ponderado) sobre campos concretos do bureau, mais os 4 modelos de crédito embarcados na camada de cliente. Compliance e crédito compõem um score único, com limiar independente para risco de crédito extremo.
Load: upsert idempotente
Cada registro carrega um payload_hash do conteúdo de negócio, sem o timestamp. Reprocessar a carteira sem mudança de dado nem de versão de regra grava zero linha: ERP costuma cobrar por chamada e disparar workflow a cada escrita.
Métricas junto da decisão
Taxa de reprovação, veto, distribuição de recomendação, score médio de crédito e top regras sinalizadas saem do mesmo pipeline. Recalcular isso numa camada de BI separada cria duas implementações da mesma regra, e num comitê de risco a divergência derruba a credibilidade do número inteiro.
Fontes
Precedência declarada e procedência por campo
Em due diligence é normal ter duas fontes para o mesmo campo: um bureau tem o processo judicial, outro tem a situação cadastral mais atualizada. A ordem das fontes é a política de confiança, escrita no ponto de configuração e não escondida num if. Cada valor do registro final guarda de qual fonte veio, então "por que essa contraparte foi reprovada" vira uma coluna da tabela de saída, não uma arqueologia de log de rede. Fonte que falha entra em fontes_com_falha e as demais seguem: perder um enriquecimento opcional não é o mesmo que perder a análise.
fontes = [
RestBureauSource(
nome="bureau_cadastral",
base_url=BUREAU_URL,
transport=http_json,
field_map={"cad_situacao": "situacao_cadastral", ...},
),
McpToolSource(
nome="mcp_sancoes",
server_url=MCP_URL,
tool_name="consultar_sancoes",
transport=http_json, # Accept: application/json, text/event-stream
field_map={"sanctioned": "possui_sancao_ativa"},
),
]
merged = coletar_de_fontes(documento, tipo_documento, fontes)
merged.field_provenance["situacao_cadastral"] # "bureau_cadastral"Sem nenhuma fonte respondendo, a situação cadastral fica DESCONHECIDA em vez de ATIVA, o que faz a regra de irregularidade disparar: ausência de dado não é ausência de risco.
Modelos de crédito
4 scorecards embarcados, com racional legível
Rodam na análise de cliente, que é onde existe exposição financeira. São determinísticos e não um modelo treinado por um motivo concreto: não há aqui uma base real de inadimplência rotulada, e um scorecard de pesos explícitos é a alternativa honesta a fabricar um dataset de treino que não existe. Cada modelo devolve, junto do score, o racional em texto que o analista lê para revisar a decisão.
| Modelo | Sinal | Peso |
|---|---|---|
| capacidade_pagamento | Dívida ativa sobre receita anualizada | 0.35 |
| comportamento_pagamento | Protestos e cheques sem fundo, saturando em 3 ocorrências | 0.35 |
| estabilidade_cadastral | Tempo de atividade e quadro societário | 0.15 |
| concentracao_setorial | Risco base do setor de atividade | 0.15 |
No score final do cliente, compliance pesa 0.4 e crédito 0.6. Só que 0.6 sozinho nunca alcança o limiar de rejeição (0.66), o que prenderia em revisão manual uma contraparte com os 4 modelos no teto. Por isso existe um limiar independente: crédito isolado acima de 0.85 rejeita sozinho, exatamente como um veto de compliance.
Regras
KYS, KYE, KYC: mesma engine, escopos diferentes
KYS · Fornecedor
Escopo mais amplo: compliance por campo (sanção, mandado de prisão, processo criminal, situação cadastral, sócios, dívida ativa) e checagem de mídia nas 6 categorias da taxonomia. Não roda crédito: o risco de fornecedor aqui é reputacional, não de inadimplência.
KYE · Colaborador
Compliance restrito a processos, mandado de prisão e histórico trabalhista, com mídia num escopo pessoal (envolvimento criminal, crime organizado, fraude). Sem sanção internacional ou cartel, que não se aplicam a uma pessoa física candidata.
KYC · Cliente
Compliance básico (sanção, situação cadastral, dívida ativa), mídia em 2 categorias essenciais e os 4 modelos de crédito por cima. Único conjunto de regras com camada de crédito.
Regra é dado, não código
Os 3 conjuntos não são 3 pipelines: são 3 valores de RiskAnalysisRules (lista de regras, escopo de mídia, usa crédito ou não) interpretados pelo mesmo motor. Um 4º conjunto é uma nova composição, não lógica nova.
Checagem de mídia
Nome da contraparte mais termos por categoria de risco
Não é um bureau: monta buscas por nome da contraparte e palavras-chave agrupadas em 6 categorias de risco (corrupção, lavagem de dinheiro, fraude, envolvimento criminal, sanções, crime organizado), 5 grupos de termos cada. A intensidade satura a partir de 3 artigos corroborantes, porque uma menção isolada não pesa como três reportagens independentes. Categorias de maior severidade viram veto automático; as demais contribuem ponderadamente.
"Fornecedor Exemplo LTDA" ("corrupção" OR "suborno" OR "propina" OR
"peculato" OR "improbidade" OR "desvio de verbas")Carga
Contrato de campos do ERP e do CRM
O mapeamento é um dicionário único e explícito: é ele que o time de integração lê quando pergunta qual campo do CRM recebe o quê. Adicionar uma regra ao motor não altera o contrato. Campo ausente é omitido em vez de virar nulo, porque KYS e KYE não rodam crédito e enviar null apagaria o score gravado por uma análise de cliente anterior da mesma contraparte.
risco_documento 12345678000199
risco_tipo_pessoa PJ
risco_status BLOQUEADO -- LIBERADO | EM_ANALISE | BLOQUEADO
risco_faixa ALTO -- BAIXO | MEDIO | ALTO
risco_score 0.91
risco_score_credito 0.88
risco_regras_sinalizadas ["sancao_ativa", "divida_ativa_registrada"]
risco_midia_categorias ["lavagem_dinheiro_crimes_financeiros"]
risco_origem_analise kyc
risco_versao_regras 1.0.0
risco_atualizado_em 2026-01-14T03:22:10Z
payload_hash sha256 do conteúdo de negócio, sem timestamp
-> reprocessar sem mudança grava 0 linhaA chave do delta inclui o conjunto de regras: a mesma empresa pode ser fornecedor e cliente ao mesmo tempo, e a carga de uma análise de cliente não pode suprimir a de fornecedor.
Escala
Por que PySpark, e não um script sequencial
Consultar uma contraparte por vez serve para uma análise pontual, não para reavaliar a carteira inteira periodicamente. O lote é distribuído entre partições via mapInPandas, que reaproveita a mesma sessão HTTP para todas as linhas de uma partição em vez de abrir uma conexão por linha. A escolha por mapInPandas em vez de rdd.mapPartitions veio de um erro real em compute serverless, que não expõe a API de RDD.
Testabilidade
Lógica de negócio testável sem cluster
Cada módulo separa a lógica pura (retry, avaliação de regra, agregação de mídia, scorecard de crédito, merge de fontes, hash de idempotência) da integração com Spark. A primeira nunca importa PySpark, e o transporte HTTP é injetável, então nem rede nem mock de rede entram nos testes. Resultado: 74 testes cobrindo cada decisão de negócio rodam com pytest puro em menos de 1 segundo, sem subir Spark nem Java.
Arquitetura
Da fonte ao cadastro no ERP
Tecnologias
- PySpark
- Python
- Pandas
- MCP
- REST
- pytest