licence-server/docs/asp-terminia/01-postojece-stanje.md
Nenad Djukic 1abe7176ec Preimenovanje: dal-license-server -> licence-server (+ debrendiranje)
Vlasnik izlazi iz DAL price za ovaj projekat - postaje samostalan proizvod.
Preimenovanje je mehanicko (import putanje, imena fajlova/baze/UI naslova),
NIJEDNA linija poslovne logike u internal/handler ili internal/service nije
dirana - go build, go vet i go test ./... prolaze cisto pod novim imenom.

- go.mod: module dal-license-server -> licence-server; 28 import linija u
  13 .go fajlova usaglaseno
- internal/config/config.go (+test): default DB_NAME licence_db
- HTML sabloni (7 stranica) + 7 Playwright e2e spec fajlova: "DAL License
  Server" -> "Licence Server" u title/nav-brand, testovi usaglaseni u istom
  prolazu (nista ne moze da se razdvoji)
- package.json/package-lock.json/.gitignore/.claude/project.json: ime
  projekta/binarnog fajla/work_dir
- Usput: package.json je u repository.url nosio OTVORENU Gitea lozinku u
  cistom tekstu - uklonjena (URL sad bez kredencijala). Lozinka je i dalje
  u staroj git istoriji - preporuka: rotirati je posebno.
- CLAUDE.md/README/API/TESTING/docs/SPEC/ARCHITECTURE/SETUP: naslovi, ASCII
  dijagrami, git clone URL, mysqldump primer, systemd predlozak u SETUP.md
  zamenjen stvarnim (obrazac terminia.service - journal log + graceful
  shutdown, ne stari minimalni predlozak)
- Debrendiranje: "Univerzalni licencni server za sve DAL proizvode" ->
  "za vise proizvoda i klijenata"; potpis "Nenad Djukic / DAL d.o.o." ->
  "Nenad Djukic". NE dirano: nazivi ESIR/ARV/LIGHT_TICKET (tudji proizvodi,
  ne DAL brend), "DAL" kao stvaran naziv org-a u RBAC modelu
  (docs/loggerservice/README.md) - to je podatak, ne branding ovog servera.
- docs/asp-terminia/, docs/loggerservice/: prozni pomeni imena servera

Baza (dal_license_db -> licence_db) i deploy na 151 idu u posebnom koraku,
posle preimenovanja Gitea repoa - vidi CLAUDE.md istorijsku belesku na dnu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 07:55:26 +02:00

5.0 KiB
Raw Blame History

Postojeće stanje (provereno na serveru 2026-07-24, read-only)

1. Server 151 — pristup i raspored

  • SSH: ssh root@157.180.119.151 (host se javlja kao MCLaud, Ubuntu; ključ ~/.ssh/id_ed25519 sa razvojne mašine; samo root). Hetzner, van LAN-a.
  • Na ISTOM serveru žive i drugi sistemi — ne dirati:
    • terminia SaaS platforma za klubove (portovi 8091/8092) — IME SLIČNO, ali NIJE naš proizvod;
    • Gitea;
    • ESIR backend (fiskalizacija).

2. licence-server (naš deo)

  • Kod: /root/projects/licence-server — Go, bez frameworka, MySQL.
  • Port: 8090 lokalno; javno preko nginx sajta arv.
  • Javni URL (ovo firmware već koristi): https://157.180.119.151/license/api/v1/
    • HTTPS 443, cert /etc/nginx/ssl/arv.crt, server_name = IP → self-signed (zato firmware koristi setInsecure(); odluku štiti RSA potpis odgovora).
    • Na portu 80 je izložen samo validator API; ostalo redirect na 443.
  • Produkcioni obim: 3 proizvoda (ESIR, ARV, LIGHT_TICKET — seed u migrations/002_seed_products.sql), ~140 licenci, ~19 aktivacija. ŽIVO.

Kripto

  • RSA-2048, potpis RSA-SHA256.
  • Privatni ključ: na serveru (crypto/ + .env konfiguracija) — NE čitati, NE kopirati, NE logovati.
  • Javni ključ: crypto/public.pem — VEĆ ugrađen u firmware (licenca.cpp, LIC_PUBKEY). Ako se ključ ikad rotira, MORA i novi firmware — to je krupna odluka, ne radi se usput.
  • Potpis stiže kao string: "signature": "RSA-SHA256:<base64>" uz license objekat. Potpisuje se serijalizacija license objekta kakvu server pošalje — klijent verifikuje SIROVE bajtove (ne re-serijalizuje). Svaka izmena serijalizacije na serveru lomi sve klijente u polju.

Klijentski API (bez autentikacije, rate-limited)

Ruta Telo zahteva Odgovor
POST /api/v1/activate {license_key, machine_fingerprint, app_version, os, hostname} {license:{... expires_at, grace_days, limits, features, customer ...}, signature}
POST /api/v1/validate {license_key, machine_fingerprint} {valid, expires_at, revoked}
POST /api/v1/deactivate (transfer/oslobađanje)

Greške (JSON error polje): INVALID_KEY, ALREADY_ACTIVATED, KEY_EXPIRED, KEY_REVOKED, PRODUCT_MISMATCH.

Admin API

  • Header X-API-Key (ključ u .env — od vlasnika se traži ključ ili da on sam klikne u dashboardu; agent NE vadi ključ iz .env bez izričite dozvole).
  • Kreira proizvode i licence. Postoji i htmx admin dashboard.

3. Firmware klijent — GOTOV (od FW 0.10.0)

Fajlovi u firmware repou (firmware/10_terminia/):

Šta Gde
Modul licenca.h / licenca.cpp
Ugrađen javni ključ licenca.cppLIC_PUBKEY (PEM)
NVS namespace lic: raw (sirovi license JSON) + sig; ključ/URL u configu: licKey, licUrl (podrazumevano https://157.180.119.151/license/api/v1)
Web API (SPA) /api/license (status), /api/license-save (ključ/URL), /api/license-activate, /api/license-check — sve samo admin
UI SPA → Podešavanja → Uređaj → kartica „Licenca" (status, izdanje, korisnik, važi do, otisak uređaja, unos ključa, Aktiviraj, Proveri na serveru)

Kako klijent radi (bitno za server stranu)

  1. Otisak: machine_fingerprint = "sha256:" + sha256hex(MAC) gde je MAC oblika AA:BB:CC:DD:EE:FF (velika slova, dvotačke). ⚠️ PRETPOSTAVKA — proveriti u Go kodu servera kako računa fingerprint za poređenje; ako se razlikuje, uskladiti NA SERVERU dokumentaciju/verifikaciju za ASP proizvod ILI javiti pa menjamo FW (zadatak Z2).
  2. Aktivacija: POST /activate; iz odgovora isecₐ SIROVE bajtove license objekta (brojanje zagrada, string-safe), verifikuje signature RSASHA256 javnim ključem, čuva sirovo+potpis u NVS.
  3. Svaki start (offline): ponovo verifikuje potpis iz NVS + poredi machine_fingerprint iz licence sa svojim + proverava expires_at (poređenje po datumu YYYY-MM-DD; prazno = trajna; nepouzdan sat → grejs, nikad pad).
  4. Statusi na uređaju: nema / vazi / grejs / los-potpis / drugi-uredjaj / istekla.
  5. ENFORCEMENT NE POSTOJI — uređaj samo prikazuje status. Gašenje funkcija bez licence je odluka vlasnika (zadatak Z4).

Polja koja klijent čita iz license objekta

edition, customer (ili customer_name), expires_at, license_id (ili key), grace_days, machine_fingerprint. Nepoznata dodatna polja ne smetaju (parsira se ciljano). limits/features se JOŠ ne čitaju — planirano uz enforcement.

4. Šta NE postoji (i pripada zadacima)

  • Proizvod „ASP-Terminia" na serveru — ne postoji (zadatak Z1).
  • Nijedan ASP ključ — ne postoji (Z1/Z2).
  • Domen licenca.terminia.net + Let's Encrypt — ne postoji (Z3; domen kupuje vlasnik).
  • Enforcement na uređaju + features/limits semantika za ASP (Z4/Z5).
  • FW potpisivanje .bin + katalog firmvera (Z6; preduslov za auto-OTA, vidi i ASP repo: serviseri/03-provisioning-i-fw-katalog.md).