License file
Your .hxlic file (also named helixor.lic) says who you are, which packs and features you may use, and until when. It also carries the key that opens your packs. This page lists every field and every check the runtime makes.
Treat the license file as a secret
crypto.content_key is the key your packs are encrypted with. Anyone who has your license file can decrypt your packs and compile new ones for it. Store the license like a private key: file mode 600, never in source control or a container image layer, and injected at deploy time from your secret store.
Format#
A UTF-8 JSON document. Every field except signature is covered by the signature, so changing any value, including whitespace inside a string, invalidates the file.
{
"license_version": "1.0",
"license_id": "hx_lic_org_example_1790000000",
"issued_at": "2026-09-01T12:00:00+00:00",
"identity": {
"organization": "Example Corp",
"org_id": "org_example",
"contact_email": "security@example.com"
},
"entitlements": {
"tier": "DEVELOPER",
"plan_name": "Developer",
"overage_policy": "TRUE_UP",
"licensed_packs": ["compliance.regulatory_pii_guard.v1", "custom.*"],
"licensed_solvers": ["solver.tcn.*", "bin_packing.*"],
"features": ["in_process_streaming", "decision_as_a_function", "custom_playbook_compilation"],
"max_decisions_per_minute": null,
"max_decisions_lifetime": null
},
"validity": {
"valid_from": 1788264000.0,
"valid_until": 1819800000.0,
"grace_period_days": 14
},
"crypto": {
"key_id": "ep1_2026",
"content_key": "<secret>",
"algorithm": "Ed25519-AES-256-GCM"
},
"signature": "<128 hex characters>"
}
Fields#
| Field | Type | Meaning |
|---|---|---|
license_version | string | 1.0. |
license_id | string | Unique per issued license. It is bound into every pack sealed for this license (see Packs). |
issued_at | string | ISO 8601 UTC time of issue. |
identity.organization | string | Your organization's name. |
identity.org_id | string | Your organization ID. |
identity.contact_email | string | License contact. |
entitlements.tier | string | COMMUNITY, DEVELOPER or ENTERPRISE. |
entitlements.plan_name | string | Display name of your plan. |
entitlements.overage_policy | string | NO_OVERAGE_FEES, BLOCK_AT_CAP or TRUE_UP. Informational in 0.2.1. In the next release it decides what a compiled pack does past a decision limit: TRUE_UP records the overage and continues; the others refuse the decision. |
entitlements.licensed_packs | string[] | Glob patterns (*, ?) of pack IDs you may compile and load, for example custom.*. |
entitlements.licensed_solvers | string[] | Glob patterns of solver IDs your packs may use. If the field is absent, it defaults by tier: ENTERPRISE gets ["*"], DEVELOPER gets ["solver.tcn.*", "bin_packing.*"], others get ["solver.tcn.basic"]. |
entitlements.features | string[] | See Features. |
entitlements.max_decisions_per_minute, max_decisions_lifetime | int | null | Parsed, but not enforced when you run a compiled pack in 0.2.1. Enforced for compiled packs in the next release, per engine instance (see Licensing). |
validity.valid_from, valid_until | number | POSIX timestamps in seconds. |
validity.grace_period_days | int | Days the license keeps working after valid_until. Default 14. |
crypto.key_id | string | Identifies the content key generation. |
crypto.content_key | string | Secret. The pack encryption key is SHA-256 of this string. |
crypto.algorithm | string | Ed25519-AES-256-GCM. |
signature | string | Hex Ed25519 signature from the Helixor license authority. |
Verification#
Every time a license is loaded (by helixor-pack, when a pack is unsealed, or in POST /v1/decision with license_data), the runtime checks, in order:
- Signature present
A missing or empty
signaturefails withLicenseSignatureInvalidError. - Signature valid
The runtime rebuilds the canonical form: every field except
signature, serialized as JSON with sorted keys and no spaces. It verifies the Ed25519 signature against the Helixor authority public key built into the runtime. Any change fails withLicenseSignatureInvalidError. A license signed by a revoked authority key fails with its subclassLicenseRevokedAuthorityError: 0.2.1 rotated the authority key, so a license issued for 0.2.0 must be reissued, and packs compiled for it compiled again. - Not before
If the current time is before
valid_from, it fails withLicenseNotYetValidError. - Not expired
If the current time is after
valid_untilplusgrace_period_days× 86,400 seconds, it fails withLicenseExpiredError. Betweenvalid_untiland that point the license still works, andinspect-licensereportsIN GRACE PERIOD.
Verification is offline. It uses the built-in public key and your system clock; no call is made to Helixor. Keep host clocks synchronized.
Pack and solver entitlements are checked separately, when you compile or load a pack. See Packs and manifest.
helixor-pack inspect-license ~/.helixor/helixor.lic
Tiers#
| Tier | How you get it | In 0.2.1 |
|---|---|---|
| Community | Built into the runtime. No file. | The runtime with the built-in example pack: evaluate, stream, serve. compile_custom_rule raises (in the next release it is removed from every engine). |
| Developer | Free registration. You receive a .hxlic. | Compile and run packs your licensed_packs allow. |
| Enterprise | Commercial agreement. | Same format, wider entitlements. |
Installing a license file is currently manual (see Licensing). A helixor license activate command is Planned.
Features#
| Feature | Effect in 0.2.1 |
|---|---|
custom_playbook_compilation | Lets you compile and load a pack whose pack_id is not in licensed_packs. |
in_process_streaming | Recorded; not checked by the runtime. |
decision_as_a_function | Recorded; not checked by the runtime. |
Where the runtime looks for the license#
| Caller | Search order |
|---|---|
helixor-pack commands | --license if given; otherwise $HELIXOR_LICENSE_FILE, then ./helixor.lic, then ~/.helixor/helixor.lic. If none exists, the command exits with status 1. |
HelixorEngine.load_pack | The license_file argument; without it, $HELIXOR_LICENSE_FILE, then ~/.helixor/helixor.lic. See the Python reference. |
HelixorEngine() | None. It always uses the built-in Community license. |
See Configuration for the environment variables.