Operator guide for pairing the desktop Plugin store tab with services/license-server.
| Component | Role |
|---|---|
| Desktop app | Verifies Ed25519-signed tokens, stores nosuckshell.license.json, checks entitlements for gated plugins (e.g. NSS-Commander / file-workspace add-on → dev.nosuckshell.addon.file-workspace). |
services/license-server |
Holds the private signing seed; mints tokens via POST /admin/issue-license or Ko-fi POST /webhooks/kofi. |
| Ko-fi | Shop, memberships, donations; webhook hits your deployed license server. |
The app does not download plugin binaries from the store. Add-ons are built into the release; the store is a catalog + purchase link + token activation flow.
| Mode | Signing seed | Desktop trusts |
|---|---|---|
| Local dev | Documented 32-byte dev seed in services/license-server/README.md (public by design so contributors can reproduce tokens) |
Built-in dev public key when no prod key is set |
| Production | A unique 32-byte seed you generate and never commit | Your public key: set NOSUCKSHELL_LICENSE_PUBKEY_HEX at compile time for official releases (GitHub Actions secret NOSUCKSHELL_LICENSE_PUBKEY_HEX) or at runtime for custom installs — see docs/licensing.md and docs/releases.md |
Security note: The dev seed in the repository is intentionally shared so forks and CI can mint test tokens. Never use that seed or its keypair for real customer purchases. Customer tokens must be signed with your production seed only.
- Generate a production 32-byte Ed25519 seed (keep secret). Derive the public key and set:
- Server:
LICENSE_SIGNING_SEED_HEX(64 hex chars). - Desktop builds / installs:
NOSUCKSHELL_LICENSE_PUBKEY_HEX(64 hex chars) so the app trusts your key instead of the dev default (seedocs/licensing.md).
- Server:
- Set
ADMIN_SECRETand use it asAuthorization: Bearer …for admin endpoints. - Set
BIND_ADDR(e.g.0.0.0.0:8787behind a reverse proxy with TLS). - Run the binary from the
services/license-servercrate (see its README forcargo run/ container).
- In Ko-fi, create a webhook pointing to
https://<your-host>/webhooks/kofi. - Set
KOFI_VERIFICATION_TOKENon the server to the verification token Ko-fi shows (handshake). - Do not expose raw
licenseTokenin a public response in production; deliver tokens by email or DM (seedocs/licensing.mdprivacy section).
Use DEFAULT_LICENSE_ENTITLEMENTS for a single global entitlement on all paid events, or extend the server to map shop item / tier → entitlement list (product-specific tokens).
Issue a token with an exp field (Unix seconds):
curl -sS -X POST https://<host>/admin/issue-license \
-H "Authorization: Bearer <ADMIN_SECRET>" \
-H "Content-Type: application/json" \
-d '{
"licenseId": "trial-user-123",
"entitlements": ["dev.nosuckshell.addon.file-workspace"],
"exp": 1735689600
}'After exp, the desktop rejects the license until the user activates a new token.
Sellable rows and entitlement strings are defined in apps/desktop/src/features/plugin-store-catalog.ts. Update:
purchaseUrlper item (your Ko-fi shop or tier link).requiredEntitlements— must match both Rustrequired_entitlement()on the plugin and what the license server puts inLicensePayload.entitlements.
Buyer-facing scope for paid add-ons: terms-of-sale.md.
Without an activated license, NSS-Commander (file panes add-on) is off until the license includes dev.nosuckshell.addon.file-workspace. With the dev license server from services/license-server:
curl -sS -X POST http://127.0.0.1:8787/admin/issue-license \
-H "Authorization: Bearer dev-admin" \
-H "Content-Type: application/json" \
-d '{"entitlements":["dev.nosuckshell.addon.file-workspace"],"licenseId":"dev-local"}'Paste the returned token into Settings → Plugins (Activate).
GET /healthon the license server.- Desktop: Settings → Plugins shows license status, entitlements, and Expires when
expis set. - Issue a dev token with the same pubkey the app uses, paste into License token → Activate.