How the dashboard is served on Cloudflare: which Worker owns each route, how server rendering reads data, and which file owns each security header and cache policy.

Reference Value
Subject and boundary Route ownership on transit.yesid.dev, Worker bindings, document CSP, static headers and HTML caching. Release steps are on ‣.
Verified source web wrangler.toml, proxy wrangler.toml, kit.config.js, _headers, securityHeaders.ts, hooks.server.ts at main 9733eb26d92533f56cdc8bc46b81b93fbb5987c8, checked November 10, 2026.
Support state Implemented configuration. Social cards are static assets under /og/, /og/pages/ and /og/home/; static/og/manifest.json records their SHA-256 values, which also version the image URLs. Matching deployment and live hashes must establish what production serves.

Route ownership

Request Owner
transit.yesid.dev/* transit-web (SvelteKit on Workers Static Assets)
transit.yesid.dev/data/*, transit.yesid.dev/api/v1/* transit-data-proxy (more specific routes win)
/api/vitals, /api/geocode, /api/stops/slim, /health, /sitemap.xml, /robots.txt, /manifest.webmanifest, /.well-known/security.txt transit-web server routes
data.yesid.dev/v1/* R2 custom domain for public snapshots

How the web Worker reads data

Browsers read the public data origin (PUBLIC_V1_BASE). Server rendering prefers the SNAPSHOTS R2 binding and falls back to the DATA service binding within the request deadline. The web Worker has no database binding or credential. Its separate /api/geocode route forwards address searches to geolocator.api.geo.ca; the request, rate-limit and cache boundaries are documented on Security and access.

The build emits .svelte-kit/cloudflare/_worker.js with static assets served by the ASSETS binding. Generated server trees beside it must survive artifact transfer, which the sealed build guarantees. Pull request previews are uploaded as noindex Worker versions; production uses the custom route.

Security headers and caching

Concern Owner Policy
Document CSP kit.config.js Script hashes, not nonces, because cached HTML would replay a nonce. The pinned @yesid/ui/boot.json supplies the theme/section boot hash
Static asset headers apps/web/_headers Long-lived immutable app assets and fonts; separate rules for service worker and offline documents
Header alignment lib/site/securityHeaders.ts and its tests Keeps document and static policies consistent
HTML edge cache key hooks.server.ts The complete request URL including query, so provider-scoped URLs keep separate cache entries
Snapshot freshness Publisher Cache-Control and the data edge rule Independent of the HTML page's cache age

Section boot and recovery

hooks.server.ts uses injectThemeBoot from @yesid/ui/head; kit.config.js includes that exact package's boot hash in the document CSP. The v0.39.1 boot uses rendered eligibility to apply the remembered content-section choice before app initialization, while the TOC and independent panels use their declared state. Pending section markup is readable on initialization errors or a five-second stall. Recovery details: Recovery, backups and retention.

Verify a serving change

From apps/web: bun run check, the affected tests and bun run build. A route or binding change also needs bash apps/data-proxy/smoke.sh from the repository root on a Bash-capable host, which separates web-owned from proxy-owned requests. A green build or preview does not prove what production serves or that feeds are healthy.

Web health and logs

GET /health returns 200 only after reading parseable v1/stm/manifest.json whose provider is STM from the direct R2 binding. It returns 503 for an absent binding/object, wrong provider, invalid JSON, timeout or read failure. The read budget is 3 seconds; healthy results memoize for 30 seconds, failures for 4 seconds. Replies use Cache-Control: no-store and include service, commit, branch, time and data state. Build/deploy configuration injects the commit and branch.

This proves one snapshot is readable. It does not establish feed freshness, OC Transpo availability or full schema integrity. It is separate from the VM health API.

Both Workers enable application logs with query-string redaction, disable invocation logs and disable traces/issues in tracked Wrangler configuration. This preserves bounded error diagnosis while avoiding request records containing searched addresses. A configuration file does not prove a dashboard setting outside that deployment.