Skip to content

Licensing System

This topic explains how PyLocket's licensing and activation system works, including activation flow, device management, offline support, and license lifecycle.


Architecture

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│  End-User   │         │  PyLocket   │         │  Developer  │
│  App        │         │  API        │         │  Portal     │
└──────┬──────┘         └──────┬──────┘         └──────┬──────┘
       │                       │                       │
       │ 1. Activation request │                       │
       │ (key + device ID)     │                       │
       ├──────────────────────►│                       │
       │                       │                       │
       │                       │ 2. Validate license   │
       │                       │    Check device limit  │
       │                       │                       │
       │ 3. Signed token       │                       │
       │◄──────────────────────┤                       │
       │                       │                       │
       │ 4. Cache token        │                       │
       │    Decrypt functions   │                       │
       │    App runs            │                       │
       │                       │                       │
       │ 5. Periodic refresh   │                       │
       ├──────────────────────►│                       │
       │◄──────────────────────┤                       │

License Key Format

XXXX-XXXX-XXXX-XXXX
  • Length: 16 alphanumeric characters in 4 groups of 4
  • Character set: Uppercase letters and digits (ambiguous characters excluded: 0/O, 1/I/L)
  • Uniqueness: Globally unique across all PyLocket apps
  • Platform-independent: A single key works on all platforms for the same app

Example

A7K2-M9P4-X3J8-W5N6

Device Fingerprinting

When an end-user activates a license, the application generates a unique device identifier based on hardware characteristics.

Key Properties

  • Per-app isolation: The same physical device produces different identifiers for different apps, preventing cross-app tracking
  • Privacy-preserving: Only a one-way hash is transmitted to PyLocket servers — raw hardware identifiers never leave the device
  • Deterministic: The same device always produces the same identifier for the same app, allowing seamless re-activation after restart
  • Non-reversible: The stored hash cannot be reversed to reveal hardware details

Activation Flow

Step 1: Activation Request

When the end-user launches the protected application and enters their license key, the app sends an activation request to the PyLocket API containing the license key and the device identifier.

Step 2: Server Validation

The API validates:

  1. License exists: The key matches a record in the database
  2. License is active: Status is ACTIVE (not REVOKED or EXPIRED)
  3. Device limit check: The number of registered devices for this license does not exceed the limit
  4. Rate limiting: Activation requests are rate-limited to prevent abuse
  5. Build check: The build ID exists and belongs to the same app as the license

Step 3: Token Issuance

On success, the API returns a cryptographically signed runtime token that enables the native runtime to decrypt protected functions. The token is bound to the specific device and application.

Step 4: Runtime Activation

The native runtime:

  1. Caches the token securely in memory
  2. Uses the token to enable function decryption
  3. Begins decrypting functions on demand as they are called
  4. Periodically refreshes the token in the background

Offline Support

Online Activation

The first activation always requires an internet connection. After successful activation:

  1. The runtime token is cached locally
  2. The token has a configurable expiry (default: 24 hours)

Offline Grace Period

If the device loses internet connectivity:

  1. The cached token remains valid until its expiry
  2. After expiry, the runtime enters the offline grace period (default: 72 hours)
  3. During the grace period, the application continues to function
  4. After the grace period expires, the application requires re-activation
Online activation → Token cached (24h) → Grace period (72h) → Re-activation required

Background Refresh

When the device is online, the runtime attempts to refresh the token:

  1. Before token expiry (proactive refresh)
  2. On application startup
  3. Periodically during execution

A successful refresh resets both the token TTL and the offline grace timer.


Device Limits

How Limits Work

Each license has a device_limit (default: 2). When a new device activates:

  • If active_devices < device_limit: Activation succeeds, new device registered
  • If active_devices >= device_limit: Activation fails with DEVICE_LIMIT_EXCEEDED

Counting Devices

A "device" is identified by its unique device identifier. The same physical device always produces the same identifier, so:

  • Restarting the application on the same device does not consume an additional slot
  • Reinstalling the application on the same device produces the same identifier (unless the OS is reinstalled or hardware changes)
  • Running on a VM that migrates to different hardware may produce a different identifier

Resetting Devices

Developers can reset device activations when customers replace hardware:

pylocket licenses reset-devices --license <LICENSE_KEY>

This clears all device records, allowing the customer to activate fresh.


Velocity Controls

Activation Rate Limiting

Activation requests are rate-limited per license key to prevent: - Automated license key sharing/testing - Brute-force activation attempts - Denial-of-service against the activation endpoint

When the rate limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header.

Download Rate Limiting

Download requests are also rate-limited to prevent abuse of signed download URLs.


License Lifecycle

┌──────────┐
│  CREATE   │──→ Status: ACTIVE
└──────────┘
     ├── Customer activates → Device registered
     ├── Customer activates on new device → Second device registered
     ├── Developer extends expiry → Expiry updated
     ├── Developer revokes
     │   └──→ Status: REVOKED → Activation fails on next check
     ├── Expiry date passes
     │   └──→ Status: EXPIRED → Activation fails on next check
     └── Developer resets devices → All device records cleared

See Also