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

98 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.cpp``LIC_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`).