Projeto aberto para baixar, processar e publicar dados públicos das empresas do Brasil.
src/ETL/Processor: ETL que baixa, processa e publica dados do CNPJ.src/ETL/Tests: testes do ETL.src/ETL/OpenCNPJ.sln: solution do ETL.src/Page: página/SPA estática para consulta dos dados publicados.src/Worker: Worker Cloudflare que lê shards publicados no R2.src/script: scripts operacionais, incluindo o deploy versionado do Worker.
.NET SDK 10.0+rcloneinstalado e autenticado no seu storage (ex.: Backblaze, R2, S3, Azure Storage, ...).bqinstalado e autenticado somente quandoBigQuery.Enabled=true.- Espaço em disco e boa conexão (a primeira execução pode levar tempo -- dias até).
- Ajuste
src/ETL/Processor/config.jsonse desejar mudar pastas locais, destino do storage, memória, paralelismo... - No
config.json, aponte para o Storage que deseja passando a configuração do rclone. - O downloader da Receita agora usa WebDAV no share público do SERPRO+/Nextcloud.
- A publicação no BigQuery fica desligada por padrão. Com
BigQuery.Enabled=falsee sem override, o pipeline apenas emite um aviso e segue sem exigirbqou credenciais Google. - Para habilitar BigQuery, configure
BigQuery.Enabled=trueouOPENCNPJ_BIGQUERY_ENABLED=true, além deDataset,TablePrefixopcional,Locationopcional eBqExecutablese o binário não forbq. O projeto pode vir deBigQuery.ProjectIdnoconfig.jsonou da envOPENCNPJ_BIGQUERY_PROJECT_ID; as envs têm prioridade. Em container,OPENCNPJ_GOOGLE_CREDENTIALS_BASE64pode receber a credencial Google codificada em base64 como secret do ambiente.
downloads/YYYY-MM: zips baixados da Receita.extracted_data/YYYY-MM: arquivos extraídos para o mês.parquet_data/YYYY-MM: Parquets gerados para o mês e Parquets mais recentes das integrações.parquet_data/YYYY-MM/bigquery/receita/part-*.parquet: Parquets colunares da Receita para BigQuery, com 1 linha por CNPJ.parquet_data/YYYY-MM/integrations/{cno,rntrc}/bigquery/*.parquet: Parquets colunares das integrações para BigQuery.cnpj_shards/YYYY-MM/releases/{release_id}/shards: shards locais*.ndjsone*.index.bindo release atual.
Os artefatos locais não são apagados automaticamente, exceto quando o pipeline é executado com --cleanup-on-success. Nesse modo, o cleanup remove downloads, CSVs extraídos e temporários, mas preserva Parquets e releases locais para permitir recomposição incremental.
- O ETL possui a interface interna
IDataIntegrationpara sub-módulos de dados. - Cada integração declara chave, propriedade JSON, frequência de atualização e versão de schema.
- O estado de hashes por CNPJ de cada integração é publicado via rclone em
files/integrations/state/{module}/hashes.json. - Integrações devem gerar Parquet canônico com 1 linha por CNPJ (
cnpj,cnpj_prefix,payload_json,content_hash, datas de origem/módulo) para API, shards e cálculo incremental. - Quando publicadas no BigQuery, as integrações com suporte dedicado geram um Parquet columnar separado, sem
payload_json. - O JSON final sempre inclui a chave das integrações habilitadas; quando o CNPJ não tiver dado naquela integração, o valor fica
null.
- Dentro de
src/ETL/Processor:dotnet run pipelinedotnet run pipeline -m YYYY-MM(opcional)dotnet run pipeline --release-id abc123...(opcional, força o release id remoto)dotnet run pipeline --cleanup-on-success(opcional, remove artefatos locais do dataset após sucesso)
Sem -m, o pipeline escolhe o mês mais recente publicado no share WebDAV da Receita.
Quando BigQuery.Enabled=true, o pipeline carrega 1 tabela por módulo: receita, cno, rntrc e futuras integrações que publiquem um Parquet canônico. receita, cno e rntrc são carregadas a partir de Parquets colunares, sem payload_json. A carga acontece após shards/ZIPs serem gerados e antes do info.json e do estado de integração serem publicados, para falhar o release antes de marcá-lo como concluído.
Antes de carregar tabelas, o deploy e o ETL executam uma validação via bq show {ProjectId}:{Dataset}. O BigQuery pode ser ligado por OPENCNPJ_BIGQUERY_ENABLED=true, e o ProjectId vem de OPENCNPJ_BIGQUERY_PROJECT_ID ou do config.json. O projeto é passado explicitamente em todos os comandos BigQuery, então o fluxo não depende do projeto default configurado no gcloud. O dataset precisa existir; as tabelas finais podem existir ou não. Cada execução carrega uma tabela staging a partir do Parquet columnar e substitui/cria a tabela final com bq cp --force, permitindo atualizar schemas desatualizados, como a tabela receita, e criar tabelas novas, como cno e rntrc.
Para deploy em container com credencial via env, gere o valor com base64 -w 0 arquivo.json e configure OPENCNPJ_GOOGLE_CREDENTIALS_BASE64 como secret. O entrypoint decodifica a credencial em arquivo temporário, ativa gcloud auth activate-service-account e remove o arquivo antes de iniciar o deploy.
- Dentro de
src/Page:npm installnpm run devpara desenvolvimento localnpm run buildpara gerar a versão estática emsrc/Page/dist
A página é implementada em React + TypeScript e continua sendo 100% estática no artefato final. O index.html de publicação deve ser o gerado em src/Page/dist, não o arquivo fonte usado pelo Vite em src/Page/index.html.
- Os shards no R2 são publicados em releases versionados, por exemplo
files/shards/releases/{release_id}/{prefix}.ndjson. - Cada dataset publicado também gera um ZIP estável por dataset em
files/releases/{dataset}/data.zip(ex.:receita,cno,rntrc), referenciado noinfo.jsoncom tamanho e MD5. - A API publicada consome os
*.ndjsone*.index.bindo release ativo no R2, ondeprefixusa os 3 primeiros caracteres do CNPJ normalizado. - Cada linha do
*.ndjsonrepresenta um CNPJ e o*.index.binguardaoffsetelengthexatos para leitura direta no Worker. - O contrato de CNPJ já aceita formato alfanumérico: 12 caracteres alfanuméricos + 2 dígitos finais.
- O arquivo
info.jsoncontinua sendo publicado com metadados do release ativo,storage_release_id, ZIP principal da Receita e o mapadatasetscom metadados de ZIP por base.
- Use
src/script/deploy.shpara orquestrar o release:- roda o ETL com release versionado
- ignora BigQuery com aviso quando
BigQuery.Enabled=false - valida
OPENCNPJ_BIGQUERY_ENABLEDouBigQuery.Enabled,OPENCNPJ_BIGQUERY_PROJECT_IDouBigQuery.ProjectId,BigQuery.Dataset, o comandobqconfigurado e o acesso ao dataset quando BigQuery está habilitado - copia
info.jsone*.index.bindo release gerado parasrc/Worker/assets - executa
npm testno Worker - faz
npx wrangler deploy - valida
/info, um CNPJ canônico e o mesmo CNPJ mascarado - remove o release antigo do bucket só depois da validação
- Abra issues para discutir mudanças.
- Faça fork, crie uma branch descritiva e envie PR.
- Mantenha commits pequenos e o projeto compilando (
dotnet build).