Skip to content

feat(node): o emitente que já existe no painel entra pela credencial, e recomeçar do zero vira botão - #1

Merged
betogd merged 3 commits into
mainfrom
claude/great-albattani-nn33cl
Sep 9, 2026
Merged

betogd merged 3 commits into
mainfrom
claude/great-albattani-nn33cl

Conversation

@betogd

@betogd betogd commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Três commits, para simplificar o exemplo em uso de teste.

1. O emitente que já existe no painel entra pela credencial

A tela Emitente só sabia cadastrar. Quem já tem o emitente pronto na plataforma — cadastrado no painel, com certificado, ativo e com uma credencial operacional cunhada lá — não tinha como usá-lo no exemplo: precisava criar um segundo, com outro CNPJ.

O passo 1 ganha um atalho: informada a credencial operacional, a aplicação descobre o resto sozinha, com duas leituras e nenhuma escrita.

Rota O que traz
1 GET /v1/contexto de quem é a credencial — escopo emitente ⇒ o id
2 GET /v1/emitentes/{id} a ficha: razão social, CRT, certificado, ambiente, webhook

O id e a credencial vão para o banco local, e os passos 2, 3 e 4 já aparecem prontos: dá para ir direto à série. É o que um ERP faz de verdade quando o cliente entrega uma credencial pronta — a integração nunca cadastra ninguém, só se apresenta.

Uma credencial de gestão é recusada no atalho, com o escopo que ela devolveu impresso na tela: guardá-la deixaria a aplicação sem o que emite.

Três consequências

  • A ficha passa a ser lida pela credencial operacional quando há uma — na tela Emitente e na Nova nota. Um emitente adotado pelo atalho pode estar fora da carteira da credencial de gestão do .env, e aí a de gestão levaria 404 justamente onde a tela lê o CRT. A de gestão continua sendo a do onboarding, antes de existir outra.
  • CERTIFICADO_PFX vira opcional. Ele só serve para cadastrar um emitente novo pela API; quem adota um pronto não tem por que ter o .pfx na máquina, e exigi-lo travava o boot. Sem ele, o passo 2 diz o que falta em vez de apontar para um arquivo que não existe.
  • O alinhamento do destinatário semeado não é possível no atalho: GET /v1/emitentes/{id} publica município e UF, mas não o código IBGE. Quando as UFs divergem, a tela avisa, cita o DIFAL que este exemplo não monta e manda ajustar na tela Destinatários.

2. Recomeçar do zero vira botão

Apagar o exemplo.sqlite na mão era a única forma de recomeçar, e três mensagens da tela Emitente mandavam fazer exatamente isso. Agora é um botão na tela Configuração, que é onde o banco local já se descreve: esvazia as seis tabelas, zera a linha de configuração, devolve os ids ao 1 e semeia os dados de exemplo outra vez.

Duas coisas que a tela diz, porque são o que se erra aqui:

  • Não chama a API. O emitente continua cadastrado, as notas emitidas continuam autorizadas e a credencial continua válida na plataforma. O reset é local, e só.
  • O que se perde é irrecuperável, e é local: os secret da credencial operacional e do webhook, que a API mostra uma única vez. Por isso a ação exige a confirmação marcada em vez de disparar num clique, e o aviso só aparece quando há de fato um segredo guardado.

Os dois primeiros commits fecham o ciclo de teste: recomeça do zero e vincula a mesma credencial de novo — as séries já provisionadas continuam lá, e a tela as lista sem provisionar nada.

3. A mínima do Node cai para 22.15

O >=22.18 era a versão em que executar .ts deixa de precisar de flag. Baixar a mínima sem mais nada deixaria o npm start quebrado em quatro releases da própria LTS, então o que a 22.15 exige passa a ir escrito: --experimental-strip-types no start e no test, inofensivo nas versões que já o dispensam.

As duas datas, do CHANGELOG_V22:

Versão O que mudou
22.13.0 node:sqlite desflagado (#55890)
22.18.0 type stripping por padrão (#56350)

A 22.15 fica acima da primeira e abaixo da segunda — daí o flag, e só ele. O --disable-warning=ExperimentalWarning, que já estava lá, cala o aviso que ele acende.

Testes

npm run check (tipos + testes) verde: 47 testes, 0 falhas — 36 existentes intactos, 11 novos.

Os novos cobrem: o atalho descobrindo a ficha e não escrevendo nada na API; a credencial de gestão recusada; a credencial inexistente caindo no envelope { erro } da autenticação sem gravar nada; o vínculo sobre um emitente já guardado recusado antes de chamar a API; o aviso de UF divergente; o .pfx opcional no carregarConfig e nas duas telas; o reset apagando e semeando de novo sem tocar na API; o reset sem confirmação não apagando nada; e o vínculo depois do reset reencontrando as séries.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LaGkFHKBBTcyAatrn1pskT

… sem repetir o onboarding

A tela Emitente só sabia cadastrar. Quem já tem o emitente pronto na plataforma — cadastrado,
com certificado, ativo e com uma credencial operacional cunhada no painel — não tinha como
usá-lo: precisava criar um segundo, com outro CNPJ, para ver o exemplo rodar.

O passo 1 ganha um atalho. Informada a credencial OPERACIONAL, a aplicação descobre o resto
sozinha, com duas leituras e nenhuma escrita:

  GET /v1/contexto        de quem é a credencial (escopo `emitente` ⇒ traz o `id`)
  GET /v1/emitentes/{id}  a ficha: razão social, CRT, certificado, ambiente, webhook

É o que um ERP faz de verdade quando o cliente entrega uma credencial pronta: a integração
nunca cadastra ninguém, só se apresenta. Uma credencial de gestão é recusada aqui, com o
escopo que ela devolveu na tela — guardá-la deixaria a aplicação sem o que emite.

Três consequências:

- A leitura da ficha passa a usar a credencial operacional quando há uma, na tela Emitente e
  na Nova nota. Um emitente adotado pelo atalho pode estar fora da carteira da credencial de
  gestão do `.env`, e aí a de gestão levaria 404 no lugar onde a tela lê o CRT.
- `CERTIFICADO_PFX` vira opcional. Ele só serve para cadastrar um emitente novo pela API; quem
  adota um pronto não tem por que ter o `.pfx` na máquina, e exigi-lo travava o boot.
- O alinhamento do destinatário semeado não é possível no atalho: `GET /v1/emitentes/{id}`
  publica município e UF, mas não o código IBGE. Quando as UFs divergem a tela avisa, cita o
  DIFAL que o exemplo não monta, e manda ajustar em Destinatários.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LaGkFHKBBTcyAatrn1pskT
…de exigir `rm`

Apagar o `exemplo.sqlite` na mão era a única forma de recomeçar, e três mensagens da tela
Emitente mandavam fazer exatamente isso. Vira um botão na tela Configuração, que é onde o
banco local já se descreve.

`Banco.reiniciar()` esvazia as seis tabelas, zera a linha de configuração, devolve os ids ao 1
e semeia os dados de exemplo outra vez — o estado da primeira execução.

Duas coisas que a tela diz, porque são o que se erra aqui:

- **Não chama a API.** O emitente continua cadastrado, as notas emitidas continuam autorizadas
  e a credencial continua válida na plataforma. O reset é local, e só.
- **O que se perde é irrecuperável, e é local:** os `secret` da credencial operacional e do
  webhook, que a API mostra uma única vez. Por isso a ação exige a confirmação marcada em vez
  de disparar num clique, e o aviso só aparece quando há de fato um segredo guardado.

Com o atalho do commit anterior, o par fecha o ciclo de teste: recomeça do zero e vincula a
mesma credencial de novo — as séries já provisionadas continuam lá, e a tela as lista sem
provisionar nada.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LaGkFHKBBTcyAatrn1pskT
@betogd betogd changed the title feat(node): o emitente que já existe no painel entra pela credencial, sem repetir o onboarding feat(node): o emitente que já existe no painel entra pela credencial, e recomeçar do zero vira botão Sep 9, 2026
…e a 22.15 exige

O `>=22.18` era a versão em que executar `.ts` deixa de precisar de flag. Baixar a mínima sem
mais nada deixaria o `npm start` quebrado em quatro releases da própria LTS, então o que a
22.15 exige passa a ir escrito: `--experimental-strip-types` no `start` e no `test`, inofensivo
nas versões que já o dispensam.

As duas datas, do CHANGELOG_V22:

  22.13.0  `node:sqlite` desflagado  (#55890)
  22.18.0  type stripping por padrão (#56350)

A 22.15 fica acima da primeira e abaixo da segunda — daí o flag, e só ele. O
`--disable-warning=ExperimentalWarning`, que já estava lá, cala o aviso que ele acende.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LaGkFHKBBTcyAatrn1pskT
@betogd
betogd marked this pull request as ready for review September 9, 2026 15:10
@betogd
betogd merged commit 7b6d3d8 into main Sep 9, 2026
betogd added a commit that referenced this pull request Sep 13, 2026
A v0.3.0 mudou quatro coisas que o exemplo consome, e o que ele dizia sobre
elas tinha ficado falso sem nenhum teste reprovar: a API falsa imitava o
contrato velho.

- `blocked` passou a ser "a numeração não deixou a nota sair". Na
  duplicidade, o caminho é revisar a numeração; na série inativada, esgotada
  ou que trocou de modo, o motivo diz o ajuste. A tela segue sem Reemitir no
  `blocked`, porque o ajuste é fora da nota.
- A série é por ambiente. `Serie` e `GET /v1/series` ganham o `ambiente`, a
  tela Emitente diz de que ambiente é a lista, e o README recomenda
  provisionar a série de produção antes de promover.
- `reconciliando` entra na situação da nota, e `reconciliando` e
  `pendente-registro` na do cancelamento e na da carta, com o que fazer em
  cada uma.
- O histórico das cartas oferece o DACCE da carta registrada.

O README ganha os dois efeitos da v0.3.0 no `documento`: a descrição do
primeiro item trocada em homologação e a conferência de CFOP, CST e CSOSN na
NFC-e. O schema copiado passa a ser o da v0.3.1, a API falsa responde o
contrato dela, e o lock grava o `engines` que o #1 deixou para trás.

O smoke em homologação, contra a v0.3.1 no ar, foi feito pelo dono e passou;
a tag testada declarada no README é a v0.3.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@betogd
betogd deleted the claude/great-albattani-nn33cl branch September 13, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants