feat(entitlement): Ultimate entitlements & version-lock subscription (geekfun#56) - #152
Merged
Merged
Conversation
…(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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Client-side implementation of the Ultimate entitlement contract (geekfun#56). The server computes two fields —
ultimateExpiresAtandversionLockHorizon— and the client consumes them; nothing entitlement-related is decided client-side.Changes
Rust backend
entitlementmodule: persisted cache, offline tolerance, failure degradation, 5-minute refresh throttle, and theapp.releaseDate <= versionLockHorizonversion-lock unlock check.device_activation/device_identitymodules and a keyring-backedsessionlease (Windows Credential Manager / macOS Keychain / Linux Secret Service).ENTITLEMENT_REQUIREDfor: 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).Tests
tests/common/entitlement.test.ts,tests/store/deviceStore.test.ts— full suite: 531 passing.Test plan
npm test/npm run lint:checkgreencargo check/cargo clippygreen (CI)