Client lifecycle (offline activation)
This document describes only the customer-facing lifecycle: installing the binary, activating each machine offline, runtime verification and switching between multiple licenses.
Reminder of guiding principle #2: the SCA binary NEVER makes HTTP calls. All server ↔ client communication goes through email + user actions on the PHP site.
Chronological recap (3 phases, in order)
Phase A — First installation (once per client)
- Purchase on
codefixture.com/pricing.php→ payment (Stripe or wire transfer in V1). - Receive a "package ready" email when the operator has delivered the binary.
- Login on
codefixture.com/login.php(UUID in V1; email/password in V2).
Phase B — For EACH platform used (Linux, macOS, Windows…)
- On
/downloads.php, click Download on the row of the desired platform. Receive a file:sca-<version>-<platform>-<id>.tar.gz(Linux)sca-<version>-<platform>-<id>.dmg(macOS)sca-<version>-<platform>-<id>.zip(Windows)
- Verify the SHA-256 (recommended):
→ compare with the value displayed on
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.php. - Extract the package. Contents:
staticcodeaudit-<platform>(the executable binary)README.txt(offline activation procedure)NOTICE.txt(license notices + reminder of the offline principle)
Phase C — For EACH activated machine (up to max_machines)
- On the target machine, run SCA for the first time:
→ The SCA footer (cf.
./staticcodeaudit-linux-x86_64 # any commandsca/license_footer.py) displays an ASCII frame with:- the license serial number
- the machine fingerprint (SHA-256 64 hex chars), computed locally from hostname + arch + OS + MAC, with no network call.
- Copy these two values (USB stick, phone, copy-paste) to a workstation connected to the Internet.
- On that connected workstation, open
codefixture.com/activate.phpand enter:- Serial number
- Machine fingerprint
- Platform (selection in the drop-down) → click Activate.
- The site returns a signed
license.keyfile (including this fingerprint in the signed list). Download that file. - Bring back the
license.keyto the target machine (USB stick / scp / AirDrop) and place it in the same folder as the binary. - Re-run SCA:
→ SCA:
./staticcodeaudit-linux-x86_64 scan ~/my-project- reads the local
license.key - verifies the HMAC HKDF signature (embedded public key — zero network calls)
- verifies that its local fingerprint ∈ signed list
- verifies
expires_at > today - launches the scan
- footer at the end:
Status: OK (machine activated)
- reads the local
Action ↔ endpoint table (for PHP devs)
| Client action | PHP page | Admin endpoint (consumed by PHP) |
|---|---|---|
| Login | login.php |
POST /auth/token |
| View profile + subscriptions + licenses | account.php |
GET /clients/<id>/, /subscriptions/, /licenses/ |
| List downloadable packages | downloads.php |
GET /clients/<id>/downloads/ |
| Download a package | direct click | GET /builds/<id>/download (signed URL TTL 15 min) |
| Activate a machine (manual challenge) | activate.php |
POST /activations (PHP relays serial + entered fingerprint) |
| List active machines | account.php |
GET /clients/<id>/activations/ |
| Deactivate a machine | account.php (button) |
PATCH /clients/<id>/activations/<id>/ {deactivate: true} |
| List invoices | invoices.php |
GET /clients/<id>/invoices/ |
| Download invoice PDF | invoices.php (button) |
GET /clients/<id>/invoices/<id>/pdf |
| Download Factur-X (PDF/A-3 + XML CII) | invoices.php |
GET /clients/<id>/invoices/<id>/facturx |
1 Runtime verification (no Internet)
On every execution on an already-activated machine, SCA:
- Reads license.key from the local filesystem
- Verifies the HMAC HKDF signature (integrity + non-tampering — public key embedded in the binary)
- Verifies the local fingerprint ∈ fingerprints of the payload
- Verifies expires_at > today
- No network call, no ping, no telemetry.
Consequence: a revocation on the admin side (§8) is only effective at the next license renewal (the user will have to re-download a new license.key that no longer includes their fingerprint or has a closer expires_at).
2 Multi-license on the same machine — SCA_LICENSE_PATH
If the client has 2 different licenses (e.g. personal Solo+ + Team for the team — rare case, see §7.4), they can switch between them without moving any file:
SCA_LICENSE_PATH=~/licences/team.key ./sca scan ~/work-project
SCA_LICENSE_PATH=~/licences/solo-plus.key ./sca scan ~/personal-project
SCA priority order to find its license.key:
$SCA_LICENSE_KEY(raw JSON content, defined by a wrapper)$SCA_LICENSE_PATH(path to a .key file — recommended for multi-license switching)./license.key(cwd, default convention)
3 Special cases on the client side
| Case | Procedure |
|---|---|
| Add an Nth machine | Repeat Phase C (steps 7→12) on the new machine. Quota max_machines consumed by 1. |
| OS reinstall on the same machine | The fingerprint changes → repeat Phase C. If quota reached, deactivate the old fingerprint first. |
| Workstation-to-workstation transfer | Deactivate the old one from /account.php → repeat Phase C on the new one. |
| Lost/stolen machine | Deactivate from /account.php (effective at next renewal, see §8.1). |
Lost license.key file |
Repeat Phase C — POST /activations is idempotent (same fingerprint = same slot). |
| Annual renewal | See §6 — the client repeats step 4 (download new package) + step 11 (bring back new license.key) on every machine. |
The operator usually has nothing to do for these common cases, except diagnostic consultation via Django admin (StaticCodeAudit → Activation).