Pular para o conteúdo principal

Lacuna Bulk Signer

O Lacuna Bulk Signer é um serviço de assinatura em lote on premises para cenários compatíveis com a ICP-Brasil. Ele recebe arquivos de origens automatizadas (pastas monitoradas ou upload via REST), processa-os através de um pipeline de assinatura controlado e produz saídas assinadas e verificadas — com histórico operacional completo, um dashboard para o operador e recuperação automática na reinicialização.

O Bulk Signer foi projetado para rodar dentro da sua própria infraestrutura: um único serviço que monitora pastas (ou aceita uploads), assina, verifica e promove os resultados para uma pasta de saída. Não há atualização automática, e uma instalação padrão não faz nenhuma conexão de saída — assinatura remota, Azure Key Vault e telemetria são todos opcionais.

Funcionalidades

  • Formatos de assinatura. CAdES (.p7m), PAdES (PDF) e XAdES (XML) — todos sob a política ADR-Básica da ICP-Brasil por padrão. A nomenclatura de saída por perfil preserva a extensão original (remessa.signed.rem) ou grava CAdES em formato PEM quando um sistema a jusante exigir.
  • Origens de certificado. Arquivos PKCS#12 (.pfx / .p12), HSMs e smart cards PKCS#11, o repositório de certificados do Windows e o Azure Key Vault (a chave permanece no cofre e assina remotamente). O .pfx ou .cer pode ser lido do Azure Blob Storage em vez do disco local. A origem é escolhida inteiramente por configuração, globalmente ou por perfil de assinatura.
  • Dois caminhos de entrada. Uma pasta de entrada monitorada (com um detector de estabilidade, para que arquivos gravados pela metade não sejam capturados cedo demais) e um endpoint POST /api/files para clientes programáticos.
  • Arquivos de pagamento CNAB240. Opcional por perfil: interpreta uma remessa do Banco do Brasil, recusa-se a assinar uma que não esteja em conformidade ou cujas datas de pagamento já tenham passado, e mostra ao operador o total, o pagador e cada pagamento individual.
  • Etapa de aprovação. Retém um arquivo de pagamento sob um quórum de aprovadores nomeados antes que qualquer assinatura exista. Uma única rejeição é um veto; as aprovações são vinculadas aos bytes do arquivo, e a regra é congelada no job, de modo que editar a configuração nunca consegue liberar um arquivo retido. Os aprovadores têm sua própria fila, com aprovação em lote e exportação para Excel — e um segundo fator TOTP opcional, que pede ao aprovador que comprove sua presença antes de uma decisão.
  • Pipeline recuperável. Os jobs fluem por uma fila durável com pausa/retomada que sobrevive a uma reinicialização. Se o serviço for interrompido no meio do percurso, uma varredura de recuperação na inicialização move para o lado qualquer job interrompido, de modo que nada se perca silenciosamente.
  • Criptografia pós-assinatura opcional (BSENC v1). Criptografa os artefatos assinados em repouso com AES-256-GCM quando habilitada. Acompanha scripts de referência de descriptografia em Python e PowerShell.
  • Integração com o Lacuna Signer (por perfil). Encaminha uma pasta para o Lacuna Signer para assinatura humana, em vez de assinar com um certificado mantido no host.
  • Autenticação, de duas formas. Uma única chave de API atende tanto ao dashboard do operador (via cookie de sessão) quanto a clientes programáticos (via cabeçalho X-API-Key) — ou ative o login opcional pelo Microsoft Entra ID, com as app roles Administrator e Approver, deixando a chave de API REST intacta.
  • Dashboard do operador, em inglês ou português do Brasil. Um console web com status ao vivo, histórico de jobs, ações de repetição/cancelamento/reescaneamento, um visualizador de exceções recentes e uma trilha de auditoria. O idioma é a escolha do leitor em cada navegador, não uma configuração do servidor.
  • Armazenamento e base, locais ou no Azure. A árvore de trabalho pode permanecer em disco local ou viver em um compartilhamento do Azure Files; a base operacional pode continuar em SQLite ou migrar para SQL Server / Azure SQL, sob o seu próprio regime de backup e DR. As duas escolhas são independentes.
  • Escala horizontal no Azure App Service (opcional). Cluster:Enabled executa mais de uma instância ativa sobre uma única base operacional e um único compartilhamento de trabalho: um job nunca é processado duas vezes, o trabalho de uma instância que morre é assumido em vez de ficar órfão, e o pipeline continua assinando enquanto um host está fora. Desabilitado por padrão, e desabilitado é, byte a byte, o produto de instância única. Veja Azure App Service e, antes disso, seus limites.
  • Backup do banco de dados (implantações com SQLite). Backups agendados ou sob demanda da base operacional para um caminho local, um bucket compatível com S3 ou um container do Azure Blob, com uma contagem de retenção.
  • Visibilidade de desempenho. Um painel de tempos por etapa (espera na fila, assinatura, verificação, saída) com vazão e uma divisão entre Local e Remoto — mantido na base operacional, de modo que sobrevive a reinicializações e descreve um cluster inteiro — além da exportação opcional para o Azure Application Insights.
  • Observabilidade. Logs estruturados com mascaramento automático de segredos e um destino opcional em Azure Table para hosts cujo disco não sobrevive a uma reinicialização, um endpoint de métricas Prometheus e um envelope de erro ProblemDetails (RFC 9457) com códigos estáveis legíveis por máquina.
  • Limitação de taxa por IP. Limites configuráveis de janela fixa nos endpoints de upload, ação, aprovação e exportação, com suporte opcional a cabeçalhos encaminhados, para que o cliente real seja contabilizado por trás de um proxy ou balanceador de carga.
  • Implantação em múltiplos alvos. O mesmo serviço roda como unidade systemd no Linux, Serviço do Windows, container Docker, Azure Web App ou processo de console em primeiro plano.

Como funciona

pasta input/ ───┐
├──▶ Fila ──▶ Claim ──▶ [gates] ──▶ Assina ──▶ Verifica ──┬──▶ output/
POST /api/files ┘ │ (output/*.enc
em caso de │ quando a cripto-
falha └──▶ error/ grafia
está ativa)

[gates], ambos opcionais por perfil de assinatura e totalmente ignorados quando não configurados:
Parse CNAB240 — recusa uma remessa não conforme, ou cujas datas de pagamento já passaram
Etapa de aprovação — retém em AwaitingApproval até que um quórum de pessoas nomeadas aprove

Cada etapa é registrada na base operacional (histórico de jobs + eventos de sistema) e no arquivo de log estruturado. O dashboard e a API REST leem os mesmos dados e disparam as mesmas ações.

Início rápido — Docker

Usando o pacote de implantação fornecido pela Lacuna Software, mais a imagem do repositório privado de imagens Docker da Lacuna — veja Obtendo o produto:

cd deploy/docker

docker login <registry-da-lacuna> --username <usuário-do-registry> # o compose nomeia o repositório

cp .env.sample .env
mkdir -p data logs config
cp ../appsettings.Production.json.sample config/appsettings.Production.json

# Edite config/appsettings.Production.json e .env — no mínimo:
# - Signing__PkiSdkLicense (string de licença em base64 fornecida pela Lacuna Software)
# - Auth__ApiKey (>= 16 caracteres; use um valor aleatório)
# - Signing:Certificate:Pfx:Path (e um arquivo .pfx irmão em config/) — ou escolha outra origem

sudo chown -R 1654:1654 data logs # o container roda como UID 1654 em hosts Linux
docker compose up -d
curl http://localhost:8080/api/health

Acesse o dashboard em http://localhost:8080/ usando a Auth:ApiKey configurada.

Para instalações com systemd no Linux, Serviço do Windows e em primeiro plano, veja Instalação.

Documentação

AssuntoPágina
Instalar o serviço em qualquer alvo suportadoInstalação
Escalar horizontalmente no Azure App Service, passo a passoAzure App Service (modo cluster)
O que rodar mais de uma instância não lhe dáAlta disponibilidade e seus limites
Cada chave do appsettings.json (tipo, padrão, override por ambiente)Configuração
Escolher e configurar uma origem de certificado (PFX / PKCS#11 / repositório do Windows / Azure Key Vault)Certificados
Tratamento de segredos, rotação da chave de API, ACLs de arquivos, mascaramento de logsSegurança
Operação do dia a dia e o ciclo de vida do jobOperação
O console Blazor do operadorDashboard
Interpretar o painel de tempos por etapaEstatísticas de jobs
Exportação opcional para o Azure Application InsightsTelemetria
A superfície REST e o envelope de erro marcado com codeAPI REST
Criptografia pós-assinatura (BSENC v1)Criptografia
Encaminhar uma pasta pelo Lacuna Signer para assinatura humanaIntegração com o Lacuna Signer
Interpretar e validar arquivos de pagamento do Banco do BrasilArquivos de pagamento CNAB240
Reter um arquivo de pagamento sob um quórum de aprovadoresAprovações
Padrões de retenção e o que é (e o que não é) podado automaticamente hojeRetenção
Modos de falha e diagnósticoDiagnóstico de problemas
Scripts de referência — descriptografia, provisionamento do Key Vault, registro de aplicativo no EntraExemplos

Com o serviço em execução, uma referência OpenAPI ao vivo é servida em /scalar/v1.

Ordem de leitura

Se você está…Comece em
Instalando o serviço pela primeira vezInstalaçãoConfiguraçãoCertificados
Conectando um sistema automatizado à API RESTAPI RESTSegurançaDiagnóstico de problemas
Operando uma instalação existenteOperaçãoDashboardDiagnóstico de problemas
Diagnosticando vazão baixaEstatísticas de jobsCertificadosTelemetria
Mantendo a chave de assinatura fora do hostCertificadosExemplosSegurança
Habilitando a criptografiaCriptografiaSegurançaExemplos
Encaminhando uma pasta pelo Lacuna Signer (assinatura humana)Integração com o Lacuna SignerConfiguraçãoOperação
Assinando arquivos de pagamento bancárioArquivos de pagamento CNAB240AprovaçõesSegurança
Colocando uma etapa de aprovação antes do assinadorAprovaçõesConfiguraçãoSegurança
Autenticando com contas organizacionaisInstalaçãoConfiguraçãoSegurança
Rodando sem disco local durávelConfiguraçãoInstalaçãoCertificados
Rodando mais de uma instânciaAlta disponibilidade e seus limitesAzure App ServiceConfiguração
Preservando o fluxo de logs quando o disco do host não sobreviveConfiguraçãoRetenção
Pedindo um segundo fator aos aprovadoresAprovaçõesConfiguraçãoSegurança
Fazendo backup da base operacionalRetençãoConfiguração