# Cloudflare Pages reads this file at deploy time and applies the headers to matching routes.
#
# The CSP is the machine-checkable version of a claim this client makes in prose: it loads nothing
# from anywhere else. `default-src 'self'` with no CDN, no font host, no analytics — so if a future
# edit ever reaches for a third-party script, the page breaks loudly in review instead of quietly
# shipping a new party into a surface that handles a token and a private key.
#
# connect-src is the one opening, and it is the point of the product: wss: for the account relay
# (which is a different hostname from this page by design — the relay is a Durable Object at
# relay.ferrow.ai) and https: for the Ferrow API. Both are user-configurable in the pairing form
# (self-hosters exist), which is why the scheme, not the host, is what is pinned here.

/*
  Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https: wss:; frame-ancestors 'none'; base-uri 'none'; form-action 'none'
  X-Content-Type-Options: nosniff
  Referrer-Policy: no-referrer
  Permissions-Policy: geolocation=(), microphone=(), camera=(), interest-cohort=()
  Cross-Origin-Opener-Policy: same-origin
  Cache-Control: no-cache
  X-Robots-Tag: noindex, nofollow

# X-ROBOTS-TAG IS THE LAYER THE OTHER TWO CANNOT REACH (R7-27). web/robots.txt carries the request
# and web/index.html carries the <meta>, but robots.txt is advisory and a meta tag cannot speak for
# app.mjs, a font, or a 404 response. This header rides on every response from this host, which is
# the only form of the statement that covers all of them. It is on `/*` deliberately — there is no
# path on app.ferrow.ai that is meant to appear in a search result. ferrow.ai is unaffected: it has
# its own site/_headers and stays fully indexable, which is the point of the split.
#
# no-cache above is NOT no-store: every asset still revalidates by etag and 304s when unchanged,
# so the cost is one conditional request per file. What it buys: html and its module graph can
# never be served from two different deploys at once. Pages' default (max-age=14400) did exactly
# that on 2026-08-11 — a visitor held a 4h-old kit while the html moved on, and the founder saw
# the chimera. The module graph is unversioned (imports say ./lib/x.mjs), so freshness must come
# from headers, not URLs. Fonts are the exception below: content-stable, safe to hold.

/fonts/*
  Cache-Control: public, max-age=86400, must-revalidate
