Licensing
How Rampline licenses work, for the software owner and for anyone who runs an installation.
Principles
- A license is a signed statement of what the licensee may do. It is checked on the installation, offline, with the public key that ships with the code.
- There is no phone-home, no usage reporting and no remote switch. Nothing in the code lets the licensor disable an installation.
- A license problem never locks or deletes data. On the independent edition it stops the creation of new workspaces and new users; everything that exists keeps working.
- The software records the rights granted. The legal terms belong in a written agreement drafted by a lawyer. docs/legal/ holds outlines for that lawyer, not finished agreements.
Keys
The software owner creates one key pair:
npm run license:keygen
.license-keys/private.pemis the private key. It signs licenses and revocation lists. It is listed in.gitignoreand must never be committed or shipped. In production, set it asLICENSE_PRIVATE_KEY(line breaks as\n) on the owner's server only.license/public.pemis the public key. It is committed and ships with every installation.LICENSE_PUBLIC_KEYoverrides it.
Running the keygen again creates a new pair, and every license signed with the old key stops verifying. Keep a backup of the private key in a safe place.
License content
| Field | Meaning |
|---|---|
| serial | RL-YYYY-NNNN, for invoices and agreements |
| type | Hosted SaaS subscription, white-label hosted, self-hosted commercial, agency reseller, source-code commercial, full software asset transfer |
| edition | cloud, whitelabel_cloud or independent; activating a license sets the edition |
| licensee | Name and email |
| maxWorkspaces, maxUsers | Empty means unlimited; checked when workspaces and users are created |
| domains | Empty means any; otherwise the app host must be one of them or a subdomain |
| version | Range such as >=0.1 <2.0 or 1.x |
| validFrom, validUntil, graceDays | Empty end means perpetual; after the end the grace period runs before the license counts as expired |
| rights | Commercial use, white label, resale of subscriptions, modification, source access, redistribution, transfer to another party, exclusive transfer of intellectual property: a record of what the agreement grants |
Issuing and revoking
On the owner's installation a platform admin opens Platform, Licenses, Issue license. The license text (RL1.…) stays available in the list. Give it to the licensee together with the signed agreement.
Revoking or suspending a license adds its serial to the revocation list at /api/license/revocations (signed, RLC1.…). An installation only learns about it if its operator sets LICENSE_REVOCATION_URL to that address; the worker then fetches it hourly. Without that variable a revocation takes effect only through the agreement.
Activating on an installation
During the first-run setup (step 3), or later under Platform, Licenses, Activate license: paste the RL1.… text. Signature, dates, domain and version are checked at once and the result is shown in plain words: valid, in grace period, expired, wrong domain, wrong version or revoked.
Environment variables
| Variable | Where | Purpose |
|---|---|---|
| LICENSE_PUBLIC_KEY | optional, any installation | Overrides license/public.pem |
| LICENSE_PRIVATE_KEY | owner's server only | Signs licenses and revocation lists |
| LICENSE_REVOCATION_URL | optional, licensee installations | Signed revocation list fetched hourly |
Tests
tests/whitelabel.test.ts covers signing, tampering, a foreign key, validity, grace, domain, version, revocation and the independent edition refusing new workspaces without a license.