Vínculos, listas restritivas e processos
Vínculos, listas restritivas e processos
Seis módulos de compliance aprofundam o screening além do titular: pep_parentes (parentes de pessoa exposta politicamente), impedidos_vinculos (vínculo familiar com impedido de apostar, a fase 2 da Lei 14.790/2023, Art. 26), pep_lista_restritiva (listas restritivas), antecedentes_estaduais, processos_judiciais e scr_bacen (retrato de endividamento no SCR). Todos partem do CPF lido do documento, e exigem Documento, Face Match e Liveness no mesmo flow pela mesma razão do pep_sancoes: nada aqui é consultado a partir de um número digitado. A consulta à fonte é pelo CPF; o nome só entra no impedidos_vinculos, e ainda assim como nome do parente, dentro do nosso motor local de vedação.
Venda pausada hoje, os seis. Eles aparecem na tabela de preços e no GET /v1/capabilities com preço e status coming_soon, e não podem ser ligados num flow enquanto a credencial do fornecedor não existir na conta. O estado vem do catálogo vivo, e esta página acompanha. O payload abaixo é o contrato que já está implementado e que passa a valer no dia da abertura.
flagged nestes módulos. Quando a fonte não é chamada (credencial ausente, portão de identidade fechado, consulta adiada), o check sai pending e ainda assim traz data, preenchido com os valores neutros: flagged: false, matched_by: "none", aggregates: null e o bloco da fonte null. Isso é "não perguntamos", e é indistinguível de "nada consta" se você olhar só a flag. Ramifique por outcome primeiro, sempre.Outro campo que promete mais do que entrega: nestes módulos matched_by: "document" é derivado de flagged, não é a prova de que o casamento se deu por CPF. Ele diz "houve resultado", e não "casou pelo documento". A única exceção é o impedidos_vinculos, onde ele é medido de verdade e distingue document, document_partial e name. E ele nem existe em dois dos seis: antecedentes_estaduais e scr_bacen não emitem a chave. Onde ela aparece fora do impedidos_vinculos, trate-a como sinônimo de flagged.
// pep_parentes: parente PEP encontrado. "parentes" é o dossiê da fonte passando por nós.
{ "module": "pep_parentes", "passed": false, "outcome": "failed", "score": 40,
"data": { "flagged": true,
"matched_by": "document", // derivado de flagged, NÃO é prova de match por CPF
"reason": null,
"parentes": { "parentescosPEP": [
{ "nome": "MARIA SILVA", "cpf": "***456789**", "grauParentesco": "MAE",
"pep": { "nome": "JOSE SILVA", "funcao": "DEPUTADO FEDERAL",
"orgao": "CAMARA MOCK", "nivel": "FEDERAL" } } ] } } }
// pep_lista_restritiva: o bloco "listas" é a resposta da fonte, como ela manda.
{ "module": "pep_lista_restritiva", "passed": false, "outcome": "failed", "score": 40,
"data": { "flagged": true, "matched_by": "document",
"listas": { "listas": [ { "lista": "LISTA RESTRITIVA MOCK", "nome": "JOAO SILVA",
"origem": "MOCK", "dataInclusao": "2025-03-01" } ] } } }
// antecedentes_estaduais: repare no tri-estado de "nada_consta" e na cobertura FIXA de UFs.
{ "module": "antecedentes_estaduais", "passed": false, "outcome": "failed", "score": 40,
"data": { "nada_consta": false, // true | false | null. null = a fonte NÃO afirmou nada.
"flagged": true,
"cobertura_uf": ["CE", "MG", "MT", "RS"], // as UFs cobertas hoje, e só elas
"antecedentes": { "nadaConsta": false,
"ocorrencias": [ { "uf": "MG", "tribunal": "TJMG",
"classe": "Acao Penal", "ano": 2024 } ] } } }
// processos_judiciais: "encontrados" é contado por nós sobre a resposta, não é campo da fonte.
{ "module": "processos_judiciais", "passed": false, "outcome": "failed", "score": 40,
"data": { "flagged": true, "matched_by": "document", "encontrados": 2,
"processos": { "totalProcessos": 2,
"processos": [ { "numero": "0001234-56.2024.8.13.0000",
"tribunal": "TJMG", "classe": "Execucao de Titulo",
"polo": "passivo", "status": "ativo" } ] } } }
// scr_bacen: INFORMACIONAL. O dossiê é o produto, e "flagged" é sempre false.
{ "module": "scr_bacen", "passed": true, "outcome": "approved", "score": 100,
"data": { "flagged": false,
"scr": { "dataBase": "2026-07", "quantidadeInstituicoes": 1,
"quantidadeOperacoes": 2,
"carteira": { "vencido": 0, "aVencer": 8765.43 } } } }Duas leituras que evitam conclusão errada. nada_consta, no antecedentes_estaduais, tem três estados e não dois: false quando há ocorrência, true só quando a fonte afirma que nada consta, e null quando não houve ocorrência e a fonte também não afirmou nada. Campo ausente na resposta nunca vira atestado nosso. E scr_bacen.flagged é sempre false, por construção: o módulo é informacional, o produto dele é o retrato de endividamento, e não existe caminho no código que o marque. Não escreva alerta em cima dessa flag.
O impedidos_vinculos é o mais denso dos seis, porque ele precisa provar duas coberturas ao mesmo tempo: de onde veio o grafo familiar (graph_coverage, hoje sempre "pep_relatives", ou seja a fonte de parentesco de PEP e mais nada) e quais bases de vedação sustentaram a triagem de cada parente (coverage e dataset_versions, as mesmas do módulo Impedidos de apostar). E ele conta os parentes de forma auditável: relatives_total é quanto a fonte devolveu, relatives_screened é quanto o motor de fato respondeu, e relatives_unscreened agrupa por motivo quem ficou de fora. Essa lista tem vocabulário fechado de seis valores: degree_unknown, degree_out_of_scope, document_missing, name_missing, screening_indeterminate e over_cap. Repare que relatives_total menos relatives_screened não é o tamanho dessa lista: ela é agrupada, e cada item traz o próprio count.
// impedidos_vinculos: parente de 1o grau na base de impedidos -> review COM evidência
{ "module": "impedidos_vinculos", "passed": false, "outcome": "failed", "score": 40,
"data": { "is_restricted": true, "flagged": true,
"matched_by": "name", // aqui ele é MEDIDO: document | document_partial | name
"reason": "family_link_restricted",
"restrictions": [ { "type": "vinculo_familiar_1g", "link_level": 1, "sport": null,
"entity": null, "source": "ptransp_servidores_reg",
"matched_by": "name",
"similarity": 91, // 0..100, NÃO 0..1
"listed_at": null, "left_at": null,
"birth_date_mismatch": false,
"entry_ref": "ptransp_servidores_reg:e_a8954835" } ],
"restrictions_total": 1, "restrictions_truncated": false,
"aggregates": { "is_restricted": true,
"restriction_types": ["vinculo_familiar_1g"],
"strongest_match": "name" },
"graph_coverage": "pep_relatives",
"relatives_total": 2, "relatives_screened": 2, "relatives_unscreened": [],
"coverage": ["ptransp_servidores_reg"], "coverage_degraded": [],
"dataset_versions": { "ptransp_servidores_reg": { "ingested_at": "2026-09-01T03:00:00Z",
"age_hours": 4, "stale": false,
"disabled": false },
"cbf_bid": { "ingested_at": null, "age_hours": null,
"stale": false, "disabled": true },
"cbf_arbitros": { "ingested_at": null, "age_hours": null,
"stale": false, "disabled": true } },
"name_source": "ocr" } }
// o caminho que MAIS importa: o parente existe e NÃO foi rastreável.
// Não é "nada consta": é "não deu para perguntar", e a contagem diz por quê.
{ "module": "impedidos_vinculos", "passed": null, "outcome": "pending", "score": 0,
"data": { "is_restricted": false, "flagged": false, "matched_by": "none",
"reason": "relatives_unscreenable",
"restrictions": [], "restrictions_total": 0, "restrictions_truncated": false,
"aggregates": null,
"graph_coverage": "pep_relatives",
"relatives_total": 1, "relatives_screened": 0,
"relatives_unscreened": [ { "reason": "degree_unknown", "count": 1 } ],
// vazios porque o motor local NEM FOI CHAMADO: sem grau de parentesco não há o
// que triar, então não há cobertura a declarar. Não confunda com base vencida.
"coverage": [], "coverage_degraded": [], "dataset_versions": null,
"name_source": null } } // null porque nem chegamos a usar um nomeNenhum dos seis reprova sozinho, pela mesma regra do pep_sancoes: um resultado é candidato, vai para review com a evidência no webhook, e a sua análise decide. E vale a mesma minimização: o que sai do impedidos_vinculos sobre o parente é contagem e restrição minimizada, nunca nome, CPF ou datas de terceiro. O nome e o documento do parente entram na consulta e morrem lá.
88 (hit) e 77 (indeterminado, só no impedidos_vinculos) escolhem o dado, mas o outcome continua vindo da tabela universal do sandbox, onde só 00, 01 e 02 mudam o desfecho. Ou seja: em sandbox você vê outcome: "approved" com flagged: true. Em produção o mesmo hit sai failed e a verificação vai a revisão. Use os sufixos para exercitar o parser, e 02 para exercitar o desfecho.Pronto para integrar? A chave de sandbox sai no painel, logo depois do cadastro. Criar conta grátis