Licensing
Elyra Sjá is commercial software (not open source). See the root
LICENSE.
Trial
A fresh install runs on a 3-day trial with full functionality. The first-run timestamp is recorded on first launch. A banner shows the days left. When the trial ends without a valid code, a lock screen requires activation.
The trial anchor is written to two places — the database and the Keychain —
and the earliest one found wins, so clearing either store does not restart the
trial. Licensing also reads time as max(now, highest clock value ever observed):
winding the clock back extends nothing and cannot revive an expired code. Winding
it forward works, and simply spends the trial faster.
Activating
Enter your code in Settings → License or on the lock screen. Buy or manage a license at https://elyracode.com/sja.
Where state lives
- License code → macOS Keychain (
com.elyra.sja/license_key). - First-run timestamp and the clock high-water mark → both the local SQLite
settingstable (keylicense) and the Keychain (license_first_run,license_last_seen).
If the Keychain refuses a write, the code is kept in the database rather than dropped, and the app shows a banner saying where it ended up. Losing an activation silently would be worse than storing it less privately.
When the license can't be checked
If the status check itself fails (a database error at startup, say), the app retries once and then stays unlocked, showing a banner that it is running unverified. This is deliberate: locking out a paying customer over a transient local fault is worse than one unverified session. The banner exists so the state is diagnosable rather than silent — an unverifiable license must not be indistinguishable from a valid one.
Key format (ed25519-signed)
Validation is offline and cryptographic. elyracode.com signs each code with
an ed25519 secret seed; the app embeds only the matching public key
(src/license.rs), so codes cannot be forged from the binary.
SJA-<base64url(payload_json)>.<base64url(signature)>
The signature covers the ASCII bytes of the base64url payload segment. The payload is JSON:
{
"v": 1,
"id": "lic_9f2c…",
"plan": "pro",
"email": "buyer@example.com",
"iat": 1782000000,
"exp": 1813536000
}
| Claim | Meaning |
|---|---|
v |
Payload version (currently 1; unknown versions fail closed) |
id |
Opaque license id, for support lookups |
plan |
Entitlement the code unlocks |
email |
Licensee |
iat |
Issued-at (unix seconds); more than 24 h in the future is rejected |
exp |
Expiry (unix seconds); 0 means perpetual (lifetime) |
A code is accepted when the signature verifies and the code is current
(exp == 0 || exp > now). Codes are case-sensitive — base64url — so never
upper-case them.
Rotating the key
Replace PUBLIC_KEY_B64 in src/license.rs and the seed on the server. Every
code signed with the old key stops validating on the next app release.
Security note
Because signing is asymmetric, the binary contains no secret: reverse
engineering it yields a verifier, not a keygen. The secret seed lives only on the
issuing server (SJA_LICENSE_SIGNING_SEED). Codes are self-contained —
activation needs no network call, and revocation is handled by expiry (exp)
rather than a callback.