fix(preview): skip premium RPCs when main app runs inside /pro live-preview iframe#3235
Conversation
…w iframe pro-test/src/App.tsx embeds the full main app as a "live preview" via <iframe src="https://worldmonitor.app?alert=false" sandbox="...">. The iframe boots an anonymous main-app session, which fires premium RPCs (get-regional-snapshot, get-tariff-trends, list-comtrade-flows, and on country-click the fetchProSections batch) with no Clerk bearer available. Every call 401s, the circuit breakers catch and fall through to empty fallbacks (so the preview renders fine), but the 401s surface on the PARENT /pro page's DevTools console and Sentry because `sandbox` includes `allow-same-origin`. Net effect: /pro pricing page shows a flood of fake-looking errors that cost us a session of debugging to trace back to the iframe. PR #3233's premiumFetch swap didn't help here (there's simply no token to inject for an anonymous iframe). Introduce `src/utils/embedded-preview.ts::IS_EMBEDDED_PREVIEW`, a module-level boolean evaluated once at load from `window.top !== window` (with try/catch for cross-origin sandboxes), and short-circuit three init-time premium entry points when true: - RegionalIntelligenceBoard.loadCurrent → renderEmpty() - fetchTariffTrends → return emptyTariffs - fetchComtradeFlows → return emptyComtrade Plus one defensive gate in country-intel.fetchProSections for the case a user clicks a country inside the iframe preview. Each gate returns the exact same empty fallback the breaker would have produced after a 401, so visual behavior is unchanged — the preview iframe still shows the dashboard layout with empty premium panels, just without the network request and its console/Sentry trail. Live-tab /pro page should now see zero 401s from regional-snapshot / tariff-trends / comtrade-flows on load.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR introduces Confidence Score: 5/5Safe to merge; all findings are P2 style/documentation suggestions with no impact on correctness or data integrity. The implementation is clean and well-reasoned. The IIFE is evaluated once at module load, handles SSR (typeof window === 'undefined') and cross-origin throw cases, and all three short-circuit sites return the exact same empty-fallback values the circuit-breaker path would have produced. No P0/P1 issues found. No files require special attention; the P2 note on src/utils/embedded-preview.ts about the flag matching any iframe context is worth a follow-up comment but does not block merge. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[App boots inside iframe] --> B{IS_EMBEDDED_PREVIEW?}
B -- true: window.top !== window --> C[Short-circuit all 3 premium entry points]
B -- false: top-level or throws --> D[Normal premium fetch path]
C --> C1[RegionalIntelligenceBoard.loadCurrent → renderEmpty]
C --> C2[fetchTariffTrends → return emptyTariffs]
C --> C3[fetchComtradeFlows → return emptyComtrade]
C --> C4[fetchProSections → return early]
D --> D1[premiumFetch injects Clerk bearer]
D1 --> D2[RPC call succeeds for pro user]
D1 --> D3[Circuit-breaker catches 401 for anon user]
D3 --> D4[Returns empty fallback + logs to Sentry]
style C fill:#d4edda,stroke:#28a745
style D4 fill:#f8d7da,stroke:#dc3545
Reviews (1): Last reviewed commit: "fix(preview): skip premium RPCs when mai..." | Re-trigger Greptile |
| export const IS_EMBEDDED_PREVIEW: boolean = (() => { | ||
| if (typeof window === 'undefined') return false; | ||
| try { | ||
| return window.top !== null && window.top !== window; | ||
| } catch { | ||
| // Accessing window.top can throw in cross-origin iframe contexts. | ||
| // If we can't read it, we're almost certainly inside a sandboxed iframe. | ||
| return true; | ||
| } | ||
| })(); |
There was a problem hiding this comment.
Flag matches any iframe, not just the
/pro preview
window.top !== window is true for ANY same-origin iframe embedding of the app, not only the /pro marketing preview. A pro user who embeds worldmonitor.app in their own dashboard (or any other same-origin page that includes an iframe) would silently receive empty premium panels, with no indication of why.
The current scope is safe because the marketing page is the only known iframe consumer, but the name IS_EMBEDDED_PREVIEW implies a narrower context than what the flag actually detects. Consider tightening the detection to the specific preview entry point — for example, a dedicated query-param set by the /pro iframe (?preview=1) checked alongside window.top !== window, or a comment that explicitly documents this "any-iframe" behaviour as intentional policy.
| private fetchProSections(code: string): void { | ||
| // /pro live-preview iframe can't carry a Clerk session, so every pro | ||
| // section call would 401. Skip the RPCs entirely so the embedded | ||
| // preview doesn't spam the parent /pro console with expected failures. | ||
| if (IS_EMBEDDED_PREVIEW) return; |
There was a problem hiding this comment.
IS_EMBEDDED_PREVIEW guard is redundant here
fetchProSections is the only caller, and it is already guarded at the call site (line 465–467):
if (hasPremiumAccess(getAuthState())) {
this.fetchProSections(code);
}Inside the anonymous iframe, hasPremiumAccess() returns false, so fetchProSections is never reached in the first place. The inner guard provides no additional protection today. The PR description calls it "defensive", which is reasonable, but a comment explaining why both guards exist would prevent future readers from removing one thinking it is dead code.
Reviewer flagged that the first iteration's `window.top !== window`
check was too broad. The repo explicitly markets "Embeddable iframe
panels" as an Enterprise feature
(pro-test/src/locales/en.json: whiteLabelDesc), so legitimate
customer embeds must keep firing premium RPCs normally. Only the /pro
marketing preview — which is known-anonymous and generates expected
401 noise — should short-circuit.
Fix: replace the blanket iframe check with a unique marker that only
/pro's preview iframe carries.
- pro-test/src/App.tsx: iframe src switched from
`?alert=false` (dead param, unused in main app) to
`?embed=pro-preview`. Rebuilt public/pro/ to ship the change.
- src/utils/embedded-preview.ts: two-gate check now. Gate 1 still
requires `window.top !== window` so the marker leaking into a
top-level URL doesn't disable premium RPCs for the top-level app.
Gate 2 requires `?embed=pro-preview` in location.search so only
the known embedder matches. Enterprise white-label embeds without
this marker behave exactly like a top-level visit.
Same three premium fetchers + the one country-intel path still gate
on IS_EMBEDDED_PREVIEW; the semantic change is purely in how the
flag is computed.
Per PR #3229 / #3228 lesson, the pro-test rebuild ships in the same
PR as the source change — public/pro/assets/index-*.js and index.html
reflect the new iframe src.
|
Valid — the blanket `window.top !== window` check would have silently broken legitimate Enterprise white-label embeds (`pro-test/src/locales/en.json` `whiteLabelDesc`: "Embeddable iframe panels"). Fixed in `f202b90e7` with a unique embedder marker: 1. Iframe carries a unique query param```diff <iframe - src="https://worldmonitor.app?alert=false" + src="https://worldmonitor.app?embed=pro-preview" \`\`\``?alert=false` was a dead param (grep confirmed no consumer in main app). Replaced with `?embed=pro-preview` as an explicit marker specific to /pro's preview section. 2. Helper requires both frame context AND marker```ts // Gate 2: must carry the unique embedder marker. Enterprise Behavior matrix
The carve-out is now scoped to the single known embedder. Any future embedding surface we add would need to opt-in by appending `?embed=pro-preview` to its iframe src — which is the correct default direction since the flag only suppresses RPCs we KNOW will 401. Also rebuilt `public/pro/` with the new iframe src per PR #3229's bundle-freshness rule (`public/pro/assets/clerk-PNSFEZs8.js` = v5 Clerk, `index-DU27HBZM.js` = new app bundle). |
Problem
`pro-test/src/App.tsx` embeds the full main app as a "live preview" section:
```tsx
<iframe src="https://worldmonitor.app?alert=false" sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox" ... /> \`\`\`The iframe boots a fresh anonymous session of the main app, which fires premium RPCs at init:
Every call 401s because an anonymous iframe has no Clerk bearer to inject. The circuit breakers catch the failures and fall through to empty fallbacks, so the preview still renders — but because `sandbox` includes `allow-same-origin`, the 401s surface on the parent /pro page's DevTools console and Sentry, making the pricing page look broken.
Confirmed via Request initiator chain on the failing request:
```
https://www.worldmonitor.app/pro
└── https://worldmonitor.app/?alert=false
└── https://www.worldmonitor.app/?alert=false
└── sentry-CRhtdLad.js
└── /api/intelligence/v1/get-regional-snapshot?region_id=mena 401
```
PR #3233's `premiumFetch` swap doesn't help this case — no token exists to inject.
Fix
New module `src/utils/embedded-preview.ts` exports `IS_EMBEDDED_PREVIEW` — a boolean evaluated once at load time from `window.top !== window` (with try/catch for cross-origin sandbox quirks).
Three init-time premium entry points short-circuit when true, returning the exact same empty fallback the breaker would have reached after a 401:
Visual behavior unchanged — the preview iframe still shows the dashboard layout with empty premium panels, just without the network request and its console/Sentry trail.
Non-fix considered
Keeping the iframe's static fallback image (`dashboardFallback`) and removing the iframe entirely was the simpler option, but the user wanted the interactive preview preserved. This patch is the targeted console-quieting alternative.
Test plan
Follow-up
None immediately, but worth filing a tracking issue for the broader "paying-user 401 silence" gap that this + PRs #3233 together highlight: `premiumFetch` filters 5xx only, so a real misconfiguration that causes 401 for a pro user remains invisible to Sentry. Would need a premium-path-specific 401 hook that respects `IS_EMBEDDED_PREVIEW` so iframe noise stays out.