Offline leases
A lease is a short signed document Keylight hands the SDK at every successful activate or validate call. The app keeps it in the Keychain and re-verifies it on every launch - no network required.
This is what makes Keylight offline-first: a customer can board a plane, launch your app at 30,000 feet, and stay licensed.
What’s in a lease
Section titled “What’s in a lease”{ "kid": "primary", "licenseKeyHash": "4e7a...", "instanceId": "5f7e7b9a-...", "issuedAt": 1713546000, "expiresAt": 1714150800, "status": "active", "signature": "MEQCIB..."}Bound to:
kid- which of your app’s Ed25519 keys signed it.licenseKeyHash- SHA-256 of the normalized license key. The SDK rejects leases that don’t match the stored license.instanceId- the specific activation slot. Leases from other devices don’t verify here.expiresAt- 7 days afterissuedAt. After that, the SDK must refresh.
Full wire format and signing rules: Ed25519 leases.
How long a user can stay offline
Section titled “How long a user can stay offline”Two limits apply, whichever fires first:
- Lease lifetime: 7 days from the moment Keylight signs. After that, the SDK must refresh.
maxOfflineDays: 15 days by default since the last successful onlineactivateorvalidate. The SDK recordslastValidatedOnlinein the Keychain on every successful network call and rejects cached leases past this window — even if the lease itself hasn’t expired. Tune it onKeylightConfigurationif your app needs a stricter or looser cap.
The SDK refreshes eagerly inside the last 24 hours of the lease (see License lifecycle), so normal users re-sign well before either limit. A user who activates and then goes fully offline gets at minimum 7 days from lease issuance, and at most 15 days from the last online check.
If the lease expires (or the offline cap is hit) while offline:
- The app flips to
.expiredon next launch. - It stays there until the next successful
/validaterefresh, which will either restore.licensedor confirm the expiry.
maxOfflineDays is cleared from the Keychain on deactivate, so a re-activated install starts fresh.
What the SDK checks before trusting a lease
Section titled “What the SDK checks before trusting a lease”On every launch:
- Signature. Ed25519-verified against the
kid-indexed public key embedded in the app build. - Unknown kid → reject. If the lease’s
kidisn’t in the app’s trusted-keys map, the lease is dropped. This is how key rotation and compromise-response work. - License-key hash match. The lease’s
licenseKeyHashmust equal SHA-256 of the currently-stored key. - Instance ID match. The lease’s
instanceIdmust match the instance ID the SDK is using for this device. - Clock manipulation check. If the system clock has moved backward by more than 1 hour since
lastSeen, the lease is treated as invalid. Details in Ed25519 leases. - Expiry.
expiresAtcompared againstnow.
Any failed check → the SDK falls back to a network refresh. If that also fails, state goes .invalid.
Why 7 days
Section titled “Why 7 days”7 days is a deliberate balance:
- Short enough that a revoked license stops working within a week everywhere, even for users who haven’t refreshed.
- Long enough that intermittent connectivity (a bad hotel wifi week, a flight, a server outage) doesn’t interrupt legitimate paying users.
The lease TTL is fixed platform-wide - you can’t tune it per account.
Why no remote revocation
Section titled “Why no remote revocation”Keylight deliberately has no remote revocation of leases already in the field. Revoking a license records the revocation server-side and blocks future activations - but an existing lease continues to verify until it expires.
This is a design tradeoff: remote revocation would break offline verification. The 7-day lease TTL is the revocation window.
If you need to kill a compromised key immediately and the leased instance is still using it, you can:
- Revoke the license in the dashboard - new activations blocked, next refresh returns
invalid. - Ask the user to launch the app while online; the next validate call will deliver the revocation.
- For mass compromise (signing key leak), rotate the signing key and ship a new app build that removes the old
kid. Details in Key rotation.
Related
Section titled “Related”- License lifecycle - how lease state feeds into app state.
- Ed25519 leases - cryptographic details and rotation.
- Threat model - what Keylight does and doesn’t defend against.