Skip to main content

License key

The framework is fully usable without a license. Every concept in the documentation — connectors, dictionary, screens, menus, dashboards, charts, jobs, auth — works on the open feature set on a fresh install.

A license key unlocks a curated set of additional integrations: a few production-grade connectors (proprietary databases, custom APIs), packaged customer apps and advanced features. The key is set under Settings → Framework → License and its live status is surfaced on the dedicated Settings → License page.


At a glance

FORMAT
RS256-signed JWT (~600 characters). Long-lived (usually a year).
WHERE IT LIVES
In the environment (kept out of disk). Referenced by name from the License field.
VERIFIED
Once at startup. A failed verification leaves the framework in restricted mode — open features still work.
SCOPE
Connectors marked Licensed, packaged customer apps, premium AI features.

Settings → License

The dedicated License tab is read-only and surfaces the current state.

Settings → License
● Accepted
Customer
Acme Corp
Edition
Enterprise
Instance
prod-eu-west
Expires
2026-05-19 in 30 days
Licensed connectors
jdedwardssapsnowflake
Licensed apps
nomajdenomasx-1
User cap
72 / 250 (29%)
AI provider
Anthropic · 2 110 / 5 000 messages today
↻ Re-verify
FieldSource
StatusAccepted / Rejected — <reason> / Not configured.
CustomerThe customer claim of the JWT.
EditionThe edition claim.
ExpiresThe exp claim. A warning chip appears 30 days before expiry.
Licensed connectorsList from the key's features.connectors. A red dot appears next to entries that aren't actually defined in the install.
Licensed appsSame shape for features.apps.
User capCurrent user count + cap, with a 90% / 95% / 100% colour scale.
AI entitlementsAllowed providers + daily message cap + current usage.
↻ Re-verifyRe-reads the key from the environment and re-verifies the signature without a restart.

The tab is gated by license:read.


Installing a key

The key lives in the environment of the host (kept out of disk). In Settings → Framework → License, the License key field stores the name of the environment variable holding the JWT, not the JWT itself:

FieldEffect
License keyReference to the env var. Default ${LIBERTY_LICENSE_KEY}.
Public key pathOptional override for the bundled public key. Useful when running with a private signing authority (OEM partners that re-sign keys).

Installing a new key on a host:

  1. Export the JWT under the env var: export LIBERTY_LICENSE_KEY="eyJhbGciOi…".
  2. Restart the framework, or click ↻ Re-verify on the License tab — the framework re-reads the variable and re-runs the signature check without a full restart.

The startup log prints one line of confirmation:

INFO liberty.licensing license accepted — customer="Acme Corp" edition="enterprise" expires=2026-05-19T00:00:00Z

A bad key logs the failure and continues; the framework enters restricted mode:

WARN liberty.licensing license rejected — reason="signature invalid"
WARN liberty.licensing running in restricted mode — licensed features disabled

In restricted mode:

  • Every connector marked Licensed is hidden — it doesn't appear in the catalogue, the AI tool list or any menu.
  • Packaged apps in the key's features.apps don't register their content.
  • The License tab shows the rejection reason and a banner appears across the header.
  • Every other concept (open connectors, screens, menus, dashboards, jobs, auth) keeps working.

Restricted mode is the default on a fresh install with no key — it isn't an error state, it's the unlicensed mode.


What's in a licensed connector

In Settings → Connectors, every entry has a Licensed toggle. When on, the connector loads only when its identifier is present in the key's features.connectors. In restricted mode, the Connectors page lists the connector as Locked — requires license <id> with the rest of its definition greyed out.

This is what gates the bundled vendor connectors (JD Edwards, SAP, Snowflake, …). The mechanism is open — customers can mark their own connectors Licensed and ship keys to their own customers if they distribute custom apps.


Verifying a key out-of-band

The liberty-license CLI verifies a key without booting the framework:

.venv/bin/liberty-license verify "$LIBERTY_LICENSE_KEY"
# license accepted
# customer="Acme Corp" edition="enterprise"
# expires=2026-05-19T00:00:00Z (in 30 days)
# features.connectors: [jdedwards, sap, snowflake]
# features.apps: [nomajde, nomasx-1]

Exits non-zero with the diagnostic on bad / expired / wrong-audience keys. See CLI reference → liberty-license for every flag.


Rotation and renewal

A renewal key is installed by:

  1. Export the new JWT under the env var on each host.
  2. Restart the framework, or click ↻ Re-verify.

For high-availability installs:

PhaseAction
30 days before expiryRequest the renewal key from the vendor. The current key's Expires chip turns yellow.
7 days before expiryInstall the new key on each replica via your secret-management tool.
At expiryOld key naturally rejected; new one takes over. No restart required because the rolling secret update already happened.

Failure modes

The Settings → License tab surfaces the diagnostic directly. Common rejections:

Status textCauseRecovery
signature invalidWrong public key, tampered JWT.Re-check the key. If using a partner signing authority, set Public key path to its key.
expired (2026-04-30)Past exp timestamp.Install a renewed key.
audience mismatchThe JWT was issued for a different product.Confirm the vendor sent a Liberty key.
malformedThe env var doesn't contain a valid JWT (extra whitespace, accidental truncation).Re-export the key carefully — copy from the source verbatim.
user cap reachedThe key's features.users.max matches the current user count.Request a larger cap, or deactivate inactive users.

Permissions

The License tab is gated by license:read (view) and license:write (re-verify, swap public key path). The Framework → License sub-form is gated by settings:framework.


Tips & best practices

  • Treat the key as configuration, not a deep secret. It's signed and verifiable on the receiver side; pasting it into a Slack thread doesn't compromise anything. Keep it in your secret manager anyway for hygiene.
  • Set Public key path only when needed. The default works for keys issued by Nomana-IT — overriding is for partner / OEM deployments only.
  • Watch the 30-day expiry chip. Renewing late means a short window where licensed connectors disappear from the UI.
  • Never edit a key by hand. A single character change invalidates the signature; ask the vendor for a new key instead.
  • Keep the open feature set self-sufficient. A well-designed install should still be useful in restricted mode — use licensed connectors for differentiation, not for the core flow.

Under the hood

The license payload is stored only in memory after the env var is read. The Settings → Framework form persists the name of the env var + the optional public-key path; the JWT itself never lands on disk. The settings are stored in config/app.toml under the [license] section.


What's next