Skip to main content

Client lifecycle (offline)

Level Beginner
Reading time ⏱ 10 min
words 781
Topics licenseactivation

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)

  1. Purchase on codefixture.com/pricing.php → payment (Stripe or wire transfer in V1).
  2. Receive a "package ready" email when the operator has delivered the binary.
  3. Login on codefixture.com/login.php (UUID in V1; email/password in V2).

Phase B — For EACH platform used (Linux, macOS, Windows…)

  1. 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)
  2. Verify the SHA-256 (recommended):
    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
    
    → compare with the value displayed on /downloads.php.
  3. 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)

  1. On the target machine, run SCA for the first time:
    ./staticcodeaudit-linux-x86_64    # any command
    
    → The SCA footer (cf. sca/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.
  2. Copy these two values (USB stick, phone, copy-paste) to a workstation connected to the Internet.
  3. On that connected workstation, open codefixture.com/activate.php and enter:
    • Serial number
    • Machine fingerprint
    • Platform (selection in the drop-down) → click Activate.
  4. The site returns a signed license.key file (including this fingerprint in the signed list). Download that file.
  5. Bring back the license.key to the target machine (USB stick / scp / AirDrop) and place it in the same folder as the binary.
  6. Re-run SCA:
    ./staticcodeaudit-linux-x86_64 scan ~/my-project
    
    → SCA:
    • 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)

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:

  1. $SCA_LICENSE_KEY (raw JSON content, defined by a wrapper)
  2. $SCA_LICENSE_PATH (path to a .key file — recommended for multi-license switching)
  3. ./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 (StaticCodeAuditActivation).