Comment blocks in cmd/minstrel and 30 smaller internal packages, rewritten
to rule 32's standard with each citation read in context: task, milestone
and rule ids go, and so do the stories they were attached to ("used to",
"Before #N", measurements from one install, quotes, pointers to Fabled
Librarian's records and to docs/superpowers files that are not in the
repo). Where a story wrapped a real constraint, the constraint stays as a
present-tense fact.
Comments that had gone stale are corrected:
- taste.Config: the tuned values are overlaid by internal/recsettings;
it is no longer "a later follow-up".
- StorageConfig: the data dir holds art, caches and the stream secret,
not only playlist covers.
- the Subsonic album list and getUser comments describe what they do
today rather than a milestone that would change it.
Checked: the non-comment token stream of every changed file matches
HEAD, and gofmt -l is empty.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There were no security headers at all. Now:
- every response: nosniff, Referrer-Policy strict-origin-when-cross-origin,
Permissions-Policy (no camera/mic/geolocation), X-Frame-Options DENY;
each set only if the handler hasn't.
- HSTS only when the trusted proxy reports HTTPS (rule 94); never a redirect.
- index.html carries a Content-Security-Policy whose script-src is 'self'
plus the sha256 of each inline script in the page as served, computed
after the branding template runs. No 'unsafe-inline' or 'unsafe-eval'
for scripts. img-src admits remote https/http because Lidarr suggestion
art is a remote poster URL.
Hashing in Go rather than via SvelteKit's kit.csp covers the inline scripts
SvelteKit doesn't know about (app.html's theme bootstrap and the branding
global injected at build) and stays correct whatever the app name is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Every request body is capped at 4 MiB and must arrive within 30s. The
deadline is set per request and cleared at end of body rather than via
http.Server.ReadTimeout, which would cancel audio streams and the SSE
stream once the background read hit it.
- IdleTimeout 120s closes idle keep-alive connections. Still no global
WriteTimeout, for the same streaming reason.
- Streams, album covers and playlist covers are Cache-Control: private, so
a shared cache never keeps an authenticated response for others.
- A cookie-authenticated write to /api must be application/json (415
otherwise). SameSite=Strict can't see a sibling app on the same
registrable domain; forms and no-preflight fetches can't send JSON.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>