Files
worldmonitor/docs/cors.mdx
Elie Habib 09a582e089 fix(docs): correct numerical inaccuracies, add missing features and variants (#1472)
* fix(docs): correct variant count from 4 to 5

Updated overview.mdx and architecture.mdx to reflect all 5 platform
variants (World Monitor, Tech Monitor, Happy Monitor, Finance Monitor,
Commodity Monitor). Previously only 2 were listed in the table and
the text said "four".

* fix(docs): correct all numerical inaccuracies across documentation

Updated counts verified against actual codebase:
- AI datacenters: 111 → 313
- Undersea cables: 55 → 86
- Map layers: 45 → 49
- News sources: 80+ → 344
- Service domains: 22 → 24
- CII countries: 20 → 24
- Military bases: 210/220+ → 226
- Strategic ports: 61/83 → 62
- Airports: 30/107 → 111
- Chokepoints: 6/8 → 9
- Signal entities: 100+/600+ → 66
- Variant count: four → five (added Commodity Monitor)

* docs(overview): add Happy, Finance, and Commodity Monitor sections

Added detailed documentation sections for the three previously
undocumented platform variants, including layers, panels, and
news categories for each.

* docs(features): document 13 previously undocumented features

Added: trade routes, FIRMS fire detection, webcam surveillance,
country brief, aviation intelligence panel, climate anomalies,
displacement tracking, Gulf economies, WTO trade policy, central
banks & BIS, market watchlist, NOTAM closure detection, and
offline ML capabilities.

* docs: standardize terminology, add cross-references, fix stale refs

Phase 4: Renamed "News Importance Scoring" to "Headline Scoring",
"Signal Correlation" to "Cross-Stream Correlation". Added cross-refs
between CII/convergence, CORS/API-key, maritime/finance chokepoints.
Deduplicated Population Exposure content. Clarified hotspot vs focal
point distinction.

Phase 5: Rewrote daily_stock_analysis as historical context. Added
legacy note for api/*.js files. Added OREF 24h rolling history boost
and GPS jamming classification thresholds to algorithms.mdx. Fixed
orbital-surveillance tier table contradictions.

Phase 6: Fixed orphaned markdown separator in orbital-surveillance.

* fix(docs): catch remaining stale numbers in secondary doc files

Fixed stale counts in data-sources.mdx, strategic-risk.mdx,
documentation.mdx, ai-intelligence.mdx, PRESS_KIT.md, and
roadmap-pro.md that were missed in the initial pass.

* fix(docs): address review findings from fresh-eyes pass

- desktop-app.mdx: "four variants" → "five", "22 services" → "24"
- infrastructure-cascade.mdx: chokepoints 8 → 9, node total 279 → 350
- data-sources.mdx: chokepoints 8 → 9
- overview.mdx: remove duplicated intro sentence
- getting-started.mdx: fix stale file tree comments (AI clusters, airports, entities)
2026-03-12 07:48:47 +04:00

92 lines
3.6 KiB
Plaintext

---
title: "CORS"
description: "How cross-origin request protection works and what to do when adding new API endpoints."
---
---
## Overview
Every API response must include CORS headers so browsers allow the frontend to read it. Two parallel implementations exist — one for standalone edge functions, one for the sebuf gateway — but they share the same origin allowlist and logic.
| File | Used by | Methods |
| --- | --- | --- |
| `api/_cors.js` | Standalone edge functions (`api/*.js`) | `GET, OPTIONS` (configurable) |
| `server/cors.ts` | Sebuf gateway (`api/[domain]/v1/[rpc].ts`) | `GET, POST, OPTIONS` |
## Allowed Origins
Both files use the same regex patterns:
| Pattern | Matches |
| --- | --- |
| `(*.)?worldmonitor.app` | Production + subdomains (`tech.`, `finance.`, etc.) |
| `worldmonitor-*-elie-*.vercel.app` | Vercel preview deploys |
| `localhost:*` / `127.0.0.1:*` | Local development |
| `tauri.localhost:*` / `*.tauri.localhost:*` | Desktop app (Tauri v2) |
| `tauri://localhost` / `asset://localhost` | Desktop app (Tauri v2 asset protocol) |
Requests from any other origin receive a 403 response. Requests with **no** `Origin` header (server-to-server, curl) are allowed through — the `isDisallowedOrigin` check only blocks when an origin is present and not on the allowlist.
## Adding CORS to a New Edge Function
Every standalone edge function in `api/` must handle CORS manually. Follow this pattern:
```js
import { getCorsHeaders, isDisallowedOrigin } from './_cors.js';
export default async function handler(req) {
const cors = getCorsHeaders(req);
// 1. Block disallowed origins
if (isDisallowedOrigin(req)) {
return new Response(JSON.stringify({ error: 'Forbidden' }), {
status: 403,
headers: { 'Content-Type': 'application/json', ...cors },
});
}
// 2. Handle preflight
if (req.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: cors });
}
// 3. Spread cors into every response
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json', ...cors },
});
}
```
Key rules:
1. **Every response** must include `...cors` in its headers — including errors, rate-limit 429s, and 500s.
2. **Preflight** (`OPTIONS`) must return `204` with CORS headers and no body.
3. **`getCorsHeaders(req, methods)`** — pass a custom methods string if the endpoint supports more than `GET, OPTIONS` (e.g., `'POST, OPTIONS'`).
## Sebuf Gateway (RPC Endpoints)
RPC endpoints defined in `.proto` files do **not** need manual CORS handling. The gateway (`server/gateway.ts`) calls `getCorsHeaders()` and `isDisallowedOrigin()` from `server/cors.ts` automatically for every request. CORS headers are injected into all responses including error boundaries.
## Adding a New Allowed Origin
To allow a new origin:
1. Add a regex pattern to `ALLOWED_ORIGIN_PATTERNS` in **both** `api/_cors.js` and `server/cors.ts`.
2. Update the test in `api/_cors.test.mjs`.
3. If the origin is a new production subdomain, also add it to the Cloudflare R2 CORS rules (see MEMORY.md notes on R2 CORS in the repo root).
## Allowed Headers
Both implementations allow these request headers:
- `Content-Type`
- `Authorization`
- `X-WorldMonitor-Key` (API key for desktop/third-party access). See [API Key Gating](/api-key-deployment) for key management details.
To allow additional headers, update `Access-Control-Allow-Headers` in both files.
## Railway Relay CORS
The Railway relay (`scripts/ais-relay.cjs`) has its own CORS handling with the `ALLOW_VERCEL_PREVIEW_ORIGINS` env var. See [RELAY_PARAMETERS.md](/relay-parameters) for details.