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.Allowed Origins
Both files use the same regex patterns:
Requests from any other origin receive a 403 response when the handler calls
isDisallowedOrigin(req). 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 inapi/ must handle CORS manually. Follow this pattern:
- Every response must include
...corsin its headers — including errors, rate-limit 429s, and 500s. - Preflight (
OPTIONS) must return204with CORS headers and no body. getCorsHeaders(req, methods)— pass a custom methods string if the endpoint supports more thanGET, 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:- Add a regex pattern to
ALLOWED_ORIGIN_PATTERNSin bothapi/_cors.jsandserver/cors.ts. - Update the test in
api/_cors.test.mjs. - 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-TypeAuthorizationX-WorldMonitor-Key(API key for desktop/third-party access). See API Key Gating for key management details.X-Api-KeyX-Widget-KeyX-Pro-KeyX-WorldMonitor-Desktop-TimestampX-WorldMonitor-Desktop-SignatureMcp-Session-IdMCP-Protocol-VersionLast-Event-ID
Access-Control-Allow-Headers in both files.
Browser-visible response headers include Mcp-Session-Id, WWW-Authenticate, and Retry-After via Access-Control-Expose-Headers so MCP clients can continue sessions, re-authenticate, and respect backoff hints.
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 for details.