Files
tesm-license/srv
alientimandClaude Sonnet 5 ed2ed00a4e Sub-Lizenzserver: Lizenzen fuer Lizenzserver ausstellbar (role='license_server')
Der Master kann jetzt ueber den normalen Kunde->Ticket->Lizenz-Flow
Lizenzen ausstellen, die eine ANDERE Lizenzserver-Instanz voll
funktionsfaehig machen (Kunden/Tickets/Lizenzen fuer eigene Kunden
ausstellen, Benutzer/Gruppen/Einstellungen verwalten) -- mit genau
einer strukturellen Einschraenkung: der so lizenzierte Sub-Lizenzserver
kann selbst KEINE weiteren Lizenzserver-Lizenzen ausstellen. Die
eigene Lizenz DIESES Masters bleibt weiterhin ausschliesslich per
create_master_license.py erzeugbar, nie ueber die Ticket-UI.

- licensing.py: neues, signiertes role-Feld (master/license_server/
  customer), siehe separates TESM-Release fuer die synchronisierte
  Kopie (harte Invariante: beide Dateien bleiben identisch).
- create_master_license.py: setzt role='master' beim Selbstausstellen.
- Neue STRUKTURELLE Sperre can_issue_license_server_licenses(): True
  NUR wenn die eigene, aktive Lizenz dieser Instanz role=='master' ist
  -- haengt an der Instanz-Rolle, nicht an einer vergebbaren Permission,
  daher von lokalen Admins eines Sub-Lizenzservers nicht aufhebbar.
  Kombiniert mit current_user.is_admin an jeder Aufrufstelle (nur echte
  Admins duerfen es je nutzen, wie gewuenscht -- kein delegierbares
  Recht).
- license_tickets.role-Spalte (Migration, Default 'customer').
  license_tickets.role bestimmt, welche Rolle eine daraus ausgestellte
  Lizenz traegt -- nach Anlage unveraendert wie customer_id.
- ticket_new(): neue, nur fuer can_issue_license_server_licenses()+Admin
  sichtbare Option 'Dies ist eine Lizenzserver-Lizenz'. Jeder andere
  Versuch (manipuliertes Formular, Sub-Lizenzserver, Nicht-Admin) wird
  serverseitig still auf 'customer' zurueckgestuft. Module werden fuer
  role!='customer' erzwungen auf [] (TESM-Client-Konzept, fuer einen
  Lizenzserver bedeutungslos).
- Self-Service (unauthentifiziert, nur ueber die Ticket-ID) ist fuer
  role!='customer'-Tickets komplett gesperrt (404) -- Lizenzserver-
  Lizenzen sind ausschliesslich admin-verwaltet, kein Kundenweg. Trial-
  Ausstellung ('30 Tage, alle Module') ebenfalls nur fuer role=customer
  moeglich (ValueError sonst, sauber abgefangen statt 500er).
- license_send_email(): ueberspringt Self-Service-/Kundenportal-Hinweise
  fuer role='license_server'-Lizenzen (waeren ohnehin blockiert).
- UI: 'Lizenzserver'-Badge auf Tickets-/Lizenzen-Liste und Ticket-
  Detailseite.

Getestet: licensing.py isoliert (role signiert+verifiziert, Manipulation
bricht die Signatur, Altformat ohne role faellt auf 'customer' zurueck),
can_issue_license_server_licenses()-Logik (6 Kombinationen), Schema-
Migration (Alt-DB ohne role-Spalte, idempotent), Ende-zu-Ende Ticket->
Lizenz-Ausstellung gegen echte create_db.py-DB. ZUSAETZLICH gegen einen
echten, lokal laufenden Flask-Server (native Windows-Python, WSL-
Netzwerksandbox in dieser Umgebung unzuverlaessig) voll durchgespielt:
Checkbox erscheint nur fuer role=master, Ticket+Lizenz-Ausstellung mit
role=license_server funktioniert Ende-zu-Ende (signierte Datei, Module
leer, Self-Service liefert 404), UND der Sicherheitstest: nach Wechsel
der eigenen Lizenz auf role=license_server verschwindet die Checkbox
UND ein direkter manipulierter POST mit role=license_server wird
serverseitig zuverlaessig auf 'customer' zurueckgestuft.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 22:08:19 +02:00
..