Pular para o conteúdo principal

Licenciamento

O ecossistema atual de licenças H1 combina o servidor de licenças (h1-license-server: Next.js + PostgreSQL), o pacote npm @hasarbrasildesenvolvimento/h1-sdk (subpaths /licenses, /hub, /contracts) e os produtos da linha H1 Tech (Gestão de Ativos, Impressão, Middleware, All-in-One).

No backend da Gestão de Ativos (e produtos equivalentes), o cliente de licença é inicializado em bootLicense(); rotas sensíveis usam o middleware licenseGuard; o front consome GET /license/status para banners e avisos.


Visão geral da arquitetura

CamadaPapel
h1-license-serverEmite leases (POST /api/v1/activate), recebe heartbeats (POST /api/v1/heartbeat), expõe chave pública (GET /api/v1/public-key), administra licenças e exporta .lic
h1-sdk /licensesLicenseClient (online/híbrido) e OfflineLicenseClient (arquivo .lic + verificação Ed25519)
h1-sdk /hubPublicação de eventos canônicos via pg-boss na base do servidor de licenças (EVENTS_DATABASE_URL)
h1-sdk /contractsTipos e nomes de eventos compartilhados entre backends e o servidor de licenças

Fluxo típico online: ativação com fingerprint da máquina → JWT assinado (Ed25519) com janela de lease (lease_duration_h, padrão 48 h) → heartbeat periódico (padrão 30 min) renova o lease e envia métricas.


Modos de implantação

Existem três topologias; o produto (código HSBR_*) é o mesmo em qualquer modo. A distinção online vs híbrido é definida no cadastro da licença no painel administrativo (type: "hybrid"), não por variável de ambiente separada no cliente — o cliente online usa o mesmo conjunto de env vars; em modo híbrido há cache local criptografado (AES-256-GCM) do token para sobreviver a quedas de rede e reinícios.

ModoRedeFonte do tokenHeartbeatRenovação
OnlineSempre alcança o servidorPOST /api/v1/activateSim (~30 min, configurável)Automática
HíbridoConecta na subida; tolera offlineServidor + cache em discoBest-effortRetoma quando o servidor voltar
OfflineAir-gap (sem internet)Arquivo .lic + verificação localNãoManual: substituir o .lic

Comportamento na carência (online / híbrido)

Os valores exatos vêm da licença (lease_duration_h, grace_period_days). Conceito:

PeríodoStatusComportamento
Dentro de lease_duration_h desde o último contato válidoAtivoOperação normal
Entre fim do lease e fim da carênciaExpirado (soft)Avisos; operações continuam
Após lease_duration_h + grace_period_daysExpirado (hard)Respostas HTTP 402 nas rotas protegidas por licenseGuard

Offline (air-gap)

  1. Criar a licença no painel do servidor H1.
  2. Exportar o arquivo .lic (botão “Baixar .lic” ou script CLI do servidor, por exemplo npx tsx scripts/export-lic-file.ts <license-key> license.lic).
  3. Obter a chave pública para verificação JWT: GET https://<servidor>/api/v1/public-key → JSON JWK (endpoint sem autenticação).
  4. Copiar .lic (e a chave, quando não embutida) para o servidor do cliente.

O .lic é um JWT assinado (Ed25519 / EdDSA) com claims de tenant, produto (aud), limites, features, validade, etc. O cliente OfflineLicenseClient do SDK valida a assinatura localmente — sem heartbeat e sem chamadas de rede.

Na Gestão de Ativos-Back, com watchFile: true (padrão), a troca do arquivo .lic é detectada e recarregada em até ~30 segundos, sem reiniciar o processo.


Pacote SDK (@hasarbrasildesenvolvimento/h1-sdk)

Publicado no GitHub Packages no escopo @hasarbrasildesenvolvimento. Importe sempre por subpath para não puxar dependências desnecessárias:

import { LicenseClient, OfflineLicenseClient } from "@hasarbrasildesenvolvimento/h1-sdk/licenses";

Superfícies do pacote:

  • /licenses — ativação, heartbeat, cache cifrado, modo offline.
  • /hubbootPublisher / publishEvent sobre pg-boss na base do servidor de licenças.
  • /contracts — tipos e constantes dos eventos canônicos (versão única entre consumidores e o servidor).

Instalação exige .npmrc apontando o registry GitHub Packages e token GITHUB_TOKEN com read:packages (ver README do repositório do SDK).


Variáveis de ambiente (backend)

Detecção automática do modo (detectMode)

Variáveis definidasModoCliente SDK
LICENSE_FILE_PATHOfflineOfflineLicenseClient
LICENSE_SERVER_URL + LICENSE_KEYOnline (e registro híbrido no servidor)LicenseClient
Nenhuma das combinações acimaNão configuradoNenhum — desenvolvimento sem enforcement

Online / híbrido

VariávelObrigatórioPadrão / notas
LICENSE_SERVER_URLSim*URL base do servidor (ex.: https://license.h1tech.com.br)
LICENSE_KEYSim*UUID da licença no painel admin
LICENSE_PRODUCTNãoEx.: HSBR_ASSETS, HSBR_ALL1
LICENSE_DEVICE_LABELNãoRótulo amigável da instância
LICENSE_CACHE_PATHNão./.license/cache.enc
LICENSE_HEARTBEAT_MINUTESNão30
LICENSE_SNAPSHOT_INTERVAL_MINUTESNão60 (tick de segurança para snapshots)
LICENSE_SNAPSHOT_DEBOUNCE_MSNão5000
EVENTS_DATABASE_URLNãoConnection string PostgreSQL do servidor de licenças (fila pg-boss); se ausente, publicações de eventos são ignoradas silenciosamente

*Em ambientes de desenvolvimento local, o backend pode subir sem licença com aviso — enforcement desativado (unconfigured).

Offline

VariávelObrigatórioNotas
LICENSE_FILE_PATHSimCaminho do .lic
LICENSE_PUBLIC_KEY_PATH ou HSBR_PUBLIC_KEY_FILEUm dos dois**Arquivo JWK de chave pública
HSBR_PUBLIC_KEY_JWKAlternativa**JWK em Base64 (útil em Docker/secrets)
LICENSE_PRODUCTNãoFiltro / audience opcional

** Em muitos fluxos o .lic gerado pelo painel já permite validação; chaves explícitas por env têm prioridade quando presentes. Comente LICENSE_SERVER_URL, LICENSE_KEY e EVENTS_DATABASE_URL no modo offline — não são usados.

Leitores FX / middleware (referência)

Instalações embarcadas podem usar variáveis como HIOT_LICENSE_SERVER, HIOT_LICENSE_KEY, HIOT_LICENSE_FILE, HIOT_ENROLLMENT_CODE, etc., conforme o pacote de deploy — detalhes no repositório do firmware / hiot_server.


Hub de integração e uso

Além da quota “em tempo real” no heartbeat, o backend pode publicar eventos canônicos (impressão confirmada, registro de ativos, snapshot de licença, etc.) para o worker do servidor de licenças consumir — por exemplo ingestão de license.snapshot.v1 na linha da licença sem depender de cron.

Isso é independente do fluxo de licença direto: falhas no bus são logadas e não revertem transações de negócio já commitadas.


Produtos e limites padrão

ProdutoCódigoLimites padrão (resumo)
Gestão de AtivosHSBR_ASSETS10 dispositivos, 3 impressoras, 50k tags ativas, 100k tags/mês
Serviço de ImpressãoHSBR_PRINTING5 impressoras, 200k tags/mês
Middleware RFIDHSBR_MIDDLEWARE20 dispositivos
All-in-OneHSBR_ALL120 dispositivos, 5 impressoras, 100k tags ativas, 200k tags/mês

Features típicas (exemplos no JWT): api_access, custom_zpl, offline_mode, pacotes, order_tracking — dependem do produto e da licença.


Fiscalização

A política é intencionalmente branda:

  • Exceder cotas não bloqueia operações: o SDK acumula warnings; o backend pode expor cabeçalhos como X-License-Warnings e o front exibe banner.
  • Bloqueio duro (HTTP 402) apenas em estados terminais, por exemplo: licença revogada ou suspensa, expirada além da carência, ainda não válida (valid_from futuro), ou ativação liberada no servidor (activation_inactive).

Recursos opcionais podem usar requireFeature('nome') após licenseGuard: sem a feature, o fluxo pode seguir com aviso em res.locals em vez de bloquear (conforme política atual do middleware).


Chave pública (modo offline)

MétodoUso típico
Arquivo public-key.json em discoLICENSE_PUBLIC_KEY_PATH
Base64 no ambienteHSBR_PUBLIC_KEY_JWK
Busca automática no cliente onlineautoFetchPublicKey (padrão em cenários conectados)

Endpoint público:

GET /api/v1/public-key{ "keys": [ { "kty": "OKP", "crv": "Ed25519", ... } ] }


Status exposto ao front (GET /license/status)

Endpoint do backend da aplicação (autenticado), não do servidor de licenças. Agrega estado do LicenseClient ou OfflineLicenseClient.

Exemplo (online, configurado):

{
"configured": true,
"active": true,
"status": "active",
"mode": "online",
"warnings": [],
"has_critical": false,
"limits": {
"max_devices": 20,
"max_printers": 5,
"max_active_tags": 100000,
"max_tags_month": 200000
},
"tenant": { "id": "…", "name": "Empresa Exemplo" },
"product": "HSBR_ALL1",
"valid_until": "2026-12-31T23:59:59.000Z",
"lease_expires_at": "2026-05-14T12:00:00.000Z"
}

Em modo não configurado (configured: false, mode: "unconfigured"), active vem true para não travar desenvolvimento local.


Perguntas frequentes

Preciso de internet?
Não obrigatoriamente. O modo offline opera só com .lic e chave pública. Com internet intermitente, use híbrido (cadastro no painel) para cache e renovação automática quando a rede voltar.

Como renovo offline?
Gere um novo .lic no painel (ou CLI), copie sobre o arquivo anterior; o serviço recarrega em até ~30 s se watchFile estiver ativo.

Posso mudar de modo sem reinstalar?
Sim: ajuste as variáveis de ambiente (online ↔ offline), reinicie o processo e, se aplicável, troque o tipo da licença no painel para refletir híbrido.

Onde está a documentação técnica completa dos modos?
No repositório h1-license-server, arquivo docs/license-modes.md, e no repositório da Gestão de Ativos-Back, docs/license-integration.md (integração Hub + lista de eventos).


Checklist rápido

Online / híbrido

  • Licença criada no painel (tenant + produto + limites).
  • LICENSE_SERVER_URL e LICENSE_KEY no .env do backend.
  • (Opcional) EVENTS_DATABASE_URL para o Hub.
  • Subida sem erro de ativação; heartbeats regulares nos logs.
  • GET /license/status com active: true.

Offline

  • .lic exportado e chave pública disponível quando necessário.
  • LICENSE_FILE_PATH (+ chave pública via arquivo ou env).
  • LICENSE_SERVER_URL / LICENSE_KEY / EVENTS_DATABASE_URL comentados ou removidos.
  • GET /license/status com mode: "offline" e active: true.