LicenseValidator API Reference
Complete reference for LicenseValidator, LicenseInfo, LicenseStatus, DevModeValidator, environment variables, local vs remote validation, and trust anchor integration.
Published Jun 2, 2026
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...