File size: 3,524 Bytes
9d2d895
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * Premium RPC paths that require either an API key or a Pro session.
 *
 * Single source of truth consumed by both the server gateway (auth enforcement)
 * and the web client runtime (token injection).
 */
export const PREMIUM_RPC_PATHS = new Set<string>([
  '/api/market/v1/analyze-stock',
  '/api/market/v1/get-stock-analysis-history',
  '/api/market/v1/backtest-stock',
  '/api/market/v1/list-stored-stock-backtests',
  // /api/intelligence/v1/classify-event: LLM-backed classifier. Keep in the
  // premium path set so browser Pro callers attach the Clerk Bearer and
  // anonymous wms_ sessions cannot mint cache-miss LLM spend.
  '/api/intelligence/v1/classify-event',
  '/api/intelligence/v1/deduct-situation',
  // Browser calls must attach Clerk auth and bypass wm-session recovery:
  // anonymous 401s here are expected Pro denials, not dead session cookies.
  '/api/intelligence/v1/get-country-intel-brief',
  '/api/intelligence/v1/list-market-implications',
  '/api/intelligence/v1/get-regional-snapshot',
  '/api/intelligence/v1/get-regime-history',
  '/api/intelligence/v1/get-regional-brief',
  // Historical intelligence memory (#5694). Read-only over the Convex history
  // store; the two semantic routes also spend one embeddings call per cache
  // miss, which is why they carry fail-closed rate policies as well.
  '/api/intelligence/v1/search-intel-history',
  '/api/intelligence/v1/get-intel-timeline',
  '/api/intelligence/v1/get-similar-events',
  '/api/resilience/v1/get-resilience-score',
  '/api/resilience/v1/get-resilience-ranking',
  '/api/supply-chain/v1/get-country-chokepoint-index',
  '/api/supply-chain/v1/get-bypass-options',
  '/api/supply-chain/v1/get-country-cost-shock',
  '/api/supply-chain/v1/get-route-explorer-lane',
  '/api/supply-chain/v1/get-route-impact',
  '/api/supply-chain/v1/get-country-products',
  '/api/supply-chain/v1/get-multi-sector-cost-shock',
  '/api/supply-chain/v1/get-sector-dependency',
  '/api/economic/v1/get-national-debt',
  // Global procurement is a Pro product surface. Keep this in the shared
  // registry so premiumFetch attaches the Clerk bearer and the gateway enforces
  // the same route as the entitlement map.
  '/api/economic/v1/list-global-tenders',
  '/api/sanctions/v1/list-sanctions-pressure',
  '/api/trade/v1/list-comtrade-flows',
  '/api/trade/v1/get-tariff-trends',
  '/api/scenario/v1/run-scenario',
  '/api/scenario/v1/get-scenario-status',
  // #3734: PRO-gated mutation that enqueues a simulation task. Companion
  // /get-simulation-outcome remains public (existing convention).
  '/api/forecast/v1/trigger-simulation',
  '/api/v2/shipping/route-intelligence',
  '/api/v2/shipping/webhooks',
  // /api/mcp-proxy: Pro-gated outbound MCP proxy (PR #3768, issue #3723).
  // Path-gated here so premiumFetch attaches the Clerk Bearer for normal
  // web Pro users; the server gate in api/mcp-proxy.ts uses isCallerPremium
  // which validates enterprise key, wm_ user key, or Bearer JWT.
  '/api/mcp-proxy',
  // /api/chat-analyst: Pro-gated streaming SSE endpoint for WM Analyst panel.
  // ChatAnalystPanel.send() calls premiumFetch('/api/chat-analyst', ...) and
  // the server uses isCallerPremium; without this entry premiumFetch never
  // attaches the Clerk Bearer for browser Pro users → every send returned
  // 403 "Pro subscription required" despite a valid subscription. Symptom
  // stayed hidden until PR #3797 fixed the unlock-wipe so users could
  // actually type and click Send.
  '/api/chat-analyst',
]);