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
| Camada | Papel |
|---|---|
| h1-license-server | Emite 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 /licenses | LicenseClient (online/híbrido) e OfflineLicenseClient (arquivo .lic + verificação Ed25519) |
h1-sdk /hub | Publicação de eventos canônicos via pg-boss na base do servidor de licenças (EVENTS_DATABASE_URL) |
h1-sdk /contracts | Tipos 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.
| Modo | Rede | Fonte do token | Heartbeat | Renovação |
|---|---|---|---|---|
| Online | Sempre alcança o servidor | POST /api/v1/activate | Sim (~30 min, configurável) | Automática |
| Híbrido | Conecta na subida; tolera offline | Servidor + cache em disco | Best-effort | Retoma quando o servidor voltar |
| Offline | Air-gap (sem internet) | Arquivo .lic + verificação local | Não | Manual: 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íodo | Status | Comportamento |
|---|---|---|
Dentro de lease_duration_h desde o último contato válido | Ativo | Operação normal |
| Entre fim do lease e fim da carência | Expirado (soft) | Avisos; operações continuam |
Após lease_duration_h + grace_period_days | Expirado (hard) | Respostas HTTP 402 nas rotas protegidas por licenseGuard |
Offline (air-gap)
- Criar a licença no painel do servidor H1.
- Exportar o arquivo
.lic(botão “Baixar .lic” ou script CLI do servidor, por exemplonpx tsx scripts/export-lic-file.ts <license-key> license.lic). - Obter a chave pública para verificação JWT:
GET https://<servidor>/api/v1/public-key→ JSON JWK (endpoint sem autenticação). - 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./hub—bootPublisher/publishEventsobre 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 definidas | Modo | Cliente SDK |
|---|---|---|
LICENSE_FILE_PATH | Offline | OfflineLicenseClient |
LICENSE_SERVER_URL + LICENSE_KEY | Online (e registro híbrido no servidor) | LicenseClient |
| Nenhuma das combinações acima | Não configurado | Nenhum — desenvolvimento sem enforcement |
Online / híbrido
| Variável | Obrigatório | Padrão / notas |
|---|---|---|
LICENSE_SERVER_URL | Sim* | URL base do servidor (ex.: https://license.h1tech.com.br) |
LICENSE_KEY | Sim* | UUID da licença no painel admin |
LICENSE_PRODUCT | Não | Ex.: HSBR_ASSETS, HSBR_ALL1 |
LICENSE_DEVICE_LABEL | Não | Rótulo amigável da instância |
LICENSE_CACHE_PATH | Não | ./.license/cache.enc |
LICENSE_HEARTBEAT_MINUTES | Não | 30 |
LICENSE_SNAPSHOT_INTERVAL_MINUTES | Não | 60 (tick de segurança para snapshots) |
LICENSE_SNAPSHOT_DEBOUNCE_MS | Não | 5000 |
EVENTS_DATABASE_URL | Não | Connection 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ável | Obrigatório | Notas |
|---|---|---|
LICENSE_FILE_PATH | Sim | Caminho do .lic |
LICENSE_PUBLIC_KEY_PATH ou HSBR_PUBLIC_KEY_FILE | Um dos dois** | Arquivo JWK de chave pública |
HSBR_PUBLIC_KEY_JWK | Alternativa** | JWK em Base64 (útil em Docker/secrets) |
LICENSE_PRODUCT | Não | Filtro / 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
| Produto | Código | Limites padrão (resumo) |
|---|---|---|
| Gestão de Ativos | HSBR_ASSETS | 10 dispositivos, 3 impressoras, 50k tags ativas, 100k tags/mês |
| Serviço de Impressão | HSBR_PRINTING | 5 impressoras, 200k tags/mês |
| Middleware RFID | HSBR_MIDDLEWARE | 20 dispositivos |
| All-in-One | HSBR_ALL1 | 20 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-Warningse 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_fromfuturo), 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étodo | Uso típico |
|---|---|
Arquivo public-key.json em disco | LICENSE_PUBLIC_KEY_PATH |
| Base64 no ambiente | HSBR_PUBLIC_KEY_JWK |
| Busca automática no cliente online | autoFetchPublicKey (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_URLeLICENSE_KEYno.envdo backend. - (Opcional)
EVENTS_DATABASE_URLpara o Hub. - Subida sem erro de ativação; heartbeats regulares nos logs.
-
GET /license/statuscomactive: true.
Offline
-
.licexportado 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_URLcomentados ou removidos. -
GET /license/statuscommode: "offline"eactive: true.