Skip to main content

Licensing

Presponsieve is commercial software. Running it requires a valid license key, purchased separately.

How the gate works

The license is an Ed25519-signed token. LICENSE_PUBLIC_KEY holds the base64 public key that verifies it. Verification is a local signature check.

Both the token and the public key come from your dashboard at presponsieve.ai/dashboard. Sign in with the email your license was issued against, and you receive a single-use link valid for 15 minutes. The dashboard shows your plan, seats, expiry, status, the token with a copy button and a download, and the public key.

If the link never arrives, the most common cause is that the email on the license does not match the one you typed. The sign-in response is deliberately identical either way, so "no email" alone does not tell you which.

app:
config:
LICENSE_PUBLIC_KEY: "<base64 Ed25519 public key>"
LICENSE_ENFORCEMENT: "enforce"
LICENSE_VALIDATION_URL: ""

The token itself goes in the application secret as LICENSE_KEY, never in a values file.

Enforcement modes

ValueEffect
enforceDefault. An invalid or missing license blocks the engine
warnLogs and continues. For a migration window, not for production
disabledNo gate at all

Leaving LICENSE_PUBLIC_KEY blank also disables the gate. That is a development configuration.

The content key

The model assets baked into the image are encrypted. Decrypting them requires MODEL_CONTENT_KEY, and without it the engine has no model to run.

A license token can carry the content key itself. In that case leave MODEL_CONTENT_KEY blank and LICENSE_KEY alone unlocks the engine. That is the normal path.

Supply MODEL_CONTENT_KEY explicitly only if your license does not embed it, and note it must match the key the image was built with. A mismatched key produces a startup failure, not a degraded mode.

What the token carries

ClaimMeaning
subThe email the license was issued to
planInformational. Shown in /license/status
seatsInformational. The app does not count users against it; seat compliance is contractual
expExpiry. 0 means perpetual
featsCapabilities the license enables, for example chat, simulation
ckeyThe model content key, so MODEL_CONTENT_KEY can stay blank

A capability not in feats is unavailable regardless of configuration. If a feature you expect is missing, check the license before checking the chart.

Revocation checks

LICENSE_VALIDATION_URL is optional and blank by default. Set it to https://presponsieve.ai/validate and the app polls every LICENSE_REFRESH_INTERVAL_HOURS, default 12, to learn whether the license has been revoked.

Leaving it blank means validation is entirely local, with no egress at any point.

Be precise about what revocation does. A revoked license is learned on the next poll, up to 12 hours later, and only if the URL is configured. The revoked state lives in each pod's memory, so a restart clears it until the next poll. Only expiry survives a restart. Revocation is a commercial lever, not a kill switch, and your commercial terms should not assume otherwise.

Renewal

Collect the renewed token from presponsieve.ai/dashboard, update LICENSE_KEY in the application secret, and restart the pods. No new image, no chart change.

The restart is not optional. The license is read once at process start, so a running pod keeps its old expiry until it restarts, even if the secret has already changed underneath it.

kubectl annotate externalsecret presponsieve-secrets -n presponsieve \
force-sync="$(date +%s)" --overwrite

With Reloader installed, the rolling restart happens on its own. Without it:

kubectl rollout restart deploy/presponsieve -n presponsieve

Renew early. There is no penalty for installing a new license before the old one expires, and it turns a deadline into a chore.

Checking status

kubectl logs -n presponsieve deploy/presponsieve | grep -i license

A valid license logs at startup. An invalid one logs the specific failure: bad signature, malformed payload, or expired.