Licensing System¶
This topic explains how PyLocket's licensing and activation system works, including activation flow, device management, offline support, and license lifecycle.
Architecture¶
sequenceDiagram
participant A as End-User App
participant P as PyLocket API
participant D as Developer Portal
A->>P: 1. Activation request (key + device ID)
Note over P: 2. Validate license<br/>Check device limit
P->>A: 3. Signed token
Note over A: 4. Cache token<br/>Decrypt functions<br/>App runs
A->>P: 5. Periodic refresh
P->>A: Refreshed token
License Key Format¶
- 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¶
Device Fingerprinting¶
When an end-user activates a license, the application generates a one-way device fingerprint based on hardware characteristics.
Key Properties¶
- Per-app isolation: The same physical device produces different fingerprints for different apps, preventing cross-app tracking
- Privacy-preserving: Only a one-way device fingerprint is transmitted to PyLocket servers — raw hardware identifiers never leave the device
- Deterministic: The same device always produces the same fingerprint for the same app, allowing seamless re-activation after restart
- Non-reversible: The stored fingerprint 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 bootstrap sends an activation request to the PyLocket activation service with the license key and a one-way device fingerprint.
Step 2: Server Validation¶
The activation service validates:
- License exists: The key matches a valid license record
- License is active: Status is
ACTIVE(notREVOKEDorEXPIRED) - Device limit check: The number of registered devices does not exceed the limit
- Rate limiting: Activation requests are rate-limited to prevent abuse
- Build check: The build exists and belongs to the correct app
- Key management: The encrypted key material for the build is decrypted server-side using cloud-based key management. The resulting material is re-encrypted for the specific activation before being returned.
Step 3: Token Issuance¶
On success, the activation service returns a cryptographically signed runtime token bound to the device, app, and build, along with encrypted key material and a policy containing configurable token expiry and offline grace period.
Step 4: Caching¶
The activation response is cached locally. Subsequent application launches check this cache first, avoiding a network round-trip if the cached token is still valid.
Step 5: Runtime Initialization¶
The bootstrap initializes the native runtime with the received key material. The native runtime:
- Validates the token and verifies the manifest signature
- Uses the key material to enable on-demand function decryption
- Begins decrypting functions as they are called
- Periodically refreshes the token in the background
Offline Support¶
Online Activation¶
The first activation always requires an internet connection. After successful activation:
- The runtime token is cached locally
- The token has a configurable expiry
Offline Grace Period¶
If the device loses internet connectivity:
- The cached token remains valid until its expiry
- After expiry, the runtime enters the offline grace period (configurable by the developer)
- During the grace period, the application continues to function
- After the grace period expires, the application requires re-activation
flowchart LR
A["Online activation"] --> B["Token cached"]
B --> C["Grace period"]
C --> D["Re-activation required"]
Background Refresh¶
When the device is online, the runtime attempts to refresh the token:
- Before token expiry (proactive refresh)
- On application startup
- 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: 1, configurable up to 10,000). When a new device activates:
- If
active_devices < device_limit: Activation succeeds, new device registered - If
active_devices >= device_limit: Activation fails withDEVICE_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:
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¶
flowchart TD
CREATE["CREATE"] --> ACTIVE["Status: ACTIVE"]
ACTIVE --> ACT1["Customer activates → Device registered"]
ACTIVE --> ACT2["Customer activates on new device → Second device registered"]
ACTIVE --> EXTEND["Developer extends expiry → Expiry updated"]
ACTIVE --> REVOKE["Developer revokes"]
REVOKE --> REVOKED["Status: REVOKED → Activation fails on next check"]
ACTIVE --> EXPIRY["Expiry date passes"]
EXPIRY --> EXPIRED["Status: EXPIRED → Activation fails on next check"]
ACTIVE --> RESET["Developer resets devices → All device records cleared"]
See Also¶
- Licensing Tutorial — Step-by-step setup
- Configure Licensing — Configuration options
- Security Model — Security architecture overview