Licenciamento
O backend H1 Tech detecta o modo de licença no startup a partir de variáveis de
ambiente (lógica em src/lib/license.ts::detectMode()). O servidor de licenças
é o h1-license-server; o back consome via @hasarbrasildesenvolvimento/h1-sdk.
Modos
A precedência é estrita e offline vence: se LICENSE_FILE_PATH existe, é
offline (mesmo que as vars de online também estejam setadas).
| Modo | Disparado por | Rede | Enforcement |
|---|---|---|---|
| Offline (air-gap) | LICENSE_FILE_PATH presente | Nenhuma — lê um .lic assinado e verifica Ed25519 localmente | Sim |
| Online / Hybrid | LICENSE_SERVER_URL e LICENSE_KEY | activate → heartbeat → cache criptografado como fallback | Sim |
| Unconfigured (dev) | nenhuma das acima | Nenhuma | Sem enforcement (loga aviso; tudo liberado) |
"Hybrid" não é um modo separado no back — usa as mesmas vars do online; a diferença ("hybrid") é uma flag no registro da licença + o comportamento de cache-fallback do mesmo
LicenseClient.
Vars — Online/Hybrid
| Var | Obrigatória | Default | Para quê |
|---|---|---|---|
LICENSE_SERVER_URL | sim | — | URL do license server (ex.: https://license.h1tech.com.br) |
LICENSE_KEY | sim | — | UUID da licença (admin UI) |
LICENSE_PRODUCT | não | HSBR_ASSETS | Código do produto (veja abaixo) |
LICENSE_HEARTBEAT_MINUTES | não | 30 | Cadência do heartbeat |
EVENTS_DATABASE_URL | não | — | Postgres do license (pg-boss / Integration Hub) |
Vars — Offline
| Var | Obrigatória | Para quê |
|---|---|---|
LICENSE_FILE_PATH | sim | Caminho do .lic (JWT assinado em Ed25519) |
LICENSE_PUBLIC_KEY_PATH (ou HSBR_PUBLIC_KEY_JWK) | recomendada | Chave pública (public-key.json / JWK) |
LICENSE_PRODUCT | não | Filtro de produto na validação |
O client offline usa watchFile: true — trocar o .lic recarrega em ~30s, sem
restart. Ao migrar para offline, comente LICENSE_SERVER_URL, LICENSE_KEY e
EVENTS_DATABASE_URL.
Produtos e limites
O código do produto vai no claim aud / LICENSE_PRODUCT:
| Produto | Código | Limites padrão | Features padrão |
|---|---|---|---|
| Gestão de Ativos | HSBR_ASSETS | 10 devices, 3 printers, 50k tags ativas, 100k/mês | api_access, custom_zpl, offline_mode |
| Printing Service | HSBR_PRINTING | 5 printers, 200k/mês | custom_zpl |
| Middleware RFID | HSBR_MIDDLEWARE | 20 devices | api_access |
| All-in-One | HSBR_ALL1 | 20 devices, 5 printers, 100k tags ativas, 200k/mês | api_access, custom_zpl, offline_mode, pacotes, order_tracking |
A licença (JWT Ed25519) carrega: tenant, aud (produto), limits
(max_devices/max_printers/max_active_tags/max_tags_month), features
(flags booleanas), exp/nbf, opcional machine_fingerprint (node-lock),
license_type (online|offline|hybrid) e key_id. Limite 0 = ilimitado.
Não existe "tier trial" no código — validade é só
valid_from/valid_until+status.
Enforcement (soft)
O modelo é soft enforcement: só estados terminais bloqueiam; estouros de quota (devices/printers/tags/prints) são medidos e avisados, nunca barrados na API.
- Bloqueio duro só em estado terminal:
revoked,suspended,expired(ou além dograce_period_days),not_yet_valid. No back, olicenseGuardresponde HTTP 402 quandoisLicenseActive()é falso; a API do license server responde 403 emactivate/heartbeat. - Quotas → acima de 80% = warning, acima de 100% = critical, mas a operação
segue; o back anexa os headers
X-License-Warnings/X-License-Critical. requireFeature()é soft — feature ausente vira aviso, não bloqueia.
Gerar/obter a licença de um deploy
Online
- No admin UI do license server, crie tenant + licença (produto + limites); copie a key (UUID).
- No host, no
.env:LICENSE_SERVER_URL,LICENSE_KEY,LICENSE_PRODUCT. - Suba o back → ele faz
activate+ heartbeat; o lease é cacheado em./.license/cache.enc. - Verifique:
GET /license/status→active: true.
Offline / on-prem (air-gap)
- Crie a licença no admin UI.
- Exporte o
.lic: botão "Baixar .lic" (comfingerprintopcional p/ node-lock), ounpx tsx scripts/export-lic-file.ts <license-key> license.lic(rodando no/contra o license server). - Baixe a chave pública:
curl <server>/api/v1/public-key -o public-key.json. - Copie
license.lic+public-key.jsonpara./.license/no host alvo. - No
.env:LICENSE_FILE_PATH,LICENSE_PUBLIC_KEY_PATH,LICENSE_PRODUCT(e remova as vars de online). - Suba o back → verifica o
.liclocalmente, sem rede. Renovação = troca o arquivo (recarrega sozinho).
O Hub pg-boss fica desligado quando EVENTS_DATABASE_URL está vazio ou o
modo é offline (caso on-prem / SQL Server). Aí o uso é reportado pelo heartbeat
HTTPS do SDK — e em offline puro (air-gap) não há rede, então nada é reportado.
Referência completa: h1-license-server/docs/license-modes.md e
HSBR-Gestao-Ativos-Back/docs/license-integration.md.