TESM-Lizenzserver 2.0.0 -- Neubau

Vollstaendiger Neubau der Anwendung. Der vorherige Stand bleibt unveraendert
im Zweig SONNET5 erhalten.

Aufbau: apps/tesm-license (Anwendung), packages/tesm-core (gemeinsamer Kern),
packages/tesm-licensing (Lizenzprotokoll), deploy (Installation, systemd,
privilegierter Helfer), docs, tests. Die verwaltete Anwendung liegt in ihrem
eigenen Repository; beide Repositorien bringen die gemeinsamen Pakete mit,
damit sich jedes allein installieren laesst.

Die wichtigsten Unterschiede zum Vorgaenger:

* Keine doppelte licensing.py -- ein Paket, das beide Anwendungen
  installieren, statt zweier Dateien, die byte-identisch bleiben sollen.
* Der Webprozess laeuft unprivilegiert; alles, was Root braucht, geht ueber
  einen einzigen Helfer mit Positivlisten fuer jedes Argument.
* CSRF-Schutz ueberhaupt -- der Vorgaenger hatte keinen.
* Rechte werden serverseitig geprueft, nicht nur im Template ausgeblendet.
* Keine Lizenz ohne master_endpoint: eine Ausstellung ohne Endpunkt wird
  abgelehnt statt eine Lizenz zu erzeugen, die sich nie aktivieren kann.
* Offline-Aktivierung in beide Richtungen; die Lizenz bleibt als
  "Aktivierung offen" markiert, bis sie zurueckkommt.
* Getrennte Signaturkontexte je Nachrichtenart, Nonce gegen Wiedereinspielung,
  seq gegen das Zurueckrollen auf eine aeltere Lizenz.
* Kein Hostname im Maschinen-Fingerabdruck.
* Verschachtelte Datenbankverbindungen sind ein Fehler, kein Deadlock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
alientimandClaude Opus 5 committed 2026-09-02 18:01:23 +02:00
1 parent c130c85b17
commit f7805a2180
211 files changed
+31099 -14759

No files matched your search

@@ -0,0 +1,125 @@
"""TESM-Lizenzprotokoll -- gemeinsames Paket von TESM und TESM-Lizenzserver.
Im Vorgaengerprojekt lag dieses Modul als handkopierte, byte-identisch zu
haltende ``licensing.py`` in beiden Repos. Jede unabhaengige Aenderung an nur
einer Kopie brach die gegenseitige Signaturpruefung, ohne dass das lokal
auffiel. Hier ist es ein installierbares Paket mit eigener Version -- die
Invariante ist damit strukturell erfuellt statt durch Disziplin.
"""
from __future__ import annotations
from .canonical import (
SIG_CONTEXT_LICENSE,
SIG_CONTEXT_REQUEST,
SIG_CONTEXT_RESPONSE,
canonical_bytes,
decode_code,
encode_code,
generate_keypair,
public_from_private,
sign,
verify,
)
from .errors import (
InvalidLicenseFile,
LicensingError,
ProtocolViolation,
ReplayDetected,
SignatureInvalid,
UntrustedIssuer,
)
from .fingerprint import machine_identity, system_fingerprint
from .license import (
ALL_MODULES,
EXPIRY_WARNING_DAYS,
FORMAT_VERSION,
GRACE_PERIOD_DAYS,
HEARTBEAT_WARNING_DAYS,
LICENSE_ROLES,
LICENSE_TYPE_LABELS,
LICENSE_TYPES,
LIFETIME_EXPIRES_AT,
MODULE_LABELS,
ROLE_LABELS,
TRIAL_DEFAULT_DAYS,
LicenseStatus,
issue_license,
iso,
key_id,
license_status,
parse_iso,
resign_license,
split_bundle,
utcnow,
verify_license,
)
from .protocol import (
ACTIONS,
CLOCK_SKEW_SECONDS,
HEARTBEAT_INTERVAL_SECONDS,
MAX_REPORT_ROWS,
REQUEST_MAX_AGE_SECONDS,
RESPONSE_STATES,
build_client_request,
build_master_response,
new_nonce,
verify_client_request,
verify_master_response,
)
__version__ = "2.0.0"
__all__ = [
"ACTIONS",
"ALL_MODULES",
"CLOCK_SKEW_SECONDS",
"EXPIRY_WARNING_DAYS",
"FORMAT_VERSION",
"GRACE_PERIOD_DAYS",
"HEARTBEAT_INTERVAL_SECONDS",
"HEARTBEAT_WARNING_DAYS",
"InvalidLicenseFile",
"LICENSE_ROLES",
"LICENSE_TYPES",
"LICENSE_TYPE_LABELS",
"LIFETIME_EXPIRES_AT",
"LicenseStatus",
"LicensingError",
"MAX_REPORT_ROWS",
"MODULE_LABELS",
"ProtocolViolation",
"REQUEST_MAX_AGE_SECONDS",
"RESPONSE_STATES",
"ROLE_LABELS",
"ReplayDetected",
"SIG_CONTEXT_LICENSE",
"SIG_CONTEXT_REQUEST",
"SIG_CONTEXT_RESPONSE",
"SignatureInvalid",
"TRIAL_DEFAULT_DAYS",
"UntrustedIssuer",
"build_client_request",
"build_master_response",
"canonical_bytes",
"decode_code",
"encode_code",
"generate_keypair",
"issue_license",
"iso",
"key_id",
"license_status",
"machine_identity",
"new_nonce",
"parse_iso",
"public_from_private",
"resign_license",
"sign",
"split_bundle",
"system_fingerprint",
"utcnow",
"verify",
"verify_client_request",
"verify_license",
"verify_master_response",
]