LicenseKit

Licensing you run yourself, with leases that keep working offline.

A license server, an admin console and an SDK for Electron and Node apps. Your customer types a license key once. The app then holds a short-lived lease signed with Ed25519 and checks it locally.

Three ways to try it without an account: the browser sandbox, an npx quickstart or the desktop demo.

Example lease · signed with Ed25519

eyJhbGciOiJFZDI1NTE5IiwidHlwIjoibGljZW5zZWtpdC1sZWFzZStqd3QiLCJraWQiOiIyMDI2LTEwIn0.eyJpc3MiOiJodHRwczovL2xpY2Vuc2VraXQuY2FyY2hhbGFicy5jb20iLCJhdWQiOiJleGFtcGxlLWFwcCIsInN1YiI6ImN1c180SDhUUTIiLCJqdGkiOiJsc18zSE5WOFIyQyIsImlhdCI6MTc5MTcyNzIwMCwibmJmIjoxNzkxNzI3MjAwLCJleHAiOjE3OTE4MTM2MDAsImxpZCI6ImxpY183UTJNNEs5WCIsImZwIjoic2hhMjU2OjljMWU0YjdhIiwiZmVhdCI6WyJleHBvcnQiLCJ2ciJdLCJyZXYiOjN9.UWL6wVkF7vvXMxuFudzGs-N5AiOKu57dwO82StMyw24SbVSBx0i6iFeSZd7MrBQCDaIpfd0oj3DvePrapV05Ag

HeaderClaimsSignatureSignature verified, key 2026-10
alg · kid
Ed25519 · 2026-10
aud
example-app
exp
12 Oct 2026, 14:00 UTC
feat
export, vr
Last checkonlineDay 9
  1. valid
  2. grace
  3. invalid
  4. clock_suspect

Online. The signature checks out against key 2026-10. The next server check is due in 24 hours.

How a check works

A revoked license stops working within the revocation window

The app checks its lease locally and asks the server again when the revalidation interval ends, every 72 hours on the default policy. If the server cannot be reached, a grace period starts.

Timeline from the last successful check on the default policy: the lease is valid for 72 hours, then a grace period of up to 7 days runs while offline, and after day 10 the lease is invalid.

Revocation windowLast successful check, plus the revalidation interval, plus the grace period: up to 10 days on the default policy. Both are set per policy.

Why short leasesThe same reasoning as short-lived certificates in RFC 9608: a credential that expires soon needs no revocation list.

Clock rollbackIf the device clock reads more than 24 hours earlier than the last time seen, the SDK reports clock_suspect until the next online check.

Integration

Ten lines in your app

The SDK runs in the Electron main process and in plain Node. It verifies leases offline with the public keys your server publishes at /v1/keys.

main.js
const { LicenseKit } = require('@carchalabs/licensekit-electron');const kit = new LicenseKit({  serverUrl: 'https://licenses.example.com',  product: 'example-app',  publicKey: [currentKeyPem, nextKeyPem],  storageDir: app.getPath('userData')});let state = await kit.check();if (state.status === 'unlicensed') state = await kit.activate(licenseKey);if (LicenseKit.hasFeature(state, 'export')) enableExport();
  1. 1kit.check()unlicensed, no lease saved yet
  2. 2kit.activate(licenseKey)valid, lease signed with key 2026-10
  3. 3LicenseKit.hasFeature(state, 'export')true

Security model

What it protects, and what it cannot

Protects against

Edited leasesEvery lease is signed with Ed25519. Changing one claim breaks the signature.
Copying a lease to another deviceThe lease carries a device fingerprint that must match.
Forged algorithmsThe validator accepts Ed25519 only, following the algorithm checks in RFC 8725.
Turning the clock backA clock earlier than the last time seen puts the SDK in clock_suspect.

Does not protect against

A patched applicationChecks run on the customer device. Someone who edits the binary can skip them.
Instant revocationA revoked license works until its revocation window ends.
Unencrypted local storageOn Linux without a keyring, Electron safeStorage falls back to plain text. The SDK flags this state.

Scope

Not in version 1

Listed so you can rule it out early.

  • Floating and concurrent licenses
  • Subscriptions and payment integrations
  • Customer self-service portal
  • Activation by file on air-gapped machines
  • Native and C++ SDKs
  • Multi-tenant sign-up
  • Code signing of the demo app
  • Keys held in a KMS or HSM