Skip to content

feat(entitlement): Ultimate entitlements & version-lock subscription (geekfun#56) - #152

Merged
Blankll merged 3 commits into
masterfrom
feat/entitlement-version-lock
Sep 16, 2026
Merged

Blankll merged 3 commits into
masterfrom
feat/entitlement-version-lock

Conversation

@Blankll

@Blankll Blankll commented Sep 15, 2026

Copy link
Copy Markdown
Member

Summary

Client-side implementation of the Ultimate entitlement contract (geekfun#56). The server computes two fields — ultimateExpiresAt and versionLockHorizon — and the client consumes them; nothing entitlement-related is decided client-side.

Changes

Rust backend

  • New entitlement module: persisted cache, offline tolerance, failure degradation, 5-minute refresh throttle, and the app.releaseDate <= versionLockHorizon version-lock unlock check.
  • New device_activation / device_identity modules and a keyring-backed session lease (Windows Credential Manager / macOS Keychain / Linux Secret Service).
  • Command gates return ENTITLEMENT_REQUIRED for: AI (agent loop/step, compaction, LLM validation), the whole Transfer module, SSH tunnel establishment, and the MCP bridge (config/policy save + auto-start).

Frontend

  • entitlementStore / deviceStore + Geekfun login entry (authService).
  • Paid-feature gates with upgrade guidance on Data Studio, Transfer, AI assistant sidebar, ER diagram actions, AI/MCP settings, and the SSH tunnel option in the connection form.
  • New Account & Plan settings tab showing the version-lock state with login/logout; logout clears the local entitlement cache so entitlements never outlive the account session.

Tests

  • tests/common/entitlement.test.ts, tests/store/deviceStore.test.ts — full suite: 531 passing.

Test plan

  • npm test / npm run lint:check green
  • cargo check / cargo clippy green (CI)
  • Manual: login → entitlement refresh → gated feature unlock; logout → cache cleared → gates re-engage

…(geekfun#56)

Client-side implementation of the Ultimate entitlement contract:

- Rust: new entitlement module (persisted cache, offline tolerance,
  failure degradation, 5-min refresh throttle, release-date vs
  versionLockHorizon unlock check), device activation/identity,
  and keyring-backed session lease. Command gates return
  ENTITLEMENT_REQUIRED for AI, Transfer, SSH tunnels and MCP bridge.
- Frontend: entitlement/device stores, Geekfun login, upgrade guidance
  on gated features, Account & Plan settings tab; logout clears the
  local entitlement cache.
- Tests: entitlement contract and deviceStore suites (531 passing).
…nux build

cfg!() is a runtime boolean — both branches must compile — so calling
the Windows-only system_manufacturer() inside the any(linux, windows)
detect_virtual() failed name resolution on Linux (E0425). Split into
per-OS functions sharing a detect_virtual_from helper, matching the
file's existing per-platform style.

Verified via cross-target cargo check for x86_64-unknown-linux-gnu and
x86_64-pc-windows-msvc (device_identity.rs in an isolated crate), plus
host check/test/clippy/fmt.
… review findings

Store the device-bound refresh lease in the persisted account session
(localStorage) instead of a Rust-side keyring/file shadow store, and
resolve every issue from the PR review:

- drop keyring: v3 requires per-platform feature flags, so Entry::new()
  silently failed everywhere and every login degraded to the plaintext
  file fallback; the lease now lives with the rest of the session state
- session.rs keeps only the rotation protocol; rotations serialize
  through a tokio::sync::Mutex (single-use lease presented twice reads
  as a leak and revokes the device), and deliberate rejections surface
  the structured SESSION_REJECTED error so the frontend drops dead
  leases while transient failures keep them
- wire logout for real: the Account & Plan tab gains a logout button
  clearing the entitlement cache, the account session and device state
- gate SSH tunnels before any transport is established, not after
- stamp APP_RELEASE_DATE at build time in the release workflow
  (option_env fallback covers local builds) so a forgotten manual bump
  cannot fail a release open
- session-refreshed broadcasts both tokens; compute_entitlement returns
  a pure decision (cached/last_error belong to the view); consolidate
  the duplicated console base URLs and reqwest clients in
  common::console; test activation_body directly
@Blankll
Blankll merged commit 093bea1 into master Sep 16, 2026
3 checks passed
@Blankll
Blankll deleted the feat/entitlement-version-lock branch September 16, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant