# Codebase Concerns

**Analysis Date:** 2026-05-21

## Tech Debt

**Auto-generated `api.js` from TypeScript:**
- Issue: `src/api.js` carries a banner warning: "don't edit the .js version of this file directly. Edit the .ts version and then run `tsc` to generate the .js version." The `.ts` source file is not in the repo (no `*.ts` files exist under `src/`).
- Files: `src/api.js` (540 lines), `src/api.js:7-8`
- Impact: Single source of truth is missing from the repo. Edits to `api.js` will be lost or get out of sync with the upstream TypeScript. No way to safely modify auth/payment-critical code without finding the external `.ts`.
- Fix approach: Recover the `.ts` source, commit it alongside `.js`, and add a build step (or convert the project to compile `.ts` in CRA via `react-scripts`).

**`react-scripts` requires `SKIP_PREFLIGHT_CHECK`:**
- Issue: README documents `SKIP_PREFLIGHT_CHECK=true yarn start` as the start command, indicating CRA preflight is failing (typically a transitive-dependency version conflict, often Jest or Babel).
- Files: `README.md:24`, `package.json:42-47`
- Impact: Real dependency conflicts are silenced; preflight exists to catch these.
- Fix approach: Run without the flag, resolve the reported conflicts, remove the workaround from README.

**Most recent commit is titled "Fixme website build errors in Node 22":**
- Issue: Recent commit (`7f83139`) hints at unresolved Node 22 build issues.
- Files: repo HEAD
- Impact: Build may still be fragile on modern Node versions.
- Fix approach: Pin Node version (add `.nvmrc` / `engines` in `package.json`) and document supported Node.

**Two parallel app entry points:**
- Issue: `src/App.js` and `src/BeyondApp.js` both define top-level routers but `BeyondApp.js` imports `./src/api.js` (wrong relative path - assumes a directory layer that doesn't exist when this file is itself in `src/`).
- Files: `src/App.js`, `src/BeyondApp.js:7`
- Impact: `BeyondApp.js` will not compile if it is ever wired up. Appears to be dead/abandoned code.
- Fix approach: Delete `src/BeyondApp.js` or fix the import path and clarify its purpose.

**Extensive commented-out code in routing and component imports:**
- Issue: `src/App.js` has 30+ lines of commented imports/routes (lines 16-46, 269-313). `src/screens/Home/index.js` keeps 10+ commented imports. `src/components/Header/index.js` keeps 80+ lines of commented nav data. `src/components/Footer/index.js` has commented social/footer sections.
- Files: `src/App.js:16-46`, `src/App.js:269-313`, `src/screens/Home/index.js:12-20`, `src/components/Header/index.js:19-86`, `src/components/Footer/index.js:29-37`
- Impact: Obscures intent; reader cannot tell what is active vs. removed. Increases time to navigate code.
- Fix approach: Delete dead comments; rely on git history.

**`Redirect` component uses `useEffect` without dependency array:**
- Issue: `src/App.js:69-80` and `src/BeyondApp.js:15-21` both fire navigate on every render.
- Files: `src/App.js:69`, `src/BeyondApp.js:15`
- Impact: Potential render loops or unnecessary navigation; CRA build warnings.
- Fix approach: Add `[searchParams, navigate]` deps and guard the redirect to fire once.

**Lodash imported as `* as _` for trivial use cases:**
- Issue: Multiple files import the entire `lodash` namespace just to call `_.isNil`, `_.isEmpty`, or `_.range`.
- Files: `src/api.js:1`, `src/bigOrders/BigOrders.js:3`, `src/bigOrders/BigOrderSetIpdPage.js:3`, `src/bigOrders/BigOrderInfoPage.js:3` (unused), `src/components/BuilderIoPage/index.js:2`
- Impact: Larger bundle; replaceable with native JS (`val == null`, `!val`, etc.).
- Fix approach: Replace with native checks or use `lodash-es` per-function imports.

**`react-scripts 5.0.1` + React 17 stack:**
- Issue: Stack is on CRA 5 with React 17 (`package.json:22, 26, 34`). CRA is effectively unmaintained, and React 17 is two majors behind current.
- Files: `package.json`
- Impact: No path for newer React features; security and performance fixes will only come via fork/migration. Build pipeline depends on aging webpack 5 config baked into CRA.
- Fix approach: Plan a migration to Vite or Next.js; bump to React 18+.

**No TypeScript despite mixed-language hints:**
- Issue: Project has type-flavored class fields (e.g., `BigApiError { code; status; errors; }` in `api.js:29-32`) and a generator note for `.ts`, but no `tsconfig.json` and no `.ts`/`.tsx` files in `src/`.
- Impact: Lost type safety for the auth/api boundary - the single most error-prone area of the app.
- Fix approach: Adopt TypeScript and migrate `api.js` first.

**`use-dark-mode` partially implemented:**
- Issue: `public/index.html:90-131` runs a dark-mode bootstrap script, but `classNameDark` and `classNameLight` are both `'dark-mode'` (line 97-98), making the toggle a no-op.
- Files: `public/index.html:97-98`
- Impact: Light mode is unreachable from this code path.
- Fix approach: Either fix the class names or remove the bootstrap script entirely.

**`react-animate-on-scroll@2.1.5` is abandoned upstream:**
- Files: `package.json:23`
- Impact: Likely source of `react-scripts` preflight warnings.
- Fix approach: Replace with `framer-motion` or a maintained alternative.

## Known Bugs

**`BigApi.handleTokenLogin` is called but does not exist:**
- Symptoms: `src/screens/Api/ApiPages.js:78` calls `BigApi.handleTokenLogin(params.token)`, but `BigApi` (in `src/api.js`) only defines `loginWithToken` and `loginWithToken2`. The route `/token/login/:token` will throw `TypeError: BigApi.handleTokenLogin is not a function`.
- Files: `src/screens/Api/ApiPages.js:74-97`, `src/api.js:202`
- Trigger: Any user hitting `/token/login/:token` (token login v1).
- Workaround: Use `/token2/login/:token` (v2) instead; v1 is broken.

**Empty error-message setters in `TokenLogin` / `TokenLogin2`:**
- Symptoms: On login failure, no UI is shown - all `setErrorMsg` lines are commented out.
- Files: `src/screens/Api/ApiPages.js:83-88`, `src/screens/Api/ApiPages.js:115-120`
- Trigger: Any token-login failure.
- Impact: User sees indefinite spinner with no feedback.

**`renewAccessToken` throws raw `Error("NO NONCE FUCK YOU")`:**
- Symptoms: When a 401 returns `AccessTokenNeedsRenewal` but no `x-bigscreen-nonce` header, a profanity-laced error bubbles up. The catch block also dereferences `err.response.status` without guarding (so a network error with no `err.response` throws).
- Files: `src/api.js:358`, `src/api.js:348`
- Trigger: Backend returns 401 with missing nonce, or a network failure during token verify.
- Impact: Logged user-facing error and possible unhandled exception.
- Fix approach: Throw a `BigApiError` with a customer-safe message; guard `err.response` access.

**`fetchRdcUrl` runs every render in `App.js`:**
- Symptoms: `src/App.js:106-112` includes `fetchRdcUrl` inside a `useEffect` with empty deps `[]`, but the `useEffect`'s body re-defines the function on every call without the guard intended by `if(rdcUrl == '')` (the closure captures the initial empty `rdcUrl`).
- Files: `src/App.js:95-112`
- Impact: Works once due to `useEffect([])`, but the guard is misleading and the pattern breaks on any future change.

**`BigOrders` returns no element when `bigOrders` is empty and loading:**
- Symptoms: `src/bigOrders/BigOrders.js:206-210` returns "Nothing to see here!" even while data is still loading - the `loading` state is set but never consulted in render.
- Files: `src/bigOrders/BigOrders.js:69-211`
- Impact: Brief incorrect state shown before data arrives.

**`BigOrderSetIpdPage` returns `undefined` when not loading and `bigOrder` is null:**
- Symptoms: After `setBigOrder(null)` on error, the component falls off the bottom of `render` without an explicit return.
- Files: `src/bigOrders/BigOrderSetIpdPage.js:149-150`
- Impact: React render error (must return null/element).

**`bigOrders.map` keys missing:**
- Symptoms: `src/bigOrders/BigOrders.js:75` maps without supplying `key=`. React will warn and reconcile incorrectly on updates.
- Files: `src/bigOrders/BigOrders.js:75`, `src/bigOrders/BigOrderSetIpdPage.js:120`
- Impact: React warning; key reconciliation drift across renders.

**Pricing/IPD list buttons rendered without keys:**
- Symptoms: `src/bigOrders/BigOrderSetIpdPage.js:120-128` returns `<button>{ipd}mm</button>` from a `_.range(55,73).map(...)` without `key`.
- Files: `src/bigOrders/BigOrderSetIpdPage.js:120`
- Impact: React reconciliation bug.

**`EtClient` `useEffect` has no deps array:**
- Symptoms: `src/screens/Access/EtClient/index.js:13-27` runs on every render and calls `w.location.assign(url)`, causing an infinite navigation loop if React ever re-renders before navigation completes.
- Files: `src/screens/Access/EtClient/index.js:13`
- Impact: Possible navigation-loop bug.

**`Footer` `useEffect` setting interval has no deps array:**
- Symptoms: `src/components/Footer/index.js:135-139` sets a new `setInterval` every render. The cleanup will clear them, but only the previous interval - causing flicker and timer churn.
- Files: `src/components/Footer/index.js:135-139`
- Impact: Wasted timer work; the 10-second auth refresh restarts constantly.

**`fetchRegionCode` failure default mismatches success shape:**
- Symptoms: `BeyondBackend` uses the result to set locale, but on success returns `{region: "jp"|"en"}` and on error returns `{region: 'N/A'}`. The `BeyondBackend` code falls back to `'en'` (good), but the `BuilderIoPage.fetchRegionCode` exposed to Builder.io returns `{region: 'N/A'}` to consumers which may not handle that case.
- Files: `src/components/BuilderIoPage/index.js:81-88`, `src/components/BeyondBackend/index.js:21-34`
- Impact: Builder.io content using region may break for users with API errors.

**Empty-deps `useEffect` ignores prop changes:**
- Symptoms: `SocialBrowser` (`src/screens/SocialBrowser.js:12-44`) reads `params.activityId` but uses `[]` deps. A future route change won't restart the Hyperbeam session.
- Files: `src/screens/SocialBrowser.js:44`
- Impact: Stale browser session if route param changes without remount.

**`Math.floor(bigOrder.createdAt / 1000)` assumes ms timestamps:**
- Files: `src/bigOrders/BigOrderInfoPage.js:68`
- Impact: If API ever returns seconds-since-epoch, date will be wildly wrong (1970-era). No bounds check.

## Security Considerations

**API key shipped to the browser as `REACT_APP_API_KEY`:**
- Risk: Every CRA `REACT_APP_*` env var is inlined into the JS bundle and served publicly. The Bigscreen API key (`process.env.REACT_APP_API_KEY` - referenced 30+ times in `src/api.js` as `Bearer ${apiKey}`) is exposed to any visitor who views the bundle.
- Files: `src/api.js:73-76`, `src/config.js:4`, all `superagent.*` calls in `src/api.js`
- Current mitigation: None at the client. Server presumably enforces additional checks.
- Recommendations: Treat the key as a public identifier (rename / document it as such), or proxy auth calls through a backend that holds the secret.

**Stripe public keys hardcoded (intentional - public keys):**
- Files: `src/screens/Purchase/Payment/CardForm/index.js:11-12`
- Impact: Acceptable since `pk_live_*` and `pk_test_*` are designed to be public, but environment selection is based on `window.location.hostname` string matching, which can be fragile if a domain is renamed.
- Recommendations: Move to env-driven config to match the rest of the app.

**Auth tokens stored in non-HttpOnly cookies (or `localStorage`):**
- Risk: `src/api.js:101-163` writes `x-refresh-token` and `x-access-token` to cookies via `document.cookie` (no `HttpOnly`, no `Secure`, no `SameSite`). Any XSS will exfiltrate them.
- Files: `src/api.js:101-163`
- Current mitigation: None. The cookies are world-readable to JS.
- Recommendations: Move to HttpOnly Secure cookies set by the server; on the client, only rely on a session bit.

**`dangerouslySetInnerHTML` with module-level constant SVG:**
- Risk: `src/components/ValueProps/index.js:47` renders `x.icon` (a raw SVG string) via `dangerouslySetInnerHTML`. The data is a hardcoded constant in the same file, so currently not exploitable - but the pattern is dangerous if `items` is ever sourced externally.
- Files: `src/components/ValueProps/index.js:43-52`
- Current mitigation: Static module-level data.
- Recommendations: Use inline `<svg>` JSX or a sanitizer (`DOMPurify`) if data ever becomes dynamic.

**Mass injected third-party tracking scripts in `index.html`:**
- Risk: `public/index.html:6-44` embeds Google AdSense, Reddit Pixel, Twitter Pixel, and Meta Pixel inline. Each adds a third-party origin that can be hijacked by the vendor (or any DNS/CDN compromise) and execute arbitrary JS.
- Files: `public/index.html:6-44`
- Current mitigation: None (no CSP, no SRI on the inline pixels' bootstraps).
- Recommendations: Add a `Content-Security-Policy` header at the server/CDN; consider GTM gating; document which scripts are still required.

**Open-redirect surface in `/go?t=` redirect:**
- Risk: `Redirect` component (`src/App.js:64-83`) navigates to any URL passed via `?t=` query param without validation. Login flow uses it after success (`src/screens/Access/Login/index.js:28-29`).
- Files: `src/App.js:69-80`, `src/screens/Access/Login/index.js:21-30`
- Current mitigation: The `navigate(...)` call routes within React Router, so absolute external URLs become path components. However, a `t=//evil.com` could still confuse some browsers/URL parsers.
- Recommendations: Validate `t` matches an allow-list of internal path prefixes before navigating.

**Logging full API request/response bodies via `console.log`:**
- Risk: `src/api.js:47`, `src/api.js:85`, `src/bigOrders/BigOrders.js:23, 26, 39`, and many others log `res.body` and errors verbatim. If responses ever include PII (account email, IPD, IP from `/auth/whoami`), it leaks into browser dev console / shared screenshots / extensions.
- Files: 22 files with `console.*` calls (67 occurrences total)
- Current mitigation: None.
- Recommendations: Add a logger that strips PII in production builds; replace bare `console.log` with no-ops in prod.

**`bset://authenticate?t=<token>` deep-link without CSRF protection:**
- Risk: `src/screens/Access/EtClient/index.js:14-18` triggers a custom-protocol redirect with the eyetracking token directly in the URL. The same token is also displayed in plaintext on the page for copy/paste (`line 47`).
- Files: `src/screens/Access/EtClient/index.js`
- Current mitigation: User must already be authenticated to reach this page.
- Recommendations: Confirm tokens are single-use and short-lived; consider clearing the on-screen copy after first use.

**Stale comment references a removed massive-security-risk hack:**
- Risk: `src/api.js:246-255` retains a commented HACK block warning "THIS IS A MASSIVE SECURITY RISK. WIND THIS BACK ONCE WE SHIP A PROPER IOS AND ANDROID APP." The block also still calls `BigApi.setCookie("retry_token", ...)` at line 234 (uncommented).
- Files: `src/api.js:224-256`
- Impact: The `retry_token` cookie is still being set, which is referenced by `ScanStartPage` to construct a retry URL. Treat this as load-bearing until the v2 token flow is audited.
- Recommendations: Audit the v2 token flow end-to-end; remove the commented block once confirmed safe.

## Performance Bottlenecks

**Public/source image directories ~322MB total:**
- Problem: `src/images` is 121MB, `public/images` is 201MB. Includes a `src/images/flags/AI` directory shipping a `.ai` Illustrator source file and 227 PNG and 227 SVG flag images even though no screen currently maps them.
- Files: `src/images/flags/AI/*.ai`, `src/images/flags/PNG/` (227 files), `src/images/flags/SVG/` (227 files)
- Cause: Vendor assets committed in raw form; no image pipeline.
- Improvement path: Move large assets to a CDN/object store; delete `.ai` sources; subset flag assets to those actually used; convert PNGs to WebP/AVIF; configure CRA build to fail on >500KB images.

**`CardScroller` runs a 60fps `setTimeout` loop perpetually:**
- Problem: `src/components/CardScroller/index.js:115-165` schedules itself every 16ms forever, even when off-screen. Calls `_platform.style.left` writes plus `setState` per tick.
- Files: `src/components/CardScroller/index.js:115-165`
- Impact: Constant main-thread work, CPU drain on mobile.
- Improvement path: Use `requestAnimationFrame`, pause when not in viewport (`IntersectionObserver`), and avoid `setState` per frame for purely visual position.

**`scroll` and `resize` listeners without throttling:**
- Files: `src/components/CardScroller/index.js:122-123`, `src/screens/MovieLibrary/MovieSearch/index.js:92`
- Impact: Heavy work per scroll event.
- Improvement path: Throttle/debounce via `lodash.throttle` or `requestAnimationFrame`.

**Polling auth state every 10 seconds:**
- Problem: `src/components/Footer/index.js:135-139` sets a 10-second `setInterval` to recompute the login button label. With the missing deps array, intervals are re-created every render.
- Files: `src/components/Footer/index.js:135-139`
- Improvement path: React to the `account` prop directly (no interval needed).

**Bundle size: lodash + react-router + builder.io + stripe + hyperbeam loaded eagerly:**
- Problem: All these are imported at top of `App.js`. Builder.io and Hyperbeam alone are large.
- Improvement path: Code-split per route via `React.lazy` + `Suspense`.

**`window.scrollTo(0, 0)` on every render:**
- Files: `src/components/Page/index.js:9-12`, `src/components/BeyondBackend/index.js:10-12`
- Impact: Forces scroll reset on every component render (no deps array on the effect in `Page`).

## Fragile Areas

**`api.js` (auth, payment, session) is generated, undocumented, 540 lines:**
- Files: `src/api.js`
- Why fragile: Single source of truth lives outside the repo (TypeScript file referenced in line 7 comment), uses class static state for tokens, has at least one broken control path (`renewAccessToken` exception messages), and is touched by every component.
- Safe modification: Find and commit the `.ts` source first. Until then, treat `api.js` as immutable.
- Test coverage: Zero - no tests for any auth/payment path.

**Builder.io routing in `App.js`:**
- Files: `src/App.js:114-184`
- Why fragile: Routes are matched by chained regexes joined via `getComposedRegex`. Any new path that should be served by Builder.io must be added to the regex list (this is how `/enrollprivacy` was added in commit `37d2020`). Trivial to miss.
- Safe modification: When adding pages, update both `builderIoFilter` and any sub-filters; verify with curl after deploy.

**Stripe public key selection by hostname substring:**
- Files: `src/screens/Purchase/Payment/CardForm/index.js:13-17`
- Why fragile: `window.location.hostname === "www.bigscreenvr.com" || window.location.hostname.startsWith("main-")` is the production discriminator. Any new prod hostname (e.g., a new TLD or CDN edge) silently falls back to the test key, causing real customer payments to fail or run in test mode.
- Safe modification: Move to env-driven; add a runtime warning when test key is selected on what looks like a prod domain.

**`getComposedRegex` with route patterns:**
- Files: `src/App.js:114`, `src/components/BuilderIoPage/index.js:15`
- Why fragile: Order matters (first match wins), and overlapping patterns can shadow each other.

**`react-router-dom` v6 + `BrowserRouter` mounted twice:**
- Files: `src/index.js:15-17` (wraps `App` in Router); `src/BeyondApp.js:45` (also wraps in Router).
- Impact: If `BeyondApp` is ever rendered alongside `App`, nested routers cause undefined behavior. Currently `BeyondApp` is not imported from `App` or `index.js`, but the duplication is a trap.

**Token storage toggle constant `USE_COOKIES_FOR_TOKENS = true`:**
- Files: `src/api.js:100`
- Why fragile: A single boolean swaps cookie vs. localStorage code paths for all token operations. Flipping it changes security model silently.

**`createBrowserHistory` import in `Header`:**
- Files: `src/components/Header/index.js:4-16`
- Why fragile: Creates a separate history instance (`var history = createBrowserHistory();`) but it is unused. Indicates incomplete migration from React Router v5 to v6.

## Scaling Limits

**Single static React build:**
- Current capacity: CRA SPA. Serves the entire app to every visitor.
- Limit: No SSR/SSG. Pages routed through Builder.io (most marketing pages) make a network call to Builder.io's API on first paint. SEO/load suffers compared with Next.js-style SSG.
- Scaling path: Migrate to Next.js or Astro; prerender Builder.io content.

**Image asset budget:**
- Current capacity: 322MB of images checked into git.
- Limit: Git clones become slow. CDN bills scale with page-weight.
- Scaling path: Move large images to an object store; use git-lfs as an interim.

## Dependencies at Risk

**`react-scripts@5.0.1`:**
- Risk: CRA is effectively unmaintained; the project README still recommends `SKIP_PREFLIGHT_CHECK=true`.
- Impact: No security updates from CRA upstream; future React/Node bumps break the build.
- Migration plan: Vite + React, or Next.js.

**`react@17.0.1` + `react-dom@17`:**
- Risk: Two majors behind. React 17 is in maintenance mode.
- Impact: New libraries assume React 18+; no concurrent features, no automatic batching.
- Migration plan: Bump to React 18, audit `ReactDOM.render` usage in `src/index.js:13`.

**`react-animate-on-scroll@2.1.5`:**
- Risk: Abandoned upstream. Known peer-dep conflicts that are the likely cause of the CRA preflight skip.
- Migration plan: Replace with `framer-motion` or remove entirely if unused.

**`react-ga@3.3.0` (Universal Analytics):**
- Risk: `ReactGA.initialize('UA-154139246-1')` in `src/App.js:61` and `src/BeyondApp.js:9` - Google sunset Universal Analytics tracking IDs in July 2023. These calls now send to a property that no longer records data.
- Impact: Analytics are silently broken.
- Migration plan: Switch to GA4 with `react-ga4` or remove.

**`react-cookies@0.1.1`:**
- Risk: 0.x version with no recent releases; imported in `src/components/BeyondBackend/index.js:2` but the file uses neither read nor write through it - dead import.
- Migration plan: Remove if unused; otherwise pin and audit.

**`@npmcli/fs@^2.1.0` as a runtime dependency:**
- Risk: A Node-only package shipped to the browser. Will be tree-shaken / no-op'd, but indicates accidental misplacement (`package.json:8`).
- Migration plan: Move to `devDependencies` or remove.

**`@hyperbeam/web@0.0.37`:**
- Risk: 0.x SDK; pre-stable API.
- Files: `package.json:67`, `src/screens/SocialBrowser.js`
- Migration plan: Track upstream; pin precisely until 1.0.

**`history@^5.3.0`:**
- Risk: Imported but not used in `src/components/Header/index.js:4` (only `createBrowserHistory()` is called and stored in `var history`, then ignored).
- Migration plan: Remove the import.

**`dependenciesMeta.isolated-vm@4.6.0` override:**
- Risk: `package.json:72-76` disables native build for `isolated-vm`. The package itself is not in the dependency list - this is a leftover override.
- Migration plan: Remove if isolated-vm is no longer transitively required.

## Missing Critical Features

**No production logging/error reporting:**
- Problem: All errors funnel into `console.error`/`console.log`. No Sentry, Datadog, LogRocket, or equivalent.
- Blocks: Triaging real-user errors; SLAs; alerting on payment or auth failures.
- Files: search for `console.error` across `src/` (22 files).

**No analytics for SPA route changes:**
- Problem: `ReactGA.initialize` is called once in `App.js:61` but no `pageview` is sent on route change. UA is dead anyway (see above).
- Blocks: Marketing/funnel attribution.

**No CSP / security headers configured at the app layer:**
- Problem: Static CRA build has no headers; the deployment platform (not in this repo) must add them.
- Blocks: XSS hardening.

**No environment validation:**
- Problem: `src/config.js` reads four env vars; none are validated. If `REACT_APP_API_SERVER_URL` is missing, every request hits `undefined/auth/...`.
- Blocks: Safe deploys to new environments.

**No type definitions:**
- Problem: No TS, no PropTypes (`prop-types` is in `package.json:21` but unused per grep).
- Blocks: IDE assistance, refactor safety, especially around `BigApi` payload shapes.

**Builder.io routing has no fallback for unmatched pages:**
- Problem: Builder.io renders `<BuilderComponent model="non-shopify" />` regardless of whether the URL exists in Builder. A 404 from Builder shows empty content.
- Blocks: Proper 404 UX and SEO.

## Test Coverage Gaps

**Effectively zero test coverage:**
- What's not tested: Everything. The only test file is `src/App.test.js` which contains the default CRA boilerplate searching for "learn react" text that does not exist on the page - meaning the test will fail if run.
- Files: `src/App.test.js:1-9` (boilerplate CRA test), `src/setupTests.js` (only imports jest-dom)
- Risk: 
  - Auth/token renewal logic (`src/api.js` - 540 lines) has zero tests.
  - Payment flow (`src/screens/Purchase`, `src/screens/Purchase/Payment/CardForm`) has zero tests.
  - Big Beyond order flow (IPD selection, scan processing) has zero tests.
  - Builder.io route matching regexes (easy to break with a typo) have zero tests.
- Priority: **High** - auth and payment must have at least integration coverage.

**No E2E tests:**
- What's not tested: Login → purchase → scan flows.
- Risk: Manual QA only; regression escapes are likely.
- Priority: High - this is a commerce site.

**No CI test runs visible:**
- Files: No `.github/workflows`, no `.gitlab-ci.yml`, no `Jenkinsfile` in this repo.
- Risk: Even the broken boilerplate test never runs in CI.
- Priority: Medium - add CI to catch lint/build breakage.

---

*Concerns audit: 2026-05-21*
