Offline Grace Mode: Keeping Your App Working Without a Connection
Your customer's laptop goes into airplane mode, or their office firewall blocks outbound requests, or api.permitcore.dev itself has a bad five minutes. If your app hard-fails the moment it can't reach the license server, you'll get support tickets from people who paid you money and did nothing wrong. That's what offline grace mode is for.
How It Works
Every successful validate() or activate() call, PermitCore signs a small payload — license status, remaining activations, feature flags, expiry — with the tenant's own ECDSA P-256 private key, and hands it back alongside the normal response. The SDK caches that signed token locally. The next time the network is unreachable, the SDK checks the cached token's signature instead of failing outright.
This matters because a signed cache is fundamentally different from a plain {"isValid":true} file sitting on disk. Anyone can hand-edit a JSON file. Forging a token that verifies against PermitCore's public key requires the tenant's private key, which never leaves the server.
Setting the Grace Period
You control this per license, in the same form you used to generate the key:
21 days is a reasonable default — long enough to cover a vacation or a slow IT department, short enough that a permanently offline machine still eventually stops working.
Set it to 0 to disable offline mode entirely for a given license — useful if your product has a hard requirement to phone home (metered billing, for example).
What the SDK Does With It
try { var result = await client.ValidateAsync(key); CacheGraceToken(result.GraceToken); // signed, opaque to the app return result; } catch (HttpRequestException) { var cached = LoadCachedGraceToken(); if (cached is null || !VerifySignature(cached)) return ValidateResult.Fail("No valid offline cache. Reconnect to continue."); if (DateTime.UtcNow > cached.ValidUntil) return ValidateResult.Fail("Offline grace period expired."); return ValidateResult.Ok(cached, offline: true); }
This logic already ships inside all 6 official SDKs — you don't need to hand-roll signature verification yourself unless you're talking to the REST API directly.
What This Doesn't Protect Against
We'd rather tell you the honest limits than let you find out the hard way. A signed offline cache stops someone from editing the cached file to fabricate a valid result. It does not stop someone from winding their system clock backward to keep an already-issued token looking unexpired — the token's expiry check is only as trustworthy as the local clock it's compared against. It's availability protection for legitimate customers hitting real network problems, not a hardened anti-tamper system for a hostile user actively trying to defeat it.
If your threat model includes users deliberately trying to run past their offline window indefinitely, keep the grace period conservative and pair it with server-side signals (like a max devices-per-license cap) rather than relying on the offline check alone.
What's Next
Offline grace applies to both node-locked and floating licenses, but floating adds its own wrinkle — what happens to a checked-out seat when the checkout machine goes offline and never checks back in? That's the subject of the next post.