Operação · conformidade
Aderência ao contrato
Mapa dos invariantes honrados por esta camada de frontend e, no mesmo nível, a lista completa das lacunas contratuais. Escopo entregue: apresentação e experiência visual.
Escopo
Corrigido: apresentação, estados, acessibilidade e fronteira de dados. Não alterado: regras financeiras, fórmulas, backend, banco de dados, integrações e o próprio OpenAPI.
Fonte contratual
- OpenAPI FINANCEIRO_HOLDING v0.3.1
- 14 endpoints cobertos
- 15 lacunas declaradas
Classificação
SYNTHETIC_ONLY — dados de demonstração, sem qualquer informação real e sem efeito externo.
Invariantes honrados
Nenhuma regra financeira é recalculada no cliente
Dinheiro trafega como string decimal e é apenas formatado. Nenhuma soma, margem, saldo ou percentual é derivado na interface. Onde o número precisa de precisão, ele vem pronto da origem.
lib/finance/format.ts · components/finance/money.tsx
Contagem de registros não é soma de valores
As telas de obrigações contam linhas por situação e dizem "registros" no rótulo. Somar saldos ali produziria um total que o backend nunca emitiu.
components/finance/views/obligations-view.tsx
Realizado e projetado não se misturam
O fluxo separa extratos conciliados de obrigações a vencer, com rótulo visível e leituras independentes por série.
components/finance/views/cash-flow-view.tsx
Custo não alocado permanece visível
Custo de fornecedor sem alocação é destacado no billing e declarado na rentabilidade, que se assume parcial. O custo nunca é descartado nem rateado para melhorar a margem exibida.
billing-view.tsx · profitability-view.tsx
Estado nunca é comunicado só por cor
Todo estado persistido carrega rótulo textual em pt-BR. Os mapas de rótulo são tipados pelos enums do contrato, então um estado sem rótulo quebra o build em vez de renderizar vazio.
lib/finance/status.ts
Lineage pertence ao recurso que o declara
Somente o painel declara lineage no v0.3.1. Nas demais telas a barra afirma a ausência, em vez de exibir a procedência do painel como se fosse daquele recurso.
components/finance/lineage-bar.tsx
Os gates documentais seguem a máquina de estados
A geração exige invoice APROVADA (não apenas "não bloqueada"), a NFS-e exige invoice gerada e o envio exige NFS-e autorizada. Qualquer bloqueio de preflight veta todo avanço.
lib/finance/document-gates.ts
Nenhum estado produz área vazia silenciosa
Os onze estados canônicos passam por uma única biblioteca com switch exaustivo. Um estado novo quebra a compilação; um estado sem dados exibe explicação em vez de nada.
components/finance/canonical-state.tsx
Escopo desconhecido não recebe dados de outra empresa
Os resolvedores sintéticos devolvem ausência explícita para escopo sem dados próprios, em vez de cair na empresa padrão — o que faria o operador ler números de outra companhia.
lib/finance/provider/fixtures.ts
Dados totalmente sintéticos, sem efeito externo
Nenhum CNPJ, cliente, banco ou valor real. Nenhuma chamada de rede, nenhuma invoice ou NFS-e emitida, nenhum e-mail enviado. Todas as ações de escrita estão desabilitadas.
lib/finance/provider/mock-provider.ts
Lacunas contratuais declaradas
CONTRATO PENDENTE· GAP-01Cada item abaixo existe na interface porque a operação precisa dele, mas não possui endpoint no OpenAPI v0.3.1. Nenhum deles é apresentado como dado vivo: todos aparecem marcados e alimentados por dados sintéticos declarados.
Empresas e consolidação da holding
GAP-01Não existe endpoint de empresas. O consolidado aparece no enum de resposta do painel, mas a requisição exige `legal_entity_id` e não oferece parâmetro de consolidação — é representável, não requisitável.
Contas bancárias
GAP-02Saldos e cadastro de contas não têm endpoint; os cartões de conta são sintéticos.
Transações bancárias importadas
GAP-03Não há leitura de extrato no contrato. Os lançamentos exibidos são sintéticos.
Conciliação de extrato bancário
GAP-04O contrato define `Settlement.reconciliation_status` (PENDING, MATCHED, DIVERGENT) para a BAIXA de uma obrigação. O que não existe é a conciliação de EXTRATO: importar lançamentos do banco e propor correspondências. O estado de conciliação do extrato reusa o vocabulário do contrato, mas a operação em si não tem endpoint.
Apuração auxiliar de mensageria
GAP-05Tráfego por canal, aliases, garantia mínima, setup/créditos e memória de cálculo por evento não possuem endpoint.
Rentabilidade detalhada por cliente/canal
GAP-06Não há endpoint de margem por cliente. A tabela é sintética e a margem chega pronta.
Auditoria detalhada (antes/depois, filtros)
GAP-07A trilha de auditoria não tem endpoint de leitura no contrato.
Cadastros e configurações
GAP-08Nenhuma escrita ou leitura de cadastro é coberta; a tela é estrutura visual declarada.
Listagem e histórico de jobs
GAP-09O contrato cobre a consulta de um job por identificador, porém não a listagem nem o histórico exibidos no painel lateral.
Replay idempotente
GAP-10O reenvio com a mesma chave é descrito no contrato, mas não há endpoint para consultar o resultado de um replay anterior.
Conflitos de versão
GAP-11A obrigação expõe `version`, porém o contrato não define a resposta de conflito de versão em escrita concorrente.
Lineage, cutoff, qualidade e freshness por recurso
GAP-12Somente `GET /v1/dashboard/summary` declara lineage. Os demais recursos não têm procedência própria, e nenhuma tela empresta a do painel.
Autorização por recurso
GAP-13O contrato não descreve papéis nem alçadas por recurso. O estado de acesso negado é apresentável, mas não é derivado de contrato.
Linha analítica de billing (cliente × produto × canal)
GAP-14`GET /v1/billing-runs` devolve o agregado por execução: identificador, período, totais e status. Não existe rota que devolva a linha analítica com preço unitário, volume trafegado, volume faturável, custo de fornecedor, comissão de parceiro e margem por linha. A grade analítica inteira é VISUAL_ONLY.
Memória de cálculo e exceções de faturamento
GAP-15Não há rota que devolva a sequência de passos que produziu o valor de uma linha (volume → preço → mínimo → desconto → imposto), nem a lista de exceções de reconciliação com severidade e bloqueio de fechamento. Ambas são apresentadas como VISUAL_ONLY e não devem ser lidas como cálculo do backend.