Policy Fields Reference
Canonical reference for every policy field — API name, type, validation rule, DB column, and default. These names are part of the Licentric v1 stability contract: any rename will follow a deprecation cycle of at least one minor version.
All Fields
| API Name | Type | Validation | DB Column | Default |
|---|---|---|---|---|
| id | string (UUID) | auto-generated | id | gen_random_uuid() |
| productId | string (UUID) | .uuid() | product_id | — |
| name | string | .min(1).max(255) | name | — |
| template | enum | null | "desktop_app" | "cli_tool" | "saas" | "trial" | "custom" | template | null |
| maxMachines | integer | null | .int().positive() | max_machines | null |
| maxUses | integer | null | .int().positive() | max_uses | null |
| floating | boolean | .boolean() | floating | false |
| durationDays | integer | null | .int().positive() | duration_days | null |
| expirationStrategy | enum | "RESTRICT_ACCESS" | "ALLOW_ACCESS" | "REVOKE" | expiration_strategy | "RESTRICT_ACCESS" |
| requireHeartbeat | boolean | .boolean() | require_heartbeat | false |
| heartbeatIntervalMinutes | integer | .int().min(1) | heartbeat_interval_minutes | 60 |
| heartbeatCullStrategy | enum | "DEACTIVATE_DEAD" | "KEEP_DEAD" | heartbeat_cull_strategy | "DEACTIVATE_DEAD" |
| requireFingerprint | boolean | .boolean() | require_fingerprint | true |
| fingerprintUniqueness | enum | "PER_LICENSE" | "PER_POLICY" | "PER_ACCOUNT" | fingerprint_uniqueness | "PER_LICENSE" |
| offlineAllowed | boolean | .boolean() | offline_allowed | true |
| offlineMaxDays | integer | .int().min(1) | offline_max_days | 14 |
| allowMachineTransfer | boolean | .boolean() | allow_machine_transfer | false |
| isTrial | boolean | .boolean() | is_trial | false |
| trialDurationDays | integer | null | .int().positive() | trial_duration_days | null |
| overridable | boolean | .boolean() | overridable | true |
| maxUniqueFingerprints | integer | null | .int().positive() | max_unique_fingerprints | null |
| metadata | object | .record(z.string(), z.unknown()) | metadata | {} |
Field Descriptions
id
Unique identifier for the policy.
productId
The product this policy is bound to. All licenses created against this policy belong to this product.
name
Human-readable label for the policy (shown in dashboard).
template
Optional template that pre-fills sensible defaults. The template is recorded but does not constrain other field values.
maxMachines
Maximum machines that can be activated against a license under this policy. null = unlimited. Per-license override available via maxMachinesOverride.
maxUses
Maximum validate-key calls allowed before the license is exhausted. null = unlimited. Per-license override available via maxUsesOverride.
floating
When true, activating a new machine after the limit auto-deactivates the oldest machine instead of rejecting. Useful for floating-seat licensing.
durationDays
Default expiration window for new licenses created under this policy (computed from createdAt). null = perpetual. Overridden by explicit expiresAt on createLicense.
expirationStrategy
Behavior when a license expires. RESTRICT_ACCESS: validation fails. ALLOW_ACCESS: validation succeeds with code=EXPIRED_ALLOWED (use sparingly — eliminates renewal pressure). REVOKE: status flips to revoked at expiry.
requireHeartbeat
When true, machines must send periodic heartbeats or are considered dead.
heartbeatIntervalMinutes
How often a machine must heartbeat. Validation marks a machine dead if 2× this interval has elapsed since the last heartbeat.
heartbeatCullStrategy
Action taken when a machine is detected as dead. DEACTIVATE_DEAD: free the activation slot. KEEP_DEAD: keep the slot occupied (machine count unchanged).
requireFingerprint
When true, every activation/validation must include a machine fingerprint. Disable only for SaaS-style licensing where the customer is the unit, not the device.
fingerprintUniqueness
Scope at which a fingerprint must be unique. PER_LICENSE allows the same machine on multiple licenses; PER_POLICY blocks reuse across licenses sharing this policy; PER_ACCOUNT blocks reuse anywhere in the account.
offlineAllowed
When true, the SDK can issue offline license files (signed certificates) via /licenses/{id}/checkout. Disable for environments where offline use is forbidden.
offlineMaxDays
Maximum TTL (in days) the SDK can request when checking out an offline license file. Hard ceiling — requests beyond this are rejected.
allowMachineTransfer
When true, customers can deactivate one machine and re-activate on a new one without admin intervention. Disable to require manual support for transfers.
isTrial
Marker that licenses created under this policy are trials. Used for analytics and conversion tracking; does not by itself enforce expiration.
trialDurationDays
Default trial length when isTrial=true. Functions as durationDays for trial licenses.
overridable
When false, per-license overrides (maxMachinesOverride, maxUsesOverride) are rejected at creation. Enforces strict policy compliance.
maxUniqueFingerprints
Sharing-detection threshold. When more than this many distinct fingerprints validate the same license, a license.sharing_detected event fires. null = detection disabled.
metadata
Free-form JSON for integrator-specific data. Common uses: feature flags, tier labels, pricing-plan back-references, A/B test markers.
Naming Conventions
- API field names use camelCase (
maxMachines). - DB columns use snake_case (
max_machines). - Repository layer maps automatically — application code only ever touches the camelCase form.
- Boolean fields prefixed with
allow,require,is, or no prefix when neutral. - Duration fields suffixed with their unit:
Days,Minutes.
Alternative Names (Not Currently Exposed)
Some external sources or community discussions reference policy concepts with different names than the Licentric v1 contract. Those alternative names are not currently exposed in the API. If you see these in third-party tutorials, translate to the canonical names above:
| Alternative | Canonical (use this) | Notes |
|---|---|---|
| maxActivations | maxMachines + maxUses | Licentric splits machine count from validation count — they enforce different limits. |
| transferAllowed | allowMachineTransfer | Licentric prefixes permission booleans with allow. |
| trialDays | trialDurationDays | Licentric uses an explicit Duration infix for time spans. |
| bindingStrategy | fingerprintUniqueness | Different semantics — bindingStrategy implies which identifier; fingerprintUniqueness only controls scope. |
| revalidationIntervalMinutes | heartbeatIntervalMinutes | Licentric ties revalidation to the heartbeat protocol. |
| gracePeriodDays | (on stripe_mappings, not policies) | Per-Stripe-mapping field — payment-failure grace, not policy-level. |
| transferCooldownDays | (not currently exposed) | No equivalent. Tracked for a future minor release. |
| featureFlags | metadata.featureFlags | Stored inside the free-form metadata JSON field by convention. |