Skip to content

URD: Licensing

ModuleCORE-15Versionv0.1
StatusBuiltDate2026-06-05

Business documentation. This URD is Licensing's feature list - each feature below is one Functional Area (<AREA>). The same <AREA> keys the feature's PRDs (PRD-<AREA>-NNN) and tests (TC-<AREA>-NNN), and each feature is listed in the Delivery feature catalog. See the Feature Spine convention.

1. Purpose

Define the user-facing requirements for the Licensing module - reusable plans, license issuance and lifecycle, device activation, and runtime validation - so platform operators can control exactly what each merchant is entitled to run, merchants can self-serve a free trial, and every other service can enforce features and seat quotas offline against a trustworthy signed certificate.

2. Scope

IncludedExcluded
Reusable plans: trial / subscription / perpetualBilling, invoicing, dunning
Typed feature flags and seat quotas per planPayment / subscription-charge integration
Public plan catalogUsage metering / heartbeat tracking
License issuance + lifecycle (renew / suspend / reinstate / revoke)Per-feature runtime enforcement (each consumer's own job)
Self-service free trialLicense management UI (frontend concern)
Device activation (fingerprint binding, seat limit)Certificate verification (every other service, offline)
Runtime validation returning a signed certificateEager expiry sweeping (expiry is lazy)
Per-license override of plan defaults
Append-only event audit log

3. Definitions

TermDefinition
PlanA reusable template a license is issued from; carries type, duration, grace period, seat limit, and feature flags
Feature flagA typed key/value on a plan (boolean / number / text / json) that switches a feature on/off or sets a quota
LicenseAn issued entitlement bound to a merchant or user, with a unique key and a lifecycle status
ActivationA binding of a license to one device, identified by a fingerprint, counted against the seat limit
Seat limitThe maximum number of unique devices that may activate against a single license
Grace periodA window after expiry during which the license is still honoured, flagged as in-grace
CertificateA signed snapshot of a license's status and resolved features, trusted offline by other services
OverridePer-license adjustments to a plan's seat limit or feature values

4. Conceptual Model

Conceptual only - the full schema lives in the developer domain model.

5. Feature Catalog

The feature list of this module. Each row is one feature (a Functional Area). Detail in §6. Mirrored in the Delivery feature catalog.

Feature IDFeaturePhaseStatusPriority
PLNPlans & Feature FlagsP1BuiltHigh
LICLicense LifecycleP1BuiltHigh
ACTDevice ActivationP2BuiltHigh
VALRuntime Validation & EntitlementsP1BuiltHigh

Status: live from Plane where mapped, otherwise registry-declared. Vocabulary mirrors Plane (state-group / phase).

6. Features

One sub-section per feature, in catalog order. Each feature keeps its description, requirements, and acceptance together. Priority = MoSCoW (Must / Should / Could / Won't).

PLN - Plans & Feature Flags Built

Feature ID: licensing/PLN · Phase: P1 · PRDs: PRD-PLN-001 · Dev: @nx/licensing

What it does for users: platform operators define reusable plans - trial, subscription, or perpetual - each carrying a duration, optional grace period, a device seat limit, and a bag of typed feature flags that licenses issued from the plan will grant.

Requirements

IDPRequirement
URD-PLN-001MCreate a plan of type trial, subscription, or perpetual
URD-PLN-002MA plan defines a duration (or null for perpetual) and an optional grace period
URD-PLN-003MA plan optionally caps the number of devices (seat limit); null = unlimited
URD-PLN-004MAttach typed feature flags to a plan: boolean, number, text, or json
URD-PLN-005MA feature flag can be deactivated, resolving to its type's empty/off default without deletion
URD-PLN-006MThe feature-flag code is unique within a plan
URD-PLN-007SPlans carry a localized display name and description and a display order
URD-PLN-008MA public catalog lists active plans with their active features, in display order
URD-PLN-009SPlans are soft-deleted (deactivated/archived), never hard-deleted from the app

Acceptance

AC-PLN-01: Plan with features
GivenWhenThen
An operator creating a subscription planThey set duration, grace period, seat limit, and several feature flagsThe plan is saved; the feature-flag codes are unique within the plan
A feature flag set to deactivatedThe plan's features are resolvedThat flag returns its type's empty/off default rather than its configured value
AC-PLN-02: Public catalog
GivenWhenThen
Several active plans and one archived planThe catalog is requestedOnly active plans appear, ordered by display order, each with its active features inlined

LIC - License Lifecycle Built

Feature ID: licensing/LIC · Phase: P1 · PRDs: PRD-PLN-001 · Dev: @nx/licensing

What it does for users: a license is issued from a plan and bound to a merchant or user with a unique key, then moves through a tracked lifecycle - renew, suspend, reinstate, revoke - with every change audited and the certificate re-signed.

Requirements

IDPRequirement
URD-LIC-001MIssue a license from a plan, bound to a merchant or user, with a unique generated key
URD-LIC-002MAn issued license computes its expiry from the plan's duration and grace period (perpetual = no expiry)
URD-LIC-003MA license has a status: activated, suspended, expired, or revoked
URD-LIC-004MSuspend an active license, then reinstate it back to active
URD-LIC-005MRenew a license to extend its validity; renewing an expired license restores it to active
URD-LIC-006MRenew is rejected for a perpetual license (no duration to extend)
URD-LIC-007MRevoke a license permanently; revoked is terminal and cannot be renewed or reinstated
URD-LIC-008MA merchant self-serves a single free-trial license; an existing trial is returned rather than duplicated
URD-LIC-009MEvery lifecycle action is recorded in an append-only event log
URD-LIC-010MEach lifecycle change re-signs and re-publishes the license certificate
URD-LIC-011SA license may override its plan's seat limit and feature values

Acceptance

AC-LIC-01: Issue & lifecycle
GivenWhenThen
A subscription planA license is issued for a merchantA unique key is generated; expiry = start + duration; status activated; a created event is logged
An active licenseIt is suspended then reinstatedStatus goes activated → suspended → activated; both actions are audited
A perpetual licenseRenew is attemptedRejected - a perpetual license has no duration to extend
An expired licenseIt is renewedStatus returns to activated with a fresh validity period starting now
Any licenseIt is revokedStatus → revoked (terminal); further renew/reinstate are rejected
AC-LIC-02: Free trial
GivenWhenThen
A merchant with no trialThey request a free trialA trial license is issued for them
A merchant who already has a trialThey request a free trial againThe existing trial is returned; no duplicate is created

ACT - Device Activation Built

Feature ID: licensing/ACT · Phase: P2 · PRDs: PRD-ACT-001 · Dev: @nx/licensing

What it does for users: a license is bound to specific devices by fingerprint; each unique device consumes one seat, the plan's seat limit is enforced, and a device can be deactivated to free its seat.

Requirements

IDPRequirement
URD-ACT-001MActivate a license on a device, identified by a fingerprint, with optional label, platform, hostname
URD-ACT-002MRe-activating the same device on the same license reuses its existing seat (idempotent)
URD-ACT-003MThe number of unique device seats cannot exceed the plan's (or override's) seat limit
URD-ACT-004MA null seat limit means unlimited device activations
URD-ACT-005MDeactivate a device to free its seat
URD-ACT-006SActivation and deactivation are recorded in the event log
URD-ACT-007MActivation is refused when the license is not in an active status (suspended / expired / revoked / not yet started)

Acceptance

AC-ACT-01: Seat enforcement
GivenWhenThen
A license with seat limit 2 and 2 devices activeA third unique device activatesRejected - seat limit reached
The same device that is already activeIt activates againThe existing seat is reused; no new seat is consumed
A licensed deviceIt is deactivatedThe seat is freed and may be taken by another device
AC-ACT-02: Activation guarded by license status
GivenWhenThen
A suspended, expired, or revoked licenseA device tries to activate against itRejected - the license is not in an active status
An active license with a free seatA device activates against itA seat is consumed and the activation succeeds

Built per PRD-ACT-001.

VAL - Runtime Validation & Entitlements Built

Feature ID: licensing/VAL · Phase: P1 · PRDs: PRD-PLN-001 · Dev: @nx/licensing

What it does for users: a service validates a license key and receives the license status, its resolved feature set, the device-seat usage, and a signed certificate that other services trust offline to gate features and seats.

Requirements

IDPRequirement
URD-VAL-001MValidate a license key and return whether it is valid plus a result code
URD-VAL-002MAn inactive license (suspended / revoked / expired) validates as invalid with a status-specific code
URD-VAL-003MA not-yet-started license validates as invalid (not started)
URD-VAL-004MA license past expiry but within grace validates as valid with a grace-period code
URD-VAL-005MA license past grace is lazily flipped to expired on validation and returns invalid
URD-VAL-006MValidation returns the resolved feature set, with per-license overrides applied
URD-VAL-007MWhen a device fingerprint is supplied, validation handles the seat (reuse or create under the limit)
URD-VAL-008MA successful validation returns a signed certificate other services can verify offline
URD-VAL-009SValidation records the last-validated time on the license (best-effort)

Acceptance

AC-VAL-01: Validation outcomes
GivenWhenThen
An active, in-date licenseIt is validatedValid; resolved features and a signed certificate are returned
A license within its grace periodIt is validatedValid with a grace-period code
A license past graceIt is validatedIt is flipped to expired and returns invalid (expired)
A suspended or revoked licenseIt is validatedInvalid with the matching status code
AC-VAL-02: Validation with a device
GivenWhenThen
A valid license with a free seat and a new fingerprintIt is validated with that fingerprintA seat is consumed and the validation succeeds
A valid license at its seat limit and a new fingerprintIt is validated with that fingerprintValidation fails - seat limit reached

7. Constraints & Non-Goals

Constraints

IDConstraint
C-01A license is always bound to exactly one principal (merchant or user)
C-02A license key is unique among live licenses
C-03A feature-flag code is unique within a plan
C-04One seat per unique (license, device fingerprint) pair
C-05Active device seats never exceed the effective seat limit
C-06Revoked is terminal - no renew or reinstate
C-07The event log is append-only and survives license deletion
C-08Expiry is detected lazily on validation; there is no background sweeper
C-09Other services only verify the certificate offline; they never call licensing at runtime to authorize

Non-Goals

  • Billing, invoicing, and dunning
  • Payment / subscription-charge integration
  • Usage metering and heartbeat tracking
  • Eager / scheduled expiry sweeping
  • Per-feature runtime enforcement (each consuming module does its own gating)
  • License management UI (frontend concern)

8. Version History

DateAuthorDescriptionVer
2026-06-05Claude (AI pair)Initial URD authored from the @nx/licensing package and developer docs (Feature Spine)v0.1

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.