# Histórico

Copyright (c) 2026 RAVAPI Soluções. www.ravapi.com

## 0.5.0 — Documento único, limite da descrição e trial

**Migration 005.**

- Descrição limitada a 300 caracteres: validação na aplicação com mensagem
  explicando o motivo, e `CHECK` no banco como rede de baixo
- CPF/CNPJ único por tenant, via índice funcional sobre os dígitos —
  "529.982.247-25" e "52998224725" passam a ser o mesmo documento
- `CadastrosService.porDocumento()` e `localizarOuCriar()`: cadastro rápido de
  contraparte com o documento como chave, buscando antes de inserir
- Contraparte inativa é reativada, nunca recriada: recriar quebraria o vínculo
  com os recibos já emitidos
- Duplicidade vinda do índice vira mensagem legível, com o nome de quem já tem
  aquele documento
- `em_trial` em `license_state` e `toleranciaEfetiva()`: a tolerância é zero
  durante o trial, mesmo que a licença venha com 15 dias. Trava do lado do
  produto contra configuração errada no Klavo
- Fixtures de teste passam a gerar CPF/CNPJ válidos e distintos (ver abaixo)
- 45 testes de integração, 11 novos

### Correção de fixtures

Os testes cadastravam dezenas de contrapartes com o mesmo CNPJ, o que só
passava porque não havia unicidade. Com a restrição no lugar, 15 testes
quebraram de uma vez. Cada fixture passou a gerar o próprio documento válido —
fixture que compartilha identidade esconde bug de identidade.

Um dos CPFs escritos à mão nos testes novos também não passava nos dígitos
verificadores. O próprio validador do sistema pegou.

## 0.4.1 — Correção de empacotamento

- Scripts entregues sem o bit de execução: `npm test` quebrava com
  "Permission denied" para quem clonasse o repositório
- `run.sh` e o CI passam a invocar os scripts via `bash`, para funcionar mesmo
  quando o modo do arquivo se perde no transporte (tarball, zip, Windows)
- Verificado extraindo o tarball num diretório limpo e rodando a suíte

## 0.4.0 — Fase 4: documento impresso

- Template A4 em duas vias como função pura, consciente da direção
- Título, rótulo de valor, verbo de quitação e partes invertem com a direção
- Rótulos "Via do pagador" / "Via do recebedor", corretos nas duas direções
- QR code real apontando para a URL pública de verificação
- Tarja e motivo de cancelamento nas duas vias
- Escape de HTML em todo campo vindo do usuário
- `ImpressaoService` monta o documento a partir do snapshot congelado
- Adaptador `PuppeteerPdf` atrás de interface
- 21 testes de layout; 6 testes de impressão na integração

## 0.3.0 — Fases 1 a 3: cadastros, usuários e selo

- Cadastro de empresas, séries e contrapartes, com validação de CPF/CNPJ
- Usuários, convites com token, quatro papéis e permissão por série
- `IdentityProvider` com implementação local e delegada
- Rascunho mutável, selo imutável e cancelamento por contra-registro
- Serviço de licença com a regra de degradação
- Contexto de tenant obrigatório em toda transação
- 28 testes de integração

### Mudança de escopo da cadeia

A cadeia de hash passou de empresa para **série**. Numeração e cadeia
ficaram com o mesmo escopo, então um único `FOR UPDATE` na série governa as
duas coisas, e séries diferentes emitem em paralelo. Decidido antes de existir
documento em produção — depois seria migration em tabela imutável.

### Bug corrigido: `::bytea` no cálculo do hash

`selar_recibo()` calculava `sha256((texto)::bytea)`. O cast não converte texto
em bytes: interpreta a string como sintaxe de escape do bytea. Com acento,
cedilha, travessão ou contrabarra, quebra ou produz bytes errados.

Os testes SQL não pegaram porque usavam texto sem acento. O teste de
integração, que sela "manutenção de coifa, instalação de exaustão — OS
\"4412\"", pegou na primeira execução. Corrigido para
`convert_to(texto, 'UTF8')`, que casa com `createHash('sha256').update(t,'utf8')`
do Node. Teria quebrado no primeiro recibo brasileiro de verdade.

### Bug corrigido: conjunção do valor por extenso

R$ 1.500,00 saía como "mil, quinhentos reais". O certo é "mil e quinhentos
reais": em português o último grupo entra com "e" quando é menor que cem ou uma
centena redonda.

## 0.2.0 — Fase 0: banco

- Schema `recibos` com 12 tabelas e RLS por tenant
- Aplicação sem `INSERT` em `receipts`: só a função de selo cria documento
- Triggers bloqueando UPDATE e DELETE, inclusive para superusuário
- Numeração com `FOR UPDATE`, sem `SEQUENCE` (sequence não faz rollback)
- Cancelamento por contra-registro
- `verificar_cadeia()` detecta exclusão no meio e truncamento da ponta
- 17 critérios de aceite, 6 testes de defesa em profundidade, teste de
  concorrência com 40 emissões simultâneas

## 0.1.0 — Escopo e mockup

- Escopo v1.1 com direção do documento, contrapartes, usuários e
  licenciamento via Klavo
- Mockup navegável com seis telas
