Licensing

Issue signed licenses, activate device-bound seats, verify access offline, rotate refresh credentials, and revoke grants without coupling product policy to the token protocol.

Supported approaches

Offline license verification

available

Validate versioned Ed25519-signed payloads locally with explicit clock, grace, product, device, and revocation inputs.

Packages

@playstack/licensing

Frameworks and integrations

Issuance and activation

available

Turn application-owned purchase policy into single-display activation codes, bounded signed payloads, and device seats.

Refresh and revocation

available

Rotate refresh credentials, detect reuse, deactivate seats, and apply revocation state when connectivity returns.

Entitlement projection

available

Translate an edition and limits into the stable grants also used by subscriptions, registration, and staff access.

Frameworks and integrations

framework

NestJS

Connect portable Playstack capabilities to dependency injection, guards, decorators, request context, workers, and lifecycle hooks.

integration

Prisma

Persist Playstack capabilities through explicit application-owned Prisma clients, transactions, and managed schema fragments.

Package reference

@playstack/licensing

Verify a paid application offline

The application embeds issuer public keys and supplies its explicit product, device, trusted-time, grace, and revocation policy to the portable verifier.

ts
import {
  RECOMMENDED_OFFLINE_GRACE_SECONDS,
  WebCryptoLicenseVerifier,
  createLicensing,
} from '@playstack/licensing'

const licensing = createLicensing(
  new WebCryptoLicenseVerifier({
    subtle: crypto.subtle,
    keys: { 'production-2026': issuerPublicKey },
  }),
)

const result = await licensing.validate({
  token,
  product: 'quickzones',
  deviceId,
  now: Math.floor(Date.now() / 1_000),
  highestTrustedTime,
  offlineGraceSeconds: RECOMMENDED_OFFLINE_GRACE_SECONDS,
  isRevoked: (licenseId) => revokedIds.has(licenseId),
})

Offline verification cannot observe immediate revocation, so payload validity and grace are bounded product policy. Omitting offlineGraceSeconds means zero grace.

Issue without surrendering key custody

@playstack/licensing-issuer owns issuance, activation-code digests, device seats, refresh rotation, deactivation, and revocation. The application supplies purchase authorization, encrypted response storage, distribution, and a signing seam backed by its KMS, HSM, or remote signer.

ts
const issuer = createLicensingIssuer({
  persistence,
  authorizer: applicationLicensePolicy,
  distribution: transactionalDeliveryOutbox,
  signer: kmsBackedEd25519Signer,
  secrets,
  responseVault,
  events,
  clock,
  ids,
})

@playstack/nest-licensing exposes separate client activation and authorized administration services. Your controllers, authentication, product catalog, payment source, mail templates, and exact signed-license distribution policy remain application-owned.

Compose direct and store purchases honestly

A direct license and an App Store receipt are different credentials. Native applications can project both into one application-owned access layer while retaining separate verification paths. Deterministic vectors from @playstack/licensing/vectors let TypeScript, Swift, and Rust implementations execute the same protocol cases.

Go

Playstack Pro tag
OriginsPricingBlogNewsletterChangelogStatusRoadmap
ContributorsCommunityIn Use ShowcaseCase StudiesPartnersSponsors
FAQsSupportContact

© 2026 Playstack. All rights reserved.

With OSS
Terms of ServicePrivacy PolicyCookie PolicyImprint

By

Commune Software