Simpl-Resultat/src/main.tsx
le king fu fd7e053239
All checks were successful
PR Check / rust (pull_request) Successful in 22m38s
PR Check / frontend (pull_request) Successful in 2m34s
feat(gating): license provider + entitlements matrix + useEntitlement (#297)
Socle for tier-based feature gating (UI-only soft-paywall).

- LicenseContext: machine-level provider (createContext<T|null>, useReducer,
  throwing consumer hook), mounted above ProfileProvider in main.tsx so a
  profile switch (BrowserRouter key remount) does not reload the license.
  Loads edition + info once; exposes { status, edition, features, info, error,
  refresh, submitKey }. Boot-error recovery (CWE-703): neutral state + capped
  exponential-backoff retry, never the upsell.
- shared/entitlements.ts: FeatureKey (kebab-case), ENTITLEMENTS matrix, pure
  isEntitled() fail-closed in Free (CWE-863) — the features[] override is
  ignored before edition==="free" is checked.
- useEntitlement(f): { allowed, ready } (ready = status==="ready"), synchronous.
- useIsPremium + its test migrated onto the context (drops the per-call double
  invoke); LicenseCard consumes the context. useLicense.ts removed (fully
  replaced, no remaining consumers).
- services/entitlements.test.ts: matrix, features[] override, override ignored
  in Free, unknown-feature deny-all.

Resolves #297
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 21:05:10 -04:00

23 lines
685 B
TypeScript

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { LicenseProvider } from "./contexts/LicenseContext";
import { ProfileProvider } from "./contexts/ProfileContext";
import ErrorBoundary from "./components/shared/ErrorBoundary";
import { initLogCapture } from "./services/logService";
import "./i18n/config";
import "./styles.css";
initLogCapture();
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<LicenseProvider>
<ProfileProvider>
<ErrorBoundary>
<App />
</ErrorBoundary>
</ProfileProvider>
</LicenseProvider>
</React.StrictMode>,
);