Andrade Systems
Todos os sistemas
BetaOpen source

REPBrasil

Cada dado exibido mantém sua origem e cadeia de transformação.

Civic Tech · Engenharia de dados · Open source

Beta
Status
AGPL-3.0
Licença
Aberto
Código
Ver o código no GitHub

Visão geral

O que este sistema resolve

REPBrasil reúne dados públicos oficiais sobre políticos brasileiros e os apresenta de forma navegável. O código é aberto sob AGPL-3.0.

O foco técnico do projeto é manter a proveniência verificável de cada dado exibido: de que fonte veio, de qual arquivo daquela fonte, por quais transformações passou e com que grau de certeza aquilo pode ser afirmado. Numa plataforma que fala sobre pessoas públicas, essa é a diferença entre um site e uma base auditável.

O desafio

O que tornava o problema difícil

Estes são os pontos que mais influenciaram a arquitetura.

  • Fonte pública é hostil

    Codificação legada, nome grafado de formas diferentes na mesma base, arquivo que muda de layout entre anos, e nenhum identificador estável que atravesse bases distintas. O trabalho de dados aqui é quase todo de normalização.

  • O pareamento é onde a plataforma pode mentir

    Ligar o registro do TSE ao da Câmara sem chave comum obriga a parear por nome. Dois políticos homônimos existem, e atribuir o mandato de um ao outro não é um dado impreciso — é uma afirmação falsa sobre uma pessoa identificada.

  • Afirmar sobre pessoa pública exige poder mostrar a origem

    Se alguém contesta um número exibido, a resposta não pode ser "veio da base oficial". Precisa ser qual base, qual arquivo, coletado quando, transformado como.

  • Nem tudo que se sabe tem a mesma força

    Um valor lido diretamente da declaração de bens e uma relação inferida por semelhança de nome não são a mesma coisa. Apresentar as duas com a mesma aparência é desonesto, mesmo quando ambas estão certas.

Escopo

Implementado e planejado

A lista acima é roteiro, e está aqui exatamente para não ser confundida com o que já funciona. Itens planejados aparecem separados do que já funciona no beta.

Implementado

  • Ingestão do TSE: candidatos, resultados de eleição e declarações de bens
  • Ingestão da Câmara dos Deputados: deputados e mandatos
  • Pareamento conservador entre TSE e Câmara por normalização de nome
  • Modelo de proveniência: evidência, cadeia de transformação e passos com hash de entrada e saída
  • API de consulta de políticos, mandatos, bens e resultados eleitorais
  • Interface de busca, listagem e perfil

Planejado — não implementado

  • Grafo de conexões em banco de grafo — existe como esquema documentado e consultas de referência, sem banco em operação
  • Ingestão de CGU, CNJ e SIAPE — as entidades de domínio existem no modelo, os pipelines não foram escritos
  • Score público explicável — modelo de dados presente, cálculo não implementado
  • Contestação pública de evidência — o estado existe na entidade, o fluxo não

Arquitetura

Como o sistema é montado

Ingestão

Python · Polars · Pydantic

Pipelines por fonte, com coleta, transformação e carga separadas e testadas isoladamente.

Domínio

.NET 8 · Clean Architecture

Entidades de política, mandato, bem, evidência e proveniência.

Dados

PostgreSQL

Metadados livres em JSONB ao lado dos campos tipados.

API

ASP.NET Core

Consultas de leitura organizadas por área.

Frontend

Next.js · TypeScript

Busca, listagem e perfil de político.

Infraestrutura local

Docker Compose

Um comando sobe o ambiente completo, para que qualquer pessoa possa reproduzir.

A cadeia de proveniência de um dadoO dado sai de um arquivo publicado pela fonte oficial e atravessa uma cadeia ordenada de transformações — extração, normalização, pareamento e derivação — com hash de entrada e de saída em cada passo. O resultado é uma evidência que carrega tipo e grau de certeza, e é a evidência, não o valor solto, que sustenta o que aparece na tela.Fonte oficialarquivo publicado, com hashCadeia de transformação1. extração2. normalização3. pareamento4. derivaçãohash de entrada e de saída em cada passoEvidênciatipo + grau de certezaDado exibido
A proveniência não é um campo de texto dizendo "fonte: TSE". É uma cadeia: cada dado aponta para uma evidência, que aponta para a fonte e para a sequência ordenada de transformações que a produziu — com hash de entrada e de saída em cada passo.

Decisões de engenharia

Decisões e trade-offs

Cada decisão registra a justificativa e o trade-off aceito.

  1. Proveniência como entidade própria

    Uma coluna "fonte" responde de onde veio, mas não como chegou naquele formato. Com evidência, cadeia e passos como entidades próprias, "o dado mudou" e "o pipeline mudou" viram perguntas distintas e respondíveis.

    Custo aceito · Cada carga escreve consideravelmente mais do que os fatos em si. É o preço de poder responder a uma contestação sem reprocessar tudo às cegas.

  2. Grau de certeza explícito

    Descartar tudo que não é perfeito deixaria a plataforma quase vazia; aceitar tudo como fato a tornaria irresponsável. A escala de certeza permite ingerir o imperfeito sem transformá-lo em afirmação categórica — hipótese não é exibida, conflito é exibido com aviso.

    Custo aceito · A interface precisa saber comunicar a diferença, e isso é mais difícil do que mostrar um número.

  3. Pareamento conservador entre fontes

    Falso negativo é um perfil incompleto; falso positivo é uma acusação contra a pessoa errada. Os dois erros não custam a mesma coisa, então a regra de pareamento é deliberadamente conservadora.

    Custo aceito · Perfis ficam menos completos do que poderiam. Aceito sem hesitação, dado o domínio.

  4. AGPL-3.0

    Uma plataforma de transparência que pode ser transformada em serviço fechado por um terceiro perde o próprio argumento. A licença obriga quem roda uma versão modificada como serviço a publicar as modificações.

    Custo aceito · Afasta uso comercial fechado. É o objetivo.

Por dentro da engenharia

Os problemas em detalhe

Cada bloco abre com o problema, mostra a solução e explica por que ela foi escolhida. Expanda o que interessar.

Proveniência como entidade de primeira classe

Problema

Numa plataforma que afirma coisas sobre pessoas identificadas, "de onde veio esse dado" não pode ser uma nota de rodapé. Quando alguém contesta um número, a resposta precisa ser reproduzível por outra pessoa, sem acesso ao ambiente de quem o produziu.

Solução

Cada dado exibido aponta para uma evidência. A evidência aponta para a fonte, para o identificador do dataset específico, para o hash do valor bruto, para a data em que o fato foi observado e para a data em que foi coletado — que são campos diferentes de propósito. E aponta para uma cadeia de transformação: a sequência ordenada dos passos que a produziram, cada um com tipo, parâmetros de configuração, hash da entrada e hash da saída.

Por que foi feito assim

Com hash em cada passo, é possível distinguir duas situações que parecem iguais de fora: a fonte publicou um dado diferente, ou o nosso pipeline passou a transformar de outro jeito. Sem isso, qualquer divergência vira discussão sem árbitro. Separar a data de observação da data de coleta é o mesmo princípio: um bem declarado em 2022 e coletado em 2026 não pode ser apresentado como situação atual.

Evidência tipada e grau de certeza

Problema

Um valor lido diretamente da declaração oficial e uma relação inferida por semelhança de nome não têm a mesma força. Guardá-los na mesma tabela sem distinção faz com que a plataforma perca a capacidade de dizer o quanto acredita no que exibe.

Solução

A evidência carrega tipo — primária, derivada ou documental — e um grau de certeza numa escala explícita, que vai de fato confirmado a conflito entre fontes, passando por vínculo documental e relação indireta. Testemunho é proibido como tipo. Hipótese existe na escala mas não é exibida publicamente; conflito é exibido com aviso, em vez de a plataforma escolher um lado.

Por que foi feito assim

Marcar conflito em vez de resolver silenciosamente preserva o que as fontes realmente dizem — que é o compromisso central do projeto. E proibir testemunho como tipo é uma decisão de escopo escrita no modelo: a plataforma trabalha com documento, não com relato.

Pareamento conservador entre fontes

Problema

O TSE e a Câmara identificam a mesma pessoa por chaves diferentes e sem correspondência publicada. Parear por nome é a única opção — e é onde a plataforma pode produzir a pior espécie de erro: atribuir a alguém um mandato que não é seu.

Solução

Normalização de nome seguida de regra deliberadamente restritiva, que prefere não parear a parear com dúvida. O vínculo criado é registrado como evidência derivada, e não como fato primário, com a cadeia de transformação que o produziu.

Por que foi feito assim

Marcar o vínculo como derivado é o que impede que uma inferência vire, três consultas depois, um fato indistinguível dos que vieram da fonte. A regra conservadora e a marcação são a mesma decisão vista de dois ângulos: a plataforma assume o custo de estar incompleta para não assumir o de estar errada.

Qualidade

O que os testes protegem

Os testes se concentram na camada de ingestão, que é onde este projeto erra. Não testam se o servidor responde — testam se o arquivo real da fonte é lido corretamente, com a codificação certa, e se o pareamento recusa o caso ambíguo.

  • A leitura dos arquivos do TSE de candidatos, resultados e bens
  • A normalização de nome e o comportamento conservador do pareamento
  • O cliente paginado da API da Câmara
  • O registro de fonte junto com o dado ingerido

Stack

Stack do projeto

O sistema em números

21
Entidades de domínio
74
Testes de ingestão
2 (TSE e Câmara dos Deputados)
Fontes integradas
12
Migrations

conferido no repositório em 27/08/2026

Status

Beta

Ingestão

Python 3.12PolarsPydanticuv

Backend

.NET 8C#Clean Architecture

Dados

PostgreSQLJSONB

Frontend

Next.jsTypeScriptTailwind

Infraestrutura

Docker Compose

Próximo sistema

Sistema de Gestão de Precatórios

Rateio, pagamento e auditoria de precatórios com precisão centesimal.

Produção