824ca03ad4
The global `script-src 'self'` CSP header blocked every inline <script>, so the SvelteKit hydration bootstrap never ran and the SPA never mounted (blank page behind the splash spinner). The anti-FOUC theme init in app.html was blocked too. Instead of weakening the policy with 'unsafe-inline', the backend now builds `script-src` at startup from 'self' plus a SHA-256 hash of every inline <script> in the served HTML shells. The policy stays strict (no 'unsafe-inline' for scripts) and the hashes are recomputed from the built assets on each startup, so a frontend rebuild needs no header edit — even though SvelteKit's bootstrap hash changes every build. - web::content_security_policy builds the header; web::resolve_static_path is extracted so serving and hashing read the exact same bytes. - byte-exact inline-script extraction (skips src= externals), unit-tested against a known SHA-256 vector and extraction edge cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>