Guia do código¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-06-18
Audiência: dev que abriu o repositório e quer passar os olhos e entender como o
código está organizado, sem ainda mergulhar no Javadoc classe a classe. Para o
porquê das decisões, veja decisoes/;
para rodar/testar, Como rodar; para o
contrato externo, API REST.
A tabela de classes no fim desta página é gerada no build a partir da 1ª frase do Javadoc de cada tipo — então acompanha o código. A narrativa abaixo é autorada.
Como o código é organizado¶
O código segue package-by-feature (decisão
0022): cada funcionalidade é um pacote de
topo sob br.com.vantroba.bi.transporte que carrega suas próprias camadas, em
vez de pastas globais controller/, service/, repository/. A fundação
transversal (erro RFC 7807, health, Sentry, motor de auth, object storage Garage,
utilitários e infra de teste) vem das libs do xadm-commons — não é código
local; ver decisões 0023/0024/0025.
O pacote local comum guarda só o resto app-específico (o que não coube numa
feature nem numa lib).
| Pacote de topo | É | Responsabilidade |
|---|---|---|
processamento |
feature | o pipeline XLS ponta a ponta — a feature central do app |
powersync |
feature | reset da replicação PowerSync |
configuracao |
feature | configuração global de runtime (admin) |
seguranca |
feature | as duas portas de auth (Bearer + login Google) — view-glue sobre o motor da lib |
comum |
resto | app-específico: config typed, exception (503 XLS), dto, util (AnosVeiculoParser), notificacao (Telegram) |
A fundação transversal (erros, health, Sentry, versão, auth, storage, util, teste) mora nas libs
xadm-seguranca/xadm-comum-web/-storage/-util/-testedoxadm-commons— um bump de lib corrige todos os apps da casa de uma vez.
As camadas dentro de uma feature¶
O fluxo de uma requisição é Controller → Service → Repository:
- Controller (
@Controller): só HTTP. Em API retorna DTO (record+@Serdeable) → JSON; em view server-rendered alimenta o template JTE com um view-model. Zero regra de negócio. - Service (
@Singleton): regra de negócio, orquestração,@Transactional, conversão entidade↔DTO. Injeção por construtor. - Repository (Micronaut Data JDBC, sem Hibernate — decisão 0001): só acesso a dado.
- A entidade (
@MappedEntity) nunca cruza o controller. A borda HTTP fala DTO (API) ou view-model (view); a entidade fica da camada de service para dentro.
Travas de arquitetura (ArchUnit)¶
O ArchitectureTest trava três invariantes do
package-by-feature — rodam no ./gradlew check:
- sem ciclos entre as features de topo;
- nenhum subpacote de
comumdepende de feature (inclusivecomum.notificacao: o Telegram é transporte puro, recebe texto pronto; a formatação que conhece o domínio vive no notificador de cada feature); processamento.processing(leitura do Excel) não depende da camada HTTP.
Referência completa¶
O Javadoc gerado (árvore de classes navegável, interna) fica em
dev/api/ — gerado pelo CI de docs a cada publish. Use-o quando precisar do
detalhe de uma classe; o inventário abaixo é o atalho para achá-la.
Inventário das classes¶
Processamento¶
Pipeline de processamento da planilha XLS — a feature central do app.
| Pacote | Classe | O que faz |
|---|---|---|
processamento |
ArmazenamentoArquivoService |
Coordena o armazenamento do binário XLS entre o Postgres (coluna arquivo_bytes) e o object storage Garage, conforme o ArmazenamentoModo configurado em app.storage.modo. |
processamento |
ArquivoBytesLegado |
Projeção de coluna única: o binário legado arquivo_bytes. |
processamento |
ArquivoXlsDownload |
Conteúdo de um arquivo XLS recuperado do storage para download. |
processamento |
BulkUpserter |
Caminho idempotente UPSERT diff-aware + DELETE seletivo (spec 004). |
processamento |
ColunasConteudo |
Fonte de verdade única das colunas relevantes ao caminho idempotente UPSERT diff-aware (spec 004 — § 4.2 e § 5.4). |
processamento |
ConjuntoLote |
Tabela xls_conjunto_lote: rastreia um lote de arquivos enviados juntos num .zip. |
processamento |
ConjuntoLoteRepository |
Persistência de ConjuntoLote (lote por zip). |
processamento |
ConjuntoLoteService |
Coordena o ciclo de vida de um lote (.zip). |
processamento |
CopyTextWriter |
Builders para o formato TEXT do COPY FROM STDIN do PostgreSQL. |
processamento |
Faturamento |
Linha de faturamento importada da aba 20 do Excel — tabela bi_faturamento. |
processamento |
FaturamentoRepository |
Repositório CRUD de bi_faturamento. |
processamento |
LoteRecebimentoBody |
Resposta do POST /api/xls/processar: id do lote, total e status por entrada. |
processamento |
MesclaResumo |
Agregado das métricas de uma execução do orquestrador (spec 004 § 5.5): contém o UpsertResultado de cada tabela alvo. |
processamento |
Movimento |
Linha de movimento contábil importada da aba 30 — tabela bi_movimento. |
processamento |
MovimentoRepository |
Repositório CRUD de bi_movimento. |
processamento |
ProcessamentoConsultaService |
Consultas de processamento: listagem paginada, detalhe, leitura do arquivo de log em disco e download do XLS original. |
processamento |
ProcessamentoDetalheResponse |
Detalhe de um processamento para API e tela de detalhe (metadados, contagens e métricas de idempotência da spec 004; sem bytes do XLS). |
processamento |
ProcessamentoListResponse |
Resposta paginada do endpoint de listagem de processamentos. |
processamento |
ProcessamentoNotificador |
Formata e dispara as notificações Telegram do pipeline de processamento. |
processamento |
ProcessamentoProcessador |
Execução assíncrona do processamento (fora do ProcessamentoService para o @Async ser aplicado via proxy). |
processamento |
ProcessamentoRepository |
Persistência JDBC de ProcessamentoXls e atualizações de status. |
processamento |
ProcessamentoResponse |
Resposta do recebimento síncrono (o controller HTTP mapeia httpStatus para o status da resposta). |
processamento |
ProcessamentoResumoDto |
Linha da lista de processamentos (JTE e GET /api/transporte/processamentos). |
processamento |
ProcessamentoService |
Orquestra recepção de arquivos, deduplicação por checksum e agendamento do processamento assíncrono. |
processamento |
ProcessamentoStatus |
Estados de um processamento de XLS (xls_processamento.status). |
processamento |
ProcessamentoTransactionalHelper |
Operações transacionais sobre os dados do BI por período (evita problemas de proxy com @Async). |
processamento |
ProcessamentoXls |
Entidade da tabela xls_processamento: metadados do envio, referência ao objeto XLS no MinIO e resultado do job. |
processamento |
StorageBackfillService |
Backfill dos blobs legados (arquivo_bytes) para o object storage Garage, dirigido pelo ArmazenamentoModo configurado em app.storage.modo: PSQL — não faz nada (tudo permanece no Postgres). |
processamento |
TransporteController |
API REST de transporte: envio de XLS (Bearer), listagem e consulta pública de processamentos. |
processamento |
UpsertResultado |
Métricas de uma operação UPSERT diff-aware + DELETE seletivo no caminho idempotente (spec 004 — § 4.7). |
processamento |
ViewController |
Rotas HTML (JTE) para histórico e detalhe de processamentos — acesso anônimo conforme configuração de segurança. |
processamento |
XlsController |
Porta única de envio de XLS — padrão da casa, idêntico entre todos os clientes. |
processamento |
ZipXlsExtrator |
Desempacota o .zip de lote em suas entradas .xlsx (o zip É o lote). |
processamento.processing |
ExcelProcessor |
Processa o byte[] do xlsx via FastExcel (StAX puro do JDK, sem XMLBeans/POI), em streaming. |
processamento.processing |
PeriodoRelatorio |
Período do relatório extraído da aba "10" (células E1/F1). |
processamento.processing |
ProcessamentoJsonExporter |
Serializa ResultadoProcessamento para JSON canônico conforme docs/dev/schema-processamento-xls.json. |
processamento.processing |
VarcharLimits |
Trunca strings ao tamanho máximo da coluna no PostgreSQL (evita erro no insert). |
processamento.processing |
VeiculoDadoFaltanteException |
Exception sintética usada pelo VeiculoDefesaCollector para envelopar um motivo+placa num evento Sentry (GlitchTip). |
processamento.processing |
VeiculoDefesaAvaliador |
Inspeciona uma linha do XLS mensal (faturamento ou movimento) e produz a lista de motivos de defesa que se aplicam ao cadastro veicular daquela linha. |
processamento.processing |
VeiculoDefesaCollector |
Coletor stateful per-processamento. |
PowerSync¶
Reset da replicação PowerSync — orquestra os steps que pausam a replicação, derrubam o estado no MongoDB do PowerSync, recriam o slot no PostgreSQL e sinalizam os clientes Dart a refazerem o bootstrap (disconnectAndClear).
| Pacote | Classe | O que faz |
|---|---|---|
powersync |
AdminController |
Endpoints administrativos: hoje, apenas o "reset" da replicação PowerSync. |
powersync |
AdminViewController |
Tela de administração JTE do reset da replicação PowerSync. |
powersync |
CoolifyClient |
Wrapper fino sobre HttpClient para a API REST do Coolify — apenas as chamadas que a estratégia coolify de PowerSyncProcessControl precisa. |
powersync |
MongoAdminService |
Operações administrativas no MongoDB do PowerSync. |
powersync |
MongoAdminServiceImpl |
Implementação real de MongoAdminService usando mongodb-driver-sync. |
powersync |
MongoAdminServiceStub |
Stub de MongoAdminService ativo quando powersync.mongodb.uri está vazio (default em dev). |
powersync |
PostgresReplicationAdmin |
Operações administrativas em slots de replicação lógica do PostgreSQL. |
powersync |
PowerSyncProcessControl |
Controla pause/resume do PowerSync Service durante o reset. |
powersync |
PowerSyncProcessControlCoolify |
Estratégia coolify de PowerSyncProcessControl: reinicia o recurso PowerSync pela API REST do Coolify ao final do reset. |
powersync |
PowerSyncProcessControlNone |
Implementação no-op de PowerSyncProcessControl: loga warning e reporta no progresso que o restart do PowerSync é manual. |
powersync |
ResetStatus |
Estados de uma execução de reset da replicação (xls_resetar_powersync.status). |
powersync |
ResetarPowersync |
Auditoria de execuções do "reset" da replicação PowerSync. |
powersync |
ResetarPowersyncAlreadyInProgressException |
Sinal do ResetarPowersyncRepository#iniciar de que já existe um reset EM_ANDAMENTO (violação do partial unique index). |
powersync |
ResetarPowersyncDetalheView |
View-model do reset para a tela de detalhe (admin/resetar-powersync-detalhe) — projeção dos campos que o template exibe. |
powersync |
ResetarPowersyncNotificador |
Formata e dispara as notificações Telegram do reset da replicação. |
powersync |
ResetarPowersyncRecovery |
Instruções de recuperação manual por step do reset — espelha a matriz de recovery do runbook (docs/resetar-powersync.md). |
powersync |
ResetarPowersyncRepository |
Persistência da auditoria de resets em xls_resetar_powersync. |
powersync |
ResetarPowersyncRequest |
Body opcional do POST /api/transporte/admin/resetar-powersync. |
powersync |
ResetarPowersyncResponse |
Resposta 202 do POST /api/transporte/admin/resetar-powersync. |
powersync |
ResetarPowersyncResumo |
View-model do reset para a listagem da tela admin — projeção dos campos que o template admin/powersync exibe. |
powersync |
ResetarPowersyncService |
Orquestra os 9 steps do reset da replicação PowerSync. |
powersync |
ResetarPowersyncStatusResponse |
Resposta 200 do GET /api/transporte/admin/resetar-powersync/{id}. |
powersync |
StartupRecoveryService |
Recuperação ao subir a aplicação: Processamentos órfãos em PROCESSANDO viram ERRO; Processamentos em PENDENTE são re-enfileirados; Resets órfãos em EM_ANDAMENTO (pool reset- morreu junto com a JVM) viram ERRO — desbloqueia o partial unique index pra novos resets. |
Configuração¶
Configuração global de runtime do app, editável pelo admin e persistida em banco — distinta da configuração estática de deploy (application.yml/env).
| Pacote | Classe | O que faz |
|---|---|---|
configuracao |
BiConfiguracao |
Configuração global do app em formato chave/valor. |
configuracao |
BiConfiguracaoRepository |
Persistência de configurações globais em bi_configuracao (V12). |
configuracao |
BiConfiguracaoView |
View-model de configuração para a tela admin/configuracoes — projeção dos campos que o template exibe. |
configuracao |
ConfigService |
Leitura de configurações globais (bi_configuracao) em runtime, com cache curto. |
configuracao |
ConfiguracaoAdminService |
Operações da tela admin de configurações (/admin/configuracoes). |
configuracao |
ConfiguracaoAdminViewController |
} (exige sessão; gate de email @xadm.com.br no login). |
Segurança¶
Camada de segurança específica do app (decisão 0011 / etapa 07): a policy de proteção das views e o fluxo de login Google.
| Pacote | Classe | O que faz |
|---|---|---|
seguranca |
AuthExceptionHandler |
Rede de segurança para AuthException que escape sem tratamento inline (o LoginController traduz as suas próprias no fluxo normal). |
seguranca |
ViewRejectionHandler |
Tradução das rejeições do micronaut-security (5.x lança AuthorizationException) preservando o comportamento do antigo AuthFilter: autenticado sem permissão (AuthorizationException#isForbidden()) → 403; view anônima, browser (Accept: text/html) → 302 /login?from=…; view anônima, script (JSON) → 401; view em fail-closed (prod sem envs de auth) → 503; path whitelisted (ex.: /api sem Bearer) → 401. |
seguranca |
ViewSecurityRule |
Regra de segurança das views, replicando o tri-estado do antigo AuthFilter: enabled (envs de auth completas): path de view exige Authentication — autenticado → ALLOWED, anônimo → REJECTED (o ViewRejectionHandler faz 302/401); bypass (dev/test sem envs): view liberada (ALLOWED) — views públicas; fail-closed (prod sem envs): view rejeitada (REJECTED) — o handler responde 503. |
seguranca |
ViewWhitelist |
Whitelist da CAMADA DE VIEWS — os paths que a ViewSecurityRule dispensa de sessão. |
Comum — base transversal¶
Base transversal — não é feature e, por trava de arquitetura (decisão 0022), não depende de nenhuma.
| Pacote | Classe | O que faz |
|---|---|---|
comum.config |
AppConfig |
Configuração de nível app.* compartilhada entre beans — prefixo app. |
comum.config |
CoolifyConfig |
Configuração do restart automático do PowerSync via API do Coolify — prefixo powersync.admin.coolify.*. |
comum.config |
LogsConfig |
Configuração do diretório de logs de execução — prefixo app.logs.*. |
comum.config |
PowersyncMongoConfig |
Configuração do MongoDB do PowerSync usada no reset da replicação — prefixo powersync.mongodb.*. |
comum.config |
PowersyncNukeConfig |
Configuração da confirmação e do bootstrap do reset destrutivo — prefixo powersync.nuke.* (contrato preservado do rename Nuke→ResetarPowersync; lido por integrações). |
comum.config |
PowersyncPostgresConfig |
Configuração da replicação Postgres do PowerSync usada no reset — prefixo powersync.postgres.*. |
comum.config |
TelegramConfig |
Configuração do bot Telegram — prefixo telegram.*. |
comum.exception |
StorageIndisponivelException |
Storage de arquivos (Garage) indisponível ao receber o XLS — HTTP 503. |
comum.notificacao |
TelegramApi |
Cliente HTTP declarativo da Telegram Bot API — só o sendMessage que o TelegramService usa. |
comum.notificacao |
TelegramService |
Transporte de notificações via Telegram Bot API: recebe um texto já pronto e o posta. |
comum.util |
AnosVeiculoParser |
Parseia o texto de ano do Excel no formato AAAA/AAAA (ex.: 2007/2007): à esquerda da barra = ano de construção; à direita = ano do modelo. |
Raiz¶
Raiz do bi-transporte-xls: serviço Micronaut que recebe a planilha XLS de transporte, processa as abas em registros bi_/xls_ no PostgreSQL e expõe o resultado por API REST e views server-rendered, sincronizando para clientes Dart via PowerSync.
| Pacote | Classe | O que faz |
|---|---|---|
transporte |
Application |
Ponto de entrada da aplicação Micronaut e definição global OpenAPI (Bearer). |
transporte |
BearerTokenEnv |
— |