Kunden-Lebenszyklus (Offline-Aktivierung)
Dieses Dokument beschreibt ausschließlich den Lebenszyklus auf Kundenseite: Installation der Binärdatei, Offline-Aktivierung jeder Maschine, Laufzeitprüfung und Wechsel zwischen mehreren Lizenzen.
Erinnerung an Leitprinzip Nr. 2: das SCA-Binary tätigt NIEMALS HTTP-Aufrufe. Jegliche Server ↔ Client-Kommunikation erfolgt per E-Mail + Benutzeraktionen auf der PHP-Site.
Chronologische Zusammenfassung (3 Phasen, in Reihenfolge)
Phase A — Erstinstallation (1× pro Kunde)
- Kauf auf
codefixture.com/pricing.php→ Zahlung (Stripe oder Überweisung in V1). - Erhalt einer "Paket bereit"-E-Mail, sobald der Operator das Binary geliefert hat.
- Login auf
codefixture.com/login.php(UUID in V1; E-Mail/Passwort in V2).
Phase B — Für JEDE genutzte Plattform (Linux, macOS, Windows…)
- Auf
/downloads.phpauf Herunterladen in der Zeile der gewünschten Plattform klicken. Erhalt einer Datei:sca-<version>-<platform>-<id>.tar.gz(Linux)sca-<version>-<platform>-<id>.dmg(macOS)sca-<version>-<platform>-<id>.zip(Windows)
- SHA-256 überprüfen (empfohlen):
→ mit dem auf
shasum -a 256 sca-1.0.0-linux-x86_64-acme.tar.gz # macOS / Linux certutil -hashfile sca-1.0.0-win-x86_64-acme.zip SHA256 # Windows/downloads.phpangezeigten Wert vergleichen. - Das Paket entpacken. Inhalt:
staticcodeaudit-<platform>(das ausführbare Binary)README.txt(Offline-Aktivierungsverfahren)NOTICE.txt(Lizenzhinweise + Erinnerung an das Offline-Prinzip)
Phase C — Für JEDE aktivierte Maschine (bis zu max_machines)
- Auf der Zielmaschine SCA das erste Mal ausführen:
→ Der SCA-Footer (vgl.
./staticcodeaudit-linux-x86_64 # beliebiger Befehlsca/license_footer.py) zeigt einen ASCII-Rahmen mit:- der Seriennummer der Lizenz
- dem Maschinen-Fingerprint (SHA-256 64 Hex-Zeichen), lokal aus hostname + arch + OS + MAC berechnet, ohne Netzwerkaufruf.
- Diese beiden Werte (USB-Stick, Telefon, Copy-Paste) auf einen mit dem Internet verbundenen Arbeitsplatz kopieren.
- Auf diesem verbundenen Arbeitsplatz
codefixture.com/activate.phpöffnen und eingeben:- Seriennummer
- Maschinen-Fingerprint
- Plattform (Auswahl in der Dropdown-Liste) → auf Aktivieren klicken.
- Die Site gibt eine signierte
license.key-Datei zurück (die diesen Fingerprint in der signierten Liste enthält). Diese Datei herunterladen. - Die
license.keyzur Zielmaschine zurückbringen (USB-Stick / scp / AirDrop) und im selben Ordner wie das Binary platzieren. - SCA neu starten:
→ SCA:
./staticcodeaudit-linux-x86_64 scan ~/mein-projekt- liest die lokale
license.key - überprüft die HMAC-HKDF-Signatur (eingebetteter öffentlicher Schlüssel — null Netzwerkaufrufe)
- überprüft, dass sein lokaler Fingerprint ∈ signierte Liste
- überprüft
expires_at > today - startet den Scan
- Footer am Ende:
Status: OK (Maschine aktiviert)
- liest die lokale
Tabelle Aktion ↔ Endpunkt (für PHP-Entwickler)
| Kundenaktion | PHP-Seite | Admin-Endpunkt (vom PHP konsumiert) |
|---|---|---|
| Anmeldung | login.php |
POST /auth/token |
| Profil + Abos + Lizenzen anzeigen | account.php |
GET /clients/<id>/, /subscriptions/, /licenses/ |
| Herunterladbare Pakete auflisten | downloads.php |
GET /clients/<id>/downloads/ |
| Ein Paket herunterladen | direkter Klick | GET /builds/<id>/download (signierte URL TTL 15 min) |
| Eine Maschine aktivieren (manueller Challenge) | activate.php |
POST /activations (PHP leitet serial + eingegebenen Fingerprint weiter) |
| Aktive Maschinen auflisten | account.php |
GET /clients/<id>/activations/ |
| Eine Maschine deaktivieren | account.php (Schaltfläche) |
PATCH /clients/<id>/activations/<id>/ {deactivate: true} |
| Rechnungen auflisten | invoices.php |
GET /clients/<id>/invoices/ |
| Rechnungs-PDF herunterladen | invoices.php (Schaltfläche) |
GET /clients/<id>/invoices/<id>/pdf |
| Factur-X (PDF/A-3 + XML CII) herunterladen | invoices.php |
GET /clients/<id>/invoices/<id>/facturx |
1 Laufzeitprüfung (ohne Internet)
Bei jeder Ausführung auf einer bereits aktivierten Maschine führt SCA aus:
- Liest license.key aus dem lokalen Dateisystem
- Überprüft die HMAC-HKDF-Signatur (Integrität + Manipulationssicherheit — öffentlicher Schlüssel im Binary eingebettet)
- Überprüft den lokalen Fingerprint ∈ fingerprints der Payload
- Überprüft expires_at > today
- Kein Netzwerkaufruf, kein Ping, keine Telemetrie.
Folge: ein Widerruf auf der Admin-Seite (§8) wird erst bei der nächsten Lizenzverlängerung wirksam (der Benutzer muss eine neue license.key erneut herunterladen, die seinen Fingerprint nicht mehr enthält oder ein näheres expires_at hat).
2 Multi-Lizenz auf derselben Maschine — SCA_LICENSE_PATH
Wenn der Kunde 2 unterschiedliche Lizenzen hat (z. B. persönliches Solo+ + Team für das Team — seltener Fall, vgl. §7.4), kann er zwischen ihnen wechseln, ohne eine Datei zu verschieben:
SCA_LICENSE_PATH=~/licences/team.key ./sca scan ~/projekt-pro
SCA_LICENSE_PATH=~/licences/solo-plus.key ./sca scan ~/projekt-privat
Prioritätsreihenfolge von SCA, um seine license.key zu finden:
$SCA_LICENSE_KEY(roher JSON-Inhalt, durch einen Wrapper definiert)$SCA_LICENSE_PATH(Pfad zu einer .key-Datei — empfohlen für das Multi-Lizenz-Switching)./license.key(cwd, Standardkonvention)
3 Sonderfälle auf der Kundenseite
| Fall | Vorgehen |
|---|---|
| Eine N-te Maschine hinzufügen | Phase C (Schritte 7→12) auf der neuen Maschine wiederholen. Kontingent max_machines um 1 verbraucht. |
| OS-Neuinstallation auf derselben Maschine | Der Fingerprint ändert sich → Phase C wiederholen. Wenn Kontingent erreicht, den alten Fingerprint vorher deaktivieren. |
| Übertragung Arbeitsplatz zu Arbeitsplatz | Den alten von /account.php aus deaktivieren → Phase C auf dem neuen wiederholen. |
| Maschine verloren/gestohlen | Von /account.php aus deaktivieren (wirksam bei der nächsten Verlängerung, vgl. §8.1). |
license.key-Datei verloren |
Phase C wiederholen — POST /activations ist idempotent (gleicher Fingerprint = gleicher Slot). |
| Jährliche Verlängerung | Siehe §6 — der Kunde wiederholt Schritt 4 (neues Paket herunterladen) + Schritt 11 (Rückführung der neuen license.key) auf jeder Maschine. |
Der Operator hat normalerweise nichts für diese gängigen Fälle zu tun, außer einer Diagnose-Konsultation über Django-Admin (StaticCodeAudit → Activation).