# Cloudflare Pages headers for the hosted-web Eliza app.
# Format: https://developers.cloudflare.com/pages/configuration/headers/
#
# Cloudflare Pages drops headers larger than ~2000 bytes silently. Keep the CSP
# line under ~1900 bytes; verify with `wc -L < public/_headers`.
#
# /api/* and /steward/* are proxied to the Workers API by functions/_middleware.ts
# (true same-origin, no CORS preflight). The api.elizacloud.ai entry in
# connect-src is the fallback for direct cross-origin calls; the canonical path
# is same-origin /api/* through the Function.
#
# vs cloud-frontend/_headers: the app additionally allows wss://*.elizacloud.ai +
# https://*.elizacloud.ai (dedicated-agent container subdomains the runtime WS
# connects to) and blob:/data: media (local voice/TTS). The SPA also ships an
# inline meta CSP (index.html) for the renderer; this edge header is canonical.

/*
  Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://static.cloudflareinsights.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self' https://oauth.telegram.org; frame-ancestors 'self'; child-src 'self' blob: https://elizacloud.ai https://*.elizacloud.ai https://*.steward.fi https://verify.walletconnect.com https://verify.walletconnect.org https://challenges.cloudflare.com https://oauth.telegram.org https://www.youtube.com https://youtube.com; frame-src 'self' https://elizacloud.ai https://*.elizacloud.ai https://*.steward.fi https://verify.walletconnect.com https://verify.walletconnect.org https://challenges.cloudflare.com https://oauth.telegram.org https://www.youtube.com https://youtube.com; connect-src 'self' https://elizacloud.ai https://*.elizacloud.ai wss://*.elizacloud.ai https://api.elizacloud.ai https://api-staging.elizacloud.ai https://api.open-meteo.com https://*.publicnode.com https://bsc-dataseed.binance.org https://api.mainnet-beta.solana.com https://*.walletconnect.com https://*.walletconnect.org wss://*.walletconnect.com wss://*.walletconnect.org https://challenges.cloudflare.com https://*.steward.fi https://*.helius-rpc.com https://*.alchemy.com https://*.coinbase.com wss://*.coinbase.com https://*.web3modal.org https://*.web3modal.com https://*.reown.com https://*.phantom.app https://*.solflare.com; worker-src 'self' blob:; manifest-src 'self'; media-src 'self' data: blob: https:
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  X-XSS-Protection: 1; mode=block
  Permissions-Policy: camera=(self), microphone=(self), geolocation=(self)
  Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  Cache-Control: no-cache

# The no-cache rule on /* is deliberately the ONLY Cache-Control in this file.
# Multiple matching _headers rules aggregate into one comma-joined value rather
# than overriding (a /assets/* rule here would produce "no-cache, public,
# max-age=..., immutable", which browsers resolve as revalidate-always), so the
# immutable policy for /assets/* hits, the 404 for /assets/* misses, and the
# no-store for /sw.js all live in functions/_middleware.ts instead.

# OAuth/popup callback pages need a relaxed COOP so popup status remains
# observable when a browser path is script-opened. OS-opened tabs still must not
# render dead close controls.
/app-auth/*
  Cross-Origin-Opener-Policy: same-origin-allow-popups

/auth/*
  Cross-Origin-Opener-Policy: same-origin-allow-popups
