Commit graph

3 commits

Author SHA1 Message Date
le king fu
57a0fbc2f7 feat(upsell): activate "Get Base", honest Premium note, purchase path in Free, Account card text
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m42s
- upsellCtaFor(tier) decides what a locked screen offers: Base is
  purchasable, Premium stays disabled with "Premium isn't sold online
  yet". Pure and tested on the whole entitlements matrix.
- Shared CTAs, one component per file: PurchaseButton ("Get Base") and
  DownloadLatestButton open the localized product page (purchaseUrl) and
  need no router; HaveKeyButton renders only inside BrowserRouter.
- UpsellGate uses them; the purchase link never calls onNavigate, so
  modal hosts stay open. ProfileFormModal reuses UpsellGate instead of
  its compact panel, keeps its Cancel button, and closes after "I
  already have a key" (onNavigate={onClose}).
- In Free, the Updates card offers Get Base, I already have a key and
  Download the latest version; the error page (outside the router)
  offers Get Base and the download link. No update check, no network
  call.
- i18n FR/EN: Account card text, Premium note, Updates notEntitled text,
  download label, editions guide step and tip; the "coming soon" note
  key is gone. Tests pin the upsell key set and the decided texts.
- Docs: ADR 0017 amendment, architecture (UpsellGate row, shared CTAs,
  upsellCtaFor, multi-profile row, counts), user guide section 12;
  CHANGELOG FR/EN.

Proven red: Premium made purchasable 2, balance sold as Base in the
matrix 4, the old note key back in a locale 1, Account text altered 1,
download label altered 1.

Fixes #346

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 15:50:45 -04:00
le king fu
6d67ab8935 feat: gate auto-updates behind license entitlement (#48)
All checks were successful
PR Check / rust (push) Successful in 16m6s
PR Check / frontend (push) Successful in 2m15s
Both code paths that touch the updater now consult `check_entitlement`
from the Rust entitlements module before calling `check()`:

- `useUpdater.ts` adds a `notEntitled` status; on Free, the check
  short-circuits and the Settings page displays an upgrade hint instead
  of fetching update metadata.
- `ErrorPage.tsx` (recovery screen) does the same so the error path
  matches the main path; users on Free no longer see network errors when
  the updater would have run.

The gate name (`auto-update`) is the same string consumed by
`commands/entitlements.rs::FEATURE_TIERS`, so changing which tier
unlocks updates is a one-line edit in that file.

Bilingual i18n keys for the new messages are added to both `fr.json`
and `en.json`. CHANGELOG entries in both languages.
2026-04-09 15:52:59 -04:00
le king fu
849945f339 Add error boundary, error page, and startup timeout
Prevent infinite spinner when DB connection fails at startup by adding
a 10s timeout on connectActiveProfile(). Add ErrorBoundary to catch
React crashes and ErrorPage with refresh, update check, and contact links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:01:39 -05:00