Plano — Lorentz.Licenca.Api (.NET 9) + UI Portal / MonitorOPS¶
Instalação passo a passo (VPS): 30-instalar-licenca.md · Índice: 28-indice-instalacao-apps.md
Status: Fase 1 implementada (
server/Lorentz.Licenca.Core+Lorentz.Licenca.Api).
Fase 2 concluída: Docker profilelicenca, proxy nginx, UI Portal, MonitorOPS.
Pendente (Fase 3): persistência SQL, testes golden vs WinForms.
1. Objetivo¶
Substituir a dependência do Lorentz.Licenca.exe (WinForms, Windows) por:
| Componente | Função |
|---|---|
| Lorentz.Licenca.Core | Crypto + montagem payload .lic (compatível CTI/URA/Supervisor) |
| Lorentz.Licenca.Api | HTTP :8092 no Linux Docker |
Portal /licenca/ |
UI comercial (formulário + download .lic) |
| MonitorOPS | Atalho / card Ferramentas (opcional) |
O WinForms permanece como fallback até validação cruzada em produção.
2. Arquitetura alvo¶
Browser (equipe comercial / TI)
│
├─► Portal /licenca/ (estático nginx)
│ │
│ └─► /api/licenca/* (proxy nginx)
│ │
│ ▼
│ lorentz-licenca :8092 (.NET 9)
│ │
│ ├─ Lorentz.Licenca.Core
│ └─ sqlserver:1433 (fase 2 — SAC_EMPRESA / SAC_LICENCA)
│
└─► MonitorOPS :9090 (link rápido → Portal /licenca/)
flowchart LR
Portal["Portal /licenca/"]
Nginx["nginx proxy"]
API["Lorentz.Licenca.Api :8092"]
Core["Lorentz.Licenca.Core"]
SQL[(SQL Server LorentzCTI)]
CTI["LorentzCTI / URA / Supervisor"]
Portal --> Nginx --> API --> Core
API -.->|fase 2| SQL
Core -->|".lic compatível"| CTI
3. Repositório — o que já existe¶
| Caminho | Descrição |
|---|---|
server/Lorentz.Licenca/ |
WinForms legado (renomeado) |
server/Lorentz.Licenca.Core/ |
Biblioteca compartilhada |
server/Lorentz.Licenca.Api/ |
Host HTTP (LicencaApiHost.vb) |
server/Lorentz.Licenca.Api.sln |
Build .NET 9 |
server/Lorentz.Licenca.Api/docs/api-licenca.md |
Referência REST |
Build local¶
dotnet build server/Lorentz.Licenca.Api.sln -c Release
LORENTZ_LICENCA_API_KEY=dev dotnet run --project server/Lorentz.Licenca.Api
curl http://127.0.0.1:8092/health
4. API REST (Fase 1)¶
| Método | Path | Auth | Descrição |
|---|---|---|---|
| GET | /health |
— | Health check |
| GET | /api/licenca/catalog |
X-Licenca-Api-Key |
Sistemas e módulos |
| POST | /api/licenca/generate |
idem | Gera chave cifrada |
| GET | /api/licenca/download/{cnpj}?key=... |
idem | Download {cnpj}.lic |
Header: X-Licenca-Api-Key: <LORENTZ_LICENCA_API_KEY>
Exemplo POST /api/licenca/generate:
{
"cnpj": "03774573000160",
"razaoSocial": "Cliente Exemplo Ltda",
"nomeUsual": "Cliente Exemplo",
"quantidadeAgentes": 10,
"chaveValidadeInicio": "2026-07-12T00:00:00",
"chaveValidadeFim": "2027-07-12T23:59:59",
"licencaValidade": "2027-07-12T23:59:59",
"naoExpirarLicenca": false,
"modulos": [
{
"sistema": "CTI",
"modulo": "Servidor",
"licencas": 1,
"usuarios": 50,
"dataInicio": "2026-07-12T00:00:00",
"dataFim": "2027-07-12T23:59:59"
}
]
}
Resposta:
{
"encryptedKey": "<base64>",
"cnpj": "03774573000160",
"arquivoLic": "03774573000160.lic",
"downloadUrl": "/api/licenca/download/03774573000160"
}
5. Compatibilidade criptográfica¶
- Algoritmo: Rijndael AES-256-CBC,
PaddingMode.Zeros - Chaves legadas (mesmas do CTI):
- Key:
lkirwf897+22#bbtrm8814z5qq=498j5 - IV:
H8g7F6e5D4c3B2a1 - Payload: formato
FU_GerarChavedefrmLicenca.vb
Fase 1.1 (obrigatória antes de produção): testes golden — gerar no WinForms e na API com mesmo input; comparar encryptedKey byte a byte.
6. Stack VPS — integração Docker (Fase 2)¶
6.1 Variáveis .env¶
LORENTZ_LICENCA_API_PORT=8092
LORENTZ_LICENCA_API_KEY=ChangeMe_LicencaApi2026!
LORENTZ_LICENCA_BIND_IP=127.0.0.1
6.2 Serviço Compose (profile licenca)¶
Espelhar lorentz-basehistorica:
lorentz-licenca:
profiles: [licenca]
build:
dockerfile: docker/lorentz-licenca/Dockerfile.runtime
ports:
- "${LORENTZ_LICENCA_BIND_IP:-127.0.0.1}:8092:8092"
environment:
LORENTZ_LICENCA_API_PORT: "8092"
LORENTZ_LICENCA_API_KEY: ${LORENTZ_LICENCA_API_KEY}
Scripts:
scripts/build-lorentz-licenca-zip.shscripts/extract-lorentz-licenca-publish.shscripts/deploy-licenca.sh
6.3 Proxy nginx (Portal)¶
location /api/licenca/ {
proxy_pass http://lorentz-licenca:8092/api/licenca/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Licenca-Api-Key $http_x_licenca_api_key;
}
config.json → licencaApi.apiBase, licencaApi.apiKey
7. UI Portal /licenca/ (Fase 2)¶
| Tela | Campos |
|---|---|
| Empresa | CNPJ, razão, endereço, MAC |
| Validade | Datas chave + licença, checkbox “não expirar” |
| Módulos | Grid CTI/SAC/TMK × módulos (como WinForms) |
| Ações | Gerar · Copiar chave · Download .lic |
Acesso: restrito — VPN, IP allowlist ou subdomínio licenca.orbitall.app (ver 22-plano-dominio-orbitall-app.md).
Arquivos (placeholder Fase 1):
portal/licenca/index.htmlportal/assets/licenca.js
Entrada no hub: app Licença em portal.apps.json.template.
8. MonitorOPS (Fase 2)¶
- Card Ferramentas → Gerar licença Lorentz → abre Portal
/licenca/ou iframe - Checagem de porta
8092emmonitor_services.pyquando profilelicencaativo - Runbook: API indisponível →
docker compose --profile licenca up -d lorentz-licenca
9. Persistência SQL (Fase 3)¶
Portar lógica de btnGravar_Click (frmLicenca.vb):
SAC_EMPRESA— dados cliente +ObsCli(chave)SAC_LICENCA— módulos por sistema- Modo PHP8 (
att_phoenix.php?cmd=phoenixlic) — avaliar se ainda necessário ou unificar só Core
Endpoint proposto: POST /api/licenca/persist (grava SQL + retorna chave).
10. Segurança¶
| Item | Regra |
|---|---|
| Exposição | Nunca 0.0.0.0:8092 público sem auth |
| Auth | X-Licenca-Api-Key forte; rotacionar no .env |
| Audit | Log estruturado: CNPJ, usuário (fase 3), IP |
| Chaves AES | Migrar para secret manager (fase 4); manter legado até CTI migrar |
| Separação | Não confundir com license-system Laravel (MySQL, outro formato) |
11. Fases e checklist¶
Fase 1 — Core + API ✅ (código)¶
- [x]
Lorentz.Licenca.Core— crypto + builder + catálogo - [x]
Lorentz.Licenca.Api— endpoints generate/catalog/download - [x] Build Release OK
- [ ] Testes golden vs WinForms
- [ ]
docs/api-licenca.mdno repo server
Fase 2 — Stack + UI ✅¶
- [x] Dockerfile.runtime + profile
licencano compose - [x] Proxy nginx +
licencaApinoconfig.json - [x] UI Portal
/licenca/(formulário + download.lic) - [x] Entrada no hub Orbitall (
status: active) - [x] MonitorOPS — link rápido + card Ferramentas + runbook troubleshooting
- [x] Scripts build/extract/deploy +
docker-compose.source.yml
Fase 3 — SQL + operação¶
- [ ] Persistência
SAC_EMPRESA/SAC_LICENCA - [ ] Leitura licença existente (equivalente “Ler chave”)
- [ ] Runbook em
docs/18-monitor-troubleshooting.md
Fase 4 — Domínio + hardening¶
- [ ]
licenca.orbitall.appvia Caddy (doc 22) - [ ] Desativar WinForms em estações comerciais (opcional)
12. Domínio (futuro)¶
| Subdomínio | Uso |
|---|---|
licenca.orbitall.app |
Portal UI + proxy API (restrito TI/comercial) |
13. Documentação relacionada¶
| Doc | Conteúdo |
|---|---|
| 22-plano-dominio-orbitall-app.md | TLS e subdomínios |
server/Lorentz.Licenca/README.md |
WinForms legado |
server/Lorentz.Licenca.Api/docs/api-licenca.md |
API REST |
14. Histórico¶
| Data | Notas |
|---|---|
| 2026-07-12 | Fase 2 concluída: Docker profile licenca, nginx, Portal UI, MonitorOPS. |
| 2026-07-12 | Plano + scaffold Core/Api; build Release OK. |