Files
bench/site/root/_headers
T
istosandClaude Opus 5 6c06583109 site: serve bench.12vectors.com from a Cloudflare Worker
site/wrangler.jsonc puts site/dist/ behind bench.12vectors.com as static
assets. No `main`: the site is files, and a Worker with no script is the
cheapest correct way to serve them.

  html_handling      force-trailing-slash, so /x redirects to /x/ — the
                     url the pages link and rel=canonical names. One
                     page, one address; no url ends in .html.
  not_found_handling 404-page, so an unknown path gets dist/404.html
                     with a 404 status rather than the landing page
                     with a 200.
  routes             bench.12vectors.com as a custom domain. Cloudflare
                     takes the hostname at the zone level and makes the
                     DNS record; nothing else on 12vectors.com moves.

site/root/_headers carries the response policy. HTML revalidates on
every view, so a deploy is visible on the next reload without anyone
clearing a cache; /static/* is kept for a year and never re-checked,
which is safe because the stylesheet and icon urls carry a hash of their
contents. The general rule is written first and the specific one second,
so a host that merged the two instead of overriding would still land on
max-age=0 — the safe side. Alongside it the baseline a public page owes:
nosniff, a referrer policy, a year of HSTS without preload,
X-Frame-Options, and a default-src 'none' CSP that makes "no analytics,
no third-party anything" something the browser enforces rather than
something a test asserted once.

Deploys are run by hand, as releases already are — no Cloudflare token
in repository secrets, no first deploy pipeline. site/README.md names
the account, the Worker, the route and the four-command sequence, plus
the four things to check after a deploy that no test here can reach.

The tests cover everything before Cloudflare: that the config says what
the site needs, that the build writes the files it names, and that
wrangler.jsonc, pages.json and README.md cannot drift apart about which
domain this is. A live response is not among them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 11:47:12 +02:00

43 lines
2.3 KiB
Plaintext

# Response headers for bench.12vectors.com.
#
# Read by Cloudflare Workers static assets at deploy time — the file is
# consumed, never served — and copied here from site/root/ by
# site/build.py, because the host looks for it at the root of the build
# and nowhere else.
#
# Rules apply in order and a later rule wins on a header it repeats. The
# two blocks below are written so that even a host that merged them
# instead would land on the safe side: HTML would still revalidate.
# Everything, so that no page can ever forget one of these.
#
# nosniff a text/plain file must not become a script
# Referrer-Policy a full url is never sent to another origin
# HSTS one year, this host and anything below it. No
# `preload`: that is a submission to browser
# vendors and a commitment this card did not make
# X-Frame-Options nothing here is meant to be framed
# CSP the runtime form of the site's own promise —
# no analytics, no font CDN, no third-party
# anything. `default-src 'none'` means an asset
# must be named below to load at all, and no
# 'unsafe-inline' anywhere means an injected
# <script> does not run
# Cache-Control HTML revalidates on every view, so a deploy is
# visible on the next reload. The ETag makes that
# a 304 rather than a re-download
/*
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: DENY
Content-Security-Policy: default-src 'none'; style-src 'self'; font-src 'self'; img-src 'self'; connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'
Cache-Control: public, max-age=0, must-revalidate
# The stylesheet and the icon are linked with a ?v=<hash> of their own
# contents (site/build.py, stamp()), and the fonts never change under a
# given filename. All of it is safe to keep for a year and never check:
# a deploy that changes the stylesheet changes the url that asks for it.
/static/*
Cache-Control: public, max-age=31536000, immutable