Overview
The Pyvorin Edge licensing system uses a cascading validation strategy: dev mode override, local file verification with Ed25519 signatures, remote server validation via HTTPS, and finally a fallback to invalid. The LicenseValidator class implements this cascade, while DevModeValidator provides a convenience subclass that always returns valid for development and CI environments.
LicenseStatus Enum
class LicenseStatus(Enum):
VALID = "valid"
EXPIRED = "expired"
REVOKED = "revoked"
INVALID = "invalid"
NOT_FOUND = "not_found"
All validation results return one of these statuses. NOT_FOUND is currently reserved and not emitted by the production validator.
LicenseInfo Dataclass
@dataclass
class LicenseInfo:
status: LicenseStatus
device_id: str
issued_at: datetime
expires_at: datetime
features: List[str] = field(default_factory=list)
| Field | Type | Description |
|---|---|---|
status | LicenseStatus | Validation result state. |
device_id | str | The device fingerprint passed to validate(). |
issued_at | datetime | UTC timestamp when the license was issued. |
expires_at | datetime | UTC timestamp when the license expires. |
features | List[str] | List of enabled feature flags. |
LicenseValidator
Constructor
class LicenseValidator:
def __init__(self) -> None:
...
The constructor takes no arguments. All configuration is driven by environment variables and filesystem state.
validate(license_key, device_fingerprint)
def validate(self, license_key: str, device_fingerprint: str) -> LicenseInfo
| Parameter | Type | Description |
|---|---|---|
license_key | str | The license key string. Used for remote validation; ignored in dev mode and local file validation (which rely on file contents). |
device_fingerprint | str | A unique identifier for the device, typically derived from CPU serial, MAC address, or a hardware-bound UUID. |
The validation cascade executes in this order:
- Dev mode: If
PYVORIN_DEV_MODE=1, returns VALID immediately with default features and an expiry of 2099-12-31. - Local file: If
~/.pyvorin/license.jsonexists, verify Ed25519 signature, check expiry, and validate device fingerprint binding. Returns VALID, EXPIRED, or INVALID. - Remote server: If
PYVORIN_LICENSE_URLis set, POST{license_key, device_fingerprint, version}to the URL. Returns the server's status mapping. - Fallback: Returns INVALID with empty features and immediate expiry.
from pyvorin_edge.licensing.stub import LicenseValidator
validator = LicenseValidator()
info = validator.validate(
license_key="PYV-LIVE-XXXX-XXXX",
device_fingerprint="a1b2c3d4e5f6",
)
print(info.status) # LicenseStatus.VALID
print(info.features) # ['edge_runtime', 'bundle_signing', 'offline_mode', 'basic_telemetry']
print(info.expires_at) # datetime(2099, 12, 31, 23, 59, 59, tzinfo=timezone.utc)
get_features()
def get_features(self) -> List[str]
Returns the default feature list. This does not perform validation; it is a static capability query.
print(validator.get_features())
# ['edge_runtime', 'bundle_signing', 'offline_mode', 'basic_telemetry']
is_feature_enabled(feature)
def is_feature_enabled(self, feature: str) -> bool
Checks whether a feature name is present in the default feature list. For runtime feature gating, validate the license first and check LicenseInfo.features instead.
assert validator.is_feature_enabled("edge_runtime")
assert not validator.is_feature_enabled("enterprise_analytics")
DevModeValidator
class DevModeValidator(LicenseValidator):
def validate(self, license_key: str, device_fingerprint: str) -> LicenseInfo:
return self._valid_info(device_fingerprint)
A subclass that bypasses all validation checks and always returns VALID. Useful for:
- Local development
- CI/CD pipelines
- Integration tests that should not depend on license server availability
from pyvorin_edge.licensing.stub import DevModeValidator
validator = DevModeValidator()
info = validator.validate("any-key", "any-device")
assert info.status == LicenseStatus.VALID
Environment Variables
| Variable | Effect |
|---|---|
PYVORIN_DEV_MODE=1 | Skips all validation and returns VALID with default features. |
PYVORIN_LICENSE_URL | HTTPS endpoint for remote license validation. If set and no local license exists, a POST request is sent here. |
Local License File Format
The local license file at ~/.pyvorin/license.json must contain:
{
"payload": {
"device_id": "a1b2c3d4e5f6",
"issued_at": "2024-01-15T10:00:00Z",
"expires_at": "2025-01-15T10:00:00Z",
"features": ["edge_runtime", "bundle_signing", "offline_mode", "basic_telemetry"]
},
"signature": "deadbeef...",
"public_key": "cafebabe..."
}
The signature is an Ed25519 signature over the canonical JSON of the payload (sorted keys, no whitespace). The public key is the hex-encoded Ed25519 public key used to verify the signature.
Local vs Remote Validation
| Aspect | Local File | Remote Server |
|---|---|---|
| Network required | No | Yes |
| Revocation check | No (file must be deleted) | Yes (server returns REVOKED) |
| Device binding | Yes (payload.device_id) | Server-side logic |
| Latency | ~1 ms (file + crypto) | ~50-500 ms (HTTPS roundtrip) |
| Best for | Offline edge devices | Cloud-managed fleets |
Trust Anchor Integration
The validator uses the cryptography library's Ed25519 implementation. The public key embedded in the license file acts as the trust anchor. There is no central certificate authority; instead, each license file is self-contained with its own verification key.
For enterprise deployments, you can pre-install a fleet-wide public key on devices and validate licenses signed with the corresponding private key. The private key should never leave your license-management server.
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
import json, base64
# Generate a fleet key pair (do this once on your license server)
priv = Ed25519PrivateKey.generate()
pub = priv.public_key()
pub_hex = pub.public_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw
).hex()
# Sign a license payload
payload = {
"device_id": "a1b2c3d4e5f6",
"issued_at": "2024-01-15T10:00:00Z",
"expires_at": "2025-01-15T10:00:00Z",
"features": ["edge_runtime", "bundle_signing"],
}
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
signature = priv.sign(canonical)
license_file = {
"payload": payload,
"signature": signature.hex(),
"public_key": pub_hex,
}
import pathlib
pathlib.Path("~/.pyvorin/license.json").expanduser().write_text(
json.dumps(license_file, indent=2)
)
Backward Compatibility
LicenseStub is an alias for DevModeValidator, maintained for existing tests and consumers:
from pyvorin_edge.licensing.stub import LicenseStub
# LicenseStub is DevModeValidator
assert LicenseStub is DevModeValidator
Complete Example: License Check on Startup
import os
import sys
from pyvorin_edge.licensing.stub import LicenseValidator, LicenseStatus
def check_license() -> bool:
validator = LicenseValidator()
fingerprint = os.environ.get("DEVICE_FINGERPRINT", "unknown")
key = os.environ.get("PYVORIN_LICENSE_KEY", "")
info = validator.validate(license_key=key, device_fingerprint=fingerprint)
if info.status == LicenseStatus.VALID:
print(f"License valid until {info.expires_at}")
print(f"Features: {info.features}")
return True
elif info.status == LicenseStatus.EXPIRED:
print("License expired. Renew at https://pyvorin.com/account")
return False
else:
print(f"License validation failed: {info.status.value}")
return False
if __name__ == "__main__":
if not check_license():
sys.exit(1)
# Continue with normal startup...