Simpl-Resultat/src-tauri/src/commands
le king fu e24c30fe6a feat(license): online revocation check — a revoked key falls back to Free (#365)
A refunded license was revoked on the server but kept working in the app:
the edition is resolved offline from the key alone, and the flag added by
#347 lasted the session only and never touched the edition.

Rust
- license.check, next to the key, holds what the license server last said
  about it: {key_sha256, attempted_at, revoked}. Never the key itself. A
  missing, unreadable or invalid file, or a state about another key, reads
  as "no state": not revoked, check due.
- entitlements_from_dir resolves a revoked key to ("free", []), which also
  locks auto-update. read_license and store_license report the state.
- check_license_revocation: POST /v1/licenses/verify with the product and
  the key only. Nothing is sent without a stored key that validates, nor
  within 24 h of the last attempt, which is written before the request.
  Fail-open: only "valid" lifts the state, only "revoked" sets it.
- Activation, machine list and deactivation record a license_revoked answer
  under the key they sent.
- fetch_price reads error.code of a 403 and names license_revoked instead of
  premium_required. It records nothing: the price route judges the license
  of the activation token, which the client cannot tie to the stored key,
  and 0.15.0 left the token of a previous key next to a new one (#367).

Front
- LicenseContext takes the revoked state from Rust (info.revoked); the
  session flag and markRevoked are gone. The check starts once per app
  start, writes its outcome to the in-app log, and reloads the context only
  when the state changed. A revoked key entered again stays Free.
- UpsellGate and the License card name the revocation.

Docs: ADR 0017 amendment (D13 replaced, the first unsolicited request and
its bounds), architecture, user guide, price contract annex, changelogs.

Refs #365

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:45:34 -04:00
..
account_cache.rs feat: HMAC-sign cached account info to close subscription tampering (#80) 2026-04-14 08:07:47 -04:00
auth_commands.rs feat: HMAC-sign cached account info to close subscription tampering (#80) 2026-04-14 08:07:47 -04:00
backup_commands.rs feat(categories): add restore backup banner and permanent restore action (#122) 2026-04-20 21:47:43 -04:00
balance_commands.rs feat(license): online revocation check — a revoked key falls back to Free (#365) 2026-10-02 14:45:34 -04:00
entitlements.rs fix(license): name key-entry errors, keep the edition off the activation token, flag revoked keys 2026-09-29 21:39:01 -04:00
export_import_commands.rs feat: add data export/import with optional AES-256-GCM encryption (#3) 2026-02-15 11:40:28 +00:00
feedback_commands.rs feat: feedback hub widget in Settings Logs card (#67) 2026-04-17 14:36:26 +00:00
fs_commands.rs feat: implement CSV import wizard with folder-based source detection 2026-02-08 03:38:46 +00:00
license_commands.rs feat(license): online revocation check — a revoked key falls back to Free (#365) 2026-10-02 14:45:34 -04:00
mod.rs feat(balance): add compute_account_return Tauri command 2026-04-25 16:23:14 -04:00
profile_commands.rs feat(prices): Rust Tauri command fetch_price + tests 2026-04-27 08:23:18 -04:00
return_calculator.rs fix(rust): wrap Modified Dietz formula doc block in text fence (S7) 2026-05-03 16:31:29 -04:00
token_store.rs feat: migrate OAuth tokens to OS keychain via token_store (#78) 2026-04-13 19:41:54 -04:00