Case 01Fiscal e ERP

Steuer

Notas fiscais que chegam sozinhas e entram conferidas no Linx.

Plataforma fiscal multiempresa que capta toda NF-e, CT-e e NFS-e emitida contra os CNPJs do cliente, guarda XML e PDF prontos para consulta e lança a entrada conferida direto no banco do ERP Linx, dentro da rede da loja. O time fiscal para de redigitar nota e passa a tratar só as exceções que o sistema aponta.

Cliente
Redes de varejo de moda com ERP Linx · matriz e filiais
Período
2024 — 2026
Equipe
Squad de 5 pessoas
Papel
Engenheiro full stack · da captura fiscal à entrada no Linx
Stack
Bun · Fastify · TypeScript · Zod · Prisma · MySQL
Confidencialidade
Dados de clientes preservados
02

Resultados em números

  • 12 milnotas fiscais processadas por mêsNF-e, CT-e e NFS-e somando os clientes
  • 90%das entradas no Linx sem digitaçãoo time fiscal atua só nas exceções
  • 42tabelas do Linx integradas pelo gatewayentradas, itens, impostos, estoque, pedidos e cadastros
  • 60 sentre verificações de saúde de cada túnel3 falhas seguidas disparam a reconexão automática
03

O contexto do negócio

Cliente
Redes de varejo de moda com ERP Linx · matriz e filiais
Período
2024 — 2026

Uma rede de moda recebe nota fiscal o dia inteiro: mercadoria de fornecedores, romaneios vindos do centro de distribuição, frete de transportadoras e serviços contratados por cada filial. Cada documento precisa ser localizado, atribuído ao CNPJ certo, conferido contra o pedido de compra e lançado no Linx, que roda em SQL Server no servidor local de cada cliente. Quando essa entrada depende de alguém baixando XML e redigitando item por item, o estoque atrasa, o fechamento fiscal aperta e cada vínculo errado vira retrabalho contábil.

04

O desafio

O desafio tinha três frentes. A captura dependia de uma API paginada por cursor, e qualquer interrupção no meio de um período podia deixar notas para trás. O grupo tem matriz e filiais com acessos diferentes, então cada documento e cada tela precisavam respeitar a empresa certa. E o Linx não está na nuvem: fica atrás do firewall de cada rede, sem endereço público, e só aceita a entrada quando pedido, fornecedor, filial e impostos batem.

  1. Captura que não perde nota

    O provedor pagina por cursor dentro de uma janela de datas. Se a execução cai no meio e a janela avança, documentos somem sem ninguém perceber — e o primeiro sincronismo de um cliente cobre mais de um ano de notas.

  2. Matriz, filiais e acessos distintos

    Uma mesma rede tem dezenas de CNPJs, usuários que só enxergam a própria filial e perfis com permissões diferentes por tela. Um dado cruzando de uma empresa para outra seria inaceitável.

  3. ERP dentro da rede do cliente

    O banco do Linx roda on-premise. Alcançá-lo sem abrir porta para a internet e gravar a entrada sem duplicar nota nem deixar registro pela metade era a parte mais delicada.

05

O que entreguei

Dividi o produto em quatro serviços com fronteiras claras. O backend central em Bun e Fastify capta as notas por empresa, registra cada cabeçalho como pendente e publica o lote no RabbitMQ, com o n8n orquestrando agenda e consumo. O painel em Laravel concentra login, permissões e a operação fiscal. O gateway Linx valida e grava a entrada no banco do ERP, alcançado por um agente Windows em .NET 8 que mantém um túnel WireGuard aberto de dentro para fora.

  1. Captura com retomada

    NF-e, CT-e e NFS-e por CNPJ, com histórico desde janeiro do ano anterior e retomada exata do cursor após qualquer queda.

  2. Entrada automática no Linx

    Prévia validada, conferência nota × pedido item a item e gravação atômica pelas procedures do próprio Linx.

  3. Steuer Connector

    Agente Windows com instalador MSI, túnel WireGuard, heartbeat e reconexão automática — o ERP segue sem porta exposta.

  4. XML e PDF sob demanda

    XML arquivado por empresa no S3, download por URL assinada e DANFE gerado na hora, com acesso limitado ao tenant.

06

Como funciona

Siga o trabalho atravessando o sistema, etapa por etapa, ou clique em qualquer componente do quadro para ver o que ele faz.

12 componentes · 13 conexões · 5 camadas

Clique em um componente para ver detalhes←→para navegarPercorra o fluxo abaixo

EXTERNOSEFAZ eprefeiturasDF-eEXTERNOProvedoresfiscaisPlugStorage /…SERVIÇOOrquestradorn8nSERVIÇOBackend centralBun / FastifyBANCOArquivo de XMLAWS S3FILAFila deimportaçãoRabbitMQBANCOBase fiscalMySQL / PrismaSAÍDAPainel SteuerLaravelSERVIÇOGateway LinxFastify / PrismaSERVIÇOInstaladorWiX MSISEGURANÇASteuer Connector.NET 8 / WireGuardEXTERNOERP LinxSQL Server

arraste para ver o fluxo

Legenda

  • Síncrono
  • Assíncrono
  • Canal seguro
  • Integração externa
Descrição textual do fluxo
  1. De SEFAZ e prefeituras para Provedores fiscais — Distribuição DF-e (integração externa).
  2. De Provedores fiscais para Backend central — Cabeçalhos por cursor (integração externa).
  3. De Orquestrador para Backend central — Dispara captura (síncrono).
  4. De Backend central para Fila de importação — Publica o lote (assíncrono).
  5. De Backend central para Base fiscal — Registra pendência (síncrono).
  6. De Fila de importação para Base fiscal — Grava nota e itens (assíncrono).
  7. De Fila de importação para Arquivo de XML — Arquiva o XML (assíncrono).
  8. De Base fiscal para Painel Steuer — Consulta por empresa (síncrono).
  9. De Arquivo de XML para Painel Steuer — URL assinada (síncrono).
  10. De Painel Steuer para Gateway Linx — Prévia e confirmação (síncrono).
  11. De Gateway Linx para Steuer Connector — Túnel WireGuard (canal seguro).
  12. De Instalador para Steuer Connector — Provisiona (síncrono).
  13. De Steuer Connector para ERP Linx — Proxy restrito (canal seguro).

Percorra o fluxo

←→trocam de etapa

6 etapas

Do começo ao fim

Escolha uma etapa ou pressione Reproduzir para acompanhar o fluxo inteiro. Enquanto isso, o quadro destaca por onde o trabalho passa.

07

Componentes do sistema

  1. Captura incremental por empresa

    O que resolve
    Trazer todas as notas emitidas contra cada CNPJ, inclusive o histórico, sem nunca pular uma página.
    Como funciona
    Para cada empresa ativa, o backend lê a última execução: se ela parou no meio, retoma com o mesmo cursor e a mesma janela; se terminou, monta a próxima janela mensal. No primeiro acesso, sincroniza desde janeiro do ano anterior, mês a mês, até alcançar o dia atual. Cada página grava cursor, período e totais, e o laço só termina quando a janela chega a hoje com a página vazia.

    Bun · Fastify · Prisma · MySQL

  2. Fila de importação e arquivo fiscal

    O que resolve
    Separar a descoberta das notas do trabalho pesado de baixar, arquivar e interpretar cada XML.
    Como funciona
    Os cabeçalhos entram como pendentes, com a chave de acesso única no banco, e o lote vai para uma fila durável no RabbitMQ com mensagens persistentes. O n8n consome a fila, o backend baixa o XML, arquiva no S3 por empresa e grava cabeçalho e itens conforme a situação — autorizada, cancelada, denegada ou em contingência. Uma falha marca a nota com erro e ela volta na execução seguinte.

    RabbitMQ · n8n · AWS S3 · TypeScript

  3. Painel fiscal multiempresa

    O que resolve
    Dar a cada pessoa do grupo a visão exata da sua empresa, com o nível de acesso que o seu papel exige.
    Como funciona
    Um escopo global do Laravel filtra cada consulta pela empresa do usuário logado, de modo que quem é de filial enxerga só a própria filial e a matriz enxerga o grupo. Permissões por menu definem se a pessoa não acessa, consulta ou opera cada tela. Ali ficam consulta e download de XML e PDF, DANFE, apuração, relatórios por CFOP e de entradas × saídas e a gestão de NFS-e.

    Laravel · PHP 8.2 · MySQL

  4. Prévia assinada da entrada

    O que resolve
    Mostrar ao operador exatamente o que vai entrar no Linx e impedir que isso mude até a confirmação.
    Como funciona
    O gateway resolve fornecedor, filial, natureza de operação, série e pedido de compra, localiza o romaneio de origem na loja ou no CD e compara quantidade e valor item a item, com tolerância de um centavo. A prévia volta com um snapshot assinado em HMAC-SHA256; na confirmação o hash é recalculado e qualquer alteração é recusada. Para NFS-e, 26 códigos de diagnóstico apontam o que falta no cadastro do Linx.

    Fastify · Zod · Prisma · SQL Server

  5. Gravação atômica e idempotente

    O que resolve
    Garantir que cada nota entre no ERP uma única vez, inteira ou não entre.
    Como funciona
    A confirmação adquire uma chave de idempotência em duas camadas — 5 minutos em memória e 30 minutos no banco — e checa se a nota já existe no Linx. Numa única transação, insere em ENTRADAS e executa LX_ORQUESTRA_ENTRADA, que gera romaneio e impostos. O código de transação sai da combinação entre tipo fiscal e origem: pedido novo, CD ou loja. Se a procedure falha, o rollback não deixa registro órfão.

    TypeScript · Prisma · SQL Server · Linx

  6. Steuer Connector

    O que resolve
    Ligar o banco do Linx à plataforma sem expor nada da rede do cliente.
    Como funciona
    Serviço Windows em .NET 8 com cinco estados explícitos. Ativa com um token de uso único, guarda a configuração cifrada com DPAPI, sobe o túnel WireGuard e um proxy TCP que só encaminha para o host e a porta do banco autorizados. Heartbeat a cada 60 s, reconexão após 3 falhas, watchdog de 2 minutos e backoff exponencial com jitter. Um painel local fala com o serviço por Named Pipe, e o MSI verifica o ambiente antes de liberar a ativação.

    C# · .NET 8 · WireGuard · WiX

08

Decisões que sustentam o sistema

  1. Log de execução, não cursor solto

    Cada página capturada grava cursor, janela de datas e totais. Uma queda vira uma retomada exata, e o sincronismo histórico de um cliente novo avança mês a mês sem sobrecarregar o provedor nem perder documento.

  2. Persistir antes de distribuir

    Toda nota vira um registro pendente, com chave de acesso única, antes de entrar na fila. Se um consumidor cai, o estado está no banco e o reprocessamento não duplica nada — a fila acelera, mas nunca é a única cópia da verdade.

  3. Prévia assinada, confirmação idempotente

    Separar prévia e confirmação deixa o operador no controle, e o hash HMAC garante que o que ele aprovou é o que será gravado. A chave de idempotência protege contra duplo clique, timeout e reenvio: a segunda chamada recebe a mesma resposta, sem nova entrada.

  4. Túnel de dentro para fora, proxy restrito

    Nenhuma rede de varejo abriria porta para o ERP. O agente inicia o WireGuard com keepalive de 25 s, o hub só permite tráfego do peer para o host e a porta do banco, e as credenciais do banco nunca são enviadas ao agente.

09

Resultado para o negócio

  • O lançamento de uma compra no Linx caiu de cerca de 6 minutos para menos de 1 minuto por nota, sem redigitar nenhum item.

  • Nenhuma nota fica para trás: cada página capturada grava janela e cursor, e a execução seguinte retoma exatamente de onde a anterior parou.

  • Zero entrada duplicada ou pela metade no ERP: chave de idempotência, checagem de nota já lançada e uma única transação com as procedures do Linx.

  • Um novo cliente entra em produção no mesmo dia: o instalador prepara WireGuard, serviço e firewall, a ativação usa um código de uso único e o ERP continua sem porta aberta para a internet.

10

Meu papel

Papel
Engenheiro full stack · da captura fiscal à entrada no Linx
Equipe
Squad de 5 pessoas

Construí o Steuer de ponta a ponta, do primeiro serviço à versão que hoje processa milhares de notas por mês. Desenhei a captura incremental e o modelo de filas, escrevi o gateway que conversa direto com o banco do Linx — prévia, conferência, idempotência e as procedures de entrada —, levei o isolamento por empresa do painel até o middleware e criei o Steuer Connector, o agente que liga cada cliente à plataforma. Também conduzi a implantação e a operação em produção com cada rede.

Pelo que respondi

  • Projetei a captura incremental em Bun, Fastify e Prisma: log de execução por empresa, janela mensal de datas e retomada pelo último cursor.
  • Modelei a fila durável de importação no RabbitMQ e os fluxos do n8n que agendam a captura e consomem cada lote.
  • Escrevi o gateway Linx: 27 rotas, 42 tabelas do ERP mapeadas, prévia assinada com HMAC e confirmação idempotente.
  • Implementei o isolamento por empresa ponta a ponta: escopo global no Laravel, contexto por requisição no gateway e modo estrito nas rotas de escrita.
  • Desenvolvi o Steuer Connector em C#/.NET 8: máquina de estados, túnel WireGuard, proxy TCP restrito e controle local por Named Pipe.
  • Automatizei o build do instalador MSI no GitHub Actions, versionado a cada execução e publicado no S3; os serviços web rodam em Docker.
11

Stack por camada

  • Backend e gateway

    • Bun
    • Fastify
    • TypeScript
    • Zod
    • Prisma
  • Dados e filas

    • MySQL
    • SQL Server
    • RabbitMQ
    • n8n
    • AWS S3
  • Painel

    • Laravel
    • PHP 8.2
    • Blade
  • Agente e entrega

    • C#
    • .NET 8
    • WireGuard
    • WiX
    • GitHub Actions
    • Docker
12

O que levo deste projeto

  1. Quando o ERP mora na rede do cliente, a conectividade é parte do produto, não um detalhe de implantação. Tratá-la como software, com estados, testes e telemetria, evitou retrabalho em cada nova rede.

  2. Estado explícito vence inferência: quando o agente passou a ser dono do próprio ciclo de vida, com máquina de estados e IPC, o falso “conectando” desapareceu e o suporte passou a ler o status real.

Próximo case 02 Kippis Segurança do trabalho no bolso de quem está na obra.

Qual é o próximo sistema que a sua empresa precisa?

Me conte o contexto: um problema, uma ideia ou um sistema que precisa evoluir. Eu respondo com um caminho técnico claro e o primeiro passo para tirar do papel.