docs: server comments say what the code does, not how it came to be (#6277)

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>
This commit is contained in:
2026-10-23 12:15:05 -04:00
co-authored by Claude Opus 5.5
parent 9f9609591d
commit d191a28217
107 changed files with 485 additions and 597 deletions
+2 -2
View File
@@ -120,8 +120,8 @@ func requireJSONForCookieWrites(next http.Handler) http.Handler {
// by the SPA handler, which knows the inline-script hashes.
//
// HSTS goes out only when the request reached us over HTTPS as the trusted
// proxy reports it (rule 94): sending it over plain HTTP is ignored by
// browsers at best, and the app never forces HTTPS.
// proxy reports it: sent over plain HTTP it is ignored by browsers at best,
// and the app never forces HTTPS.
func securityHeaders(hops func() int) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+1 -1
View File
@@ -115,7 +115,7 @@ func TestSecurityHeaders(t *testing.T) {
t.Errorf("Permissions-Policy = %q", base.Get("Permissions-Policy"))
}
// Rule 94's three cases for HSTS.
// HSTS with no trusted proxy, and through one saying https or http.
if got := serve(0, "https").Get("Strict-Transport-Security"); got != "" {
t.Errorf("hops 0 + forwarded https: HSTS = %q, want none", got)
}
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"gopkg.in/yaml.v3"
)
// The publish gate (rule 177, M462 #4984), pinned. release.yml holds every
// The publish gate, pinned. release.yml holds every
// verifying lane and every publishing job in one graph so that a publish can
// depend on the lanes; these tests keep that dependency from eroding.
//
+16 -26
View File
@@ -10,17 +10,10 @@ import (
"testing"
)
// Guards the version derivation that stamps every build.
//
// These assertions used to be impossible to run. The derivation lived inline
// in release.yml, which triggers only on `main` and on tags — so a mistake in
// it could not surface until a release was already under way, and its failure
// mode is silence: a version nobody can compare looks exactly like being up to
// date, and nobody reports an update they were never offered.
//
// Moving it to ci/version.sh made it executable, so this runs on every push
// that touches the release machinery. That is the whole point of the file; the
// specific assertions below matter less than the fact that they run at all.
// Guards the version derivation that stamps every build, in ci/version.sh.
// Its failure mode is silence: a version nobody can compare looks exactly
// like being up to date, and nobody reports an update they were never
// offered. Keeping it in a script lets these tests run it on every push.
//
// The tests EXECUTE the script rather than asserting on its text, so they
// break when the behaviour changes rather than when the wording does.
@@ -188,8 +181,7 @@ var jobBoundary = regexp.MustCompile(`\n\n [^ \n]`)
//
// The naive cut — "up to the next `- name:`" — silently returns an EMPTY body
// for the last step in a job, and every assertion over it then passes
// vacuously. That is the failure rule 167 names: a check that reads as
// coverage while asserting on nothing. Cutting at a blank line followed by
// vacuously: a check that reads as coverage while asserting on nothing. Cutting at a blank line followed by
// job-level indentation handles the last-step case, which is exactly where
// `Build and push` sits.
func stepBody(t *testing.T, yaml, name string) string {
@@ -274,7 +266,7 @@ func TestDevChannel_PublishesDevAloneAndNeverLatest(t *testing.T) {
if strings.Contains(arm, ":latest") {
t.Errorf("dev arm moves :latest — that ships dev code to every stable operator\n%s", arm)
}
// Rule 145: a rolling channel gets no commit-addressable tag.
// A rolling channel gets no commit-addressable tag.
if strings.Contains(arm, "GITHUB_SHA") {
t.Errorf("dev arm publishes a per-commit tag; a rolling channel should not\n%s", arm)
}
@@ -367,21 +359,19 @@ func TestMainChannel_PublishesLatestAndTheRollbackUnit(t *testing.T) {
if !strings.Contains(arm, "${IMAGE}:${GITHUB_SHA}") {
t.Errorf("main arm publishes no commit-addressable image; there is no rollback target for production commits\n%s", arm)
}
// Rule 147: :latest tracks main's tip, and a second name for the same
// :latest tracks main's tip, and a second name for the same
// image sends readers looking for a distinction that does not exist.
if strings.Contains(arm, "${IMAGE}:main") {
t.Errorf("main arm publishes :main — rule 147 says that tag should not exist\n%s", arm)
}
}
// A release refreshes the CHANNEL and mints nothing else (rules 145 + 146).
// A release refreshes the CHANNEL and mints nothing else.
//
// The specific regression: re-adding :<sha> here. The tag build rebuilds the
// SAME SOURCE as main's build minutes earlier, differing only in which APK is
// baked in — so a :<sha> minted here would overwrite main's immutable rollback
// target with different contents, under the same name. That is the exact thing
// rule 145's immutability clause exists to prevent, and it is the half with
// the incidents behind it.
// The regression to guard: a :<sha> tag here. The tag build rebuilds the SAME
// SOURCE as main's build minutes earlier, differing only in which APK is baked
// in — so a :<sha> minted here would overwrite main's immutable rollback
// target with different contents, under the same name.
func TestReleaseBuild_RefreshesTheChannelAndMintsNothingElse(t *testing.T) {
arm, _, _ := imageTagArms(t, releaseYAML(t))
@@ -393,8 +383,8 @@ func TestReleaseBuild_RefreshesTheChannelAndMintsNothingElse(t *testing.T) {
}
}
// No version-numbered image tags anywhere, on any arm (rule 145, and the
// operator's 2026-09-10 decision to drop them across every project).
// No version-numbered image tags anywhere, on any arm: the build's version is
// self-reported, and the tag map is :latest, :<sha> and :dev.
//
// Asserted across the whole step rather than per-arm because the mistake this
// catches is re-adding one ANYWHERE, and the tag arm is only the likeliest
@@ -441,9 +431,9 @@ func TestVerifyJob_ChecksTheRollbackImageNotAVersionTag(t *testing.T) {
}
}
// The server's self-reported version is now the ONLY thing that identifies a
// The server's self-reported version is the ONLY thing that identifies a
// build, so a lane that stamps a channel word instead of a version silently
// removes that ability. It used to stamp the literal "main"/"dev".
// removes that ability.
func TestImageBuild_StampsADerivedVersionAndAChannel(t *testing.T) {
yaml := releaseYAML(t)
+7 -9
View File
@@ -19,18 +19,16 @@ import (
// hits it every 5s and would otherwise drown real signals (~17k lines/day).
//
// Severity is keyed off the response status so 4xx/5xx surface even when
// the operator's logger level is set above Info.
// the logger level is set above Info.
//
// The `remote` attribute holds the address resolved through the operator's
// configured reverse-proxy depth, NOT the raw socket peer (#2453). Behind a
// proxy — the normal deployment for anything public — the socket peer is the
// proxy, so every line would have carried the same useless address, and the
// access log would have disagreed with the Active-sessions surface about who
// connected. The attribute key is unchanged so existing log greps keep
// working; only its accuracy improved.
// The `remote` attribute holds the address resolved through the configured
// reverse-proxy depth, NOT the raw socket peer. Behind a proxy — the normal
// deployment for anything public — the socket peer is the proxy, so every
// line would carry the same useless address, and the access log would
// disagree with the Active-sessions list about who connected.
//
// trustedHops is a func because this middleware is constructed at boot while
// the value is operator-editable at runtime, and — since Router() registers
// the value is editable at runtime, and — since Router() registers
// this before it builds the settings service — because it lets the accessor
// be wired before the thing it reads exists. auth.ClientIP tolerates a depth
// of 0, which is what a nil service reports.
+3 -4
View File
@@ -109,8 +109,7 @@ func TestRequestLog_AttributesPresent(t *testing.T) {
}
}
// The point of routing #2453 through the access log: behind a proxy, `remote`
// must be the client rather than the proxy, and must agree with what the
// Behind a proxy, the access log's `remote` must be the client rather than the proxy, and must agree with what the
// Active-sessions surface records for the same request. Logs and UI
// disagreeing about who connected is worse than either being wrong alone.
func TestRequestLog_RemoteHonoursTrustedProxyDepth(t *testing.T) {
@@ -136,8 +135,8 @@ func TestRequestLog_RemoteHonoursTrustedProxyDepth(t *testing.T) {
want: "203.0.113.200",
},
{
// The case that motivated the change: proxy on a PUBLIC address,
// which the pre-#2453 heuristic logged as the proxy forever.
// A proxy on a PUBLIC address: a "trust XFF only from private
// peers" heuristic would log the proxy forever.
name: "depth 1 through a public-addressed proxy logs the client",
hops: func() int { return 1 },
remoteAddr: "203.0.113.200:40000",
+16 -18
View File
@@ -65,34 +65,34 @@ type Server struct {
// When nil, Router() constructs a local fallback (test contexts).
Bus *eventbus.Bus
// PlaylistScheduler fires per-user daily system-playlist builds at
// 03:00 in each user's stored timezone (#392 Half B). Constructed
// 03:00 in each user's stored timezone. Constructed
// in cmd/minstrel/main.go and threaded into the API handlers so
// PUT /api/me/timezone and POST /api/auth/register can call
// Refresh synchronously.
PlaylistScheduler *playlists.Scheduler
// RecSettings is the DB-backed recommendation tuning lab (#1250):
// RecSettings is the DB-backed recommendation tuning:
// scoring-weight profiles + taste-build knobs. Constructed in
// cmd/minstrel/main.go (it pushes daily-mix weights into package
// playlists at boot); the API layer reads radio weights per request
// and serves the admin tuning endpoints from it. Router() constructs
// a fallback when nil (tests).
RecSettings *recsettings.Service
// FingerprintSettings is the DB-backed fingerprinting policy (M400 #3913).
// FingerprintSettings is the DB-backed fingerprinting policy.
// Constructed in cmd/minstrel/main.go and shared with the scanner and the
// fingerprint workers, so a save from the admin card reaches them without a
// restart. Router() constructs a fallback when nil (tests).
FingerprintSettings *library.FingerprintSettingsService
// LoudnessSettings is the DB-backed loudness analysis policy (M464 #4995),
// LoudnessSettings is the DB-backed loudness analysis policy,
// shared with the loudness backfill. Nil makes the router load its own.
LoudnessSettings *library.LoudnessSettingsService
// AcoustIDLookup is the AcoustID lookup worker (M401), whose settings,
// AcoustIDLookup is the AcoustID lookup worker, whose settings,
// status and "look up now" the admin card drives. Nil in test contexts;
// one is built (and never run) so the admin routes still answer.
AcoustIDLookup *library.AcoustIDLookupWorker
// ReacqSettings is the DB-backed missing-file re-acquisition policy
// (milestone #290) — the same instance the sweeper in cmd/minstrel/main.go
// reads, so a save from the admin card reaches it without a restart
// (#3936). Router() constructs a fallback when nil (tests).
// ReacqSettings is the DB-backed missing-file re-acquisition policy — the
// same instance the sweeper in cmd/minstrel/main.go reads, so a save from
// the admin card reaches it without a restart. Router() constructs a
// fallback when nil (tests).
ReacqSettings *reacquisition.SettingsService
// StreamSecret is the HMAC key used by /api/cast/stream-token to
// mint signed UPnP / Sonos stream URLs and by /api/tracks/{id}/stream
@@ -154,13 +154,11 @@ func (s *Server) Router() http.Handler {
tracksSvc := tracks.NewService(s.Pool, s.Logger, s.DataDir)
playlistsSvc := playlists.NewService(s.Pool, s.Logger, s.DataDir)
smtpSender := mailer.NewSMTPSender(s.Pool, s.Logger.With("component", "mailer"))
// Live-event bus for SSE subscribers (#392). Constructed per-process;
// producers in playevents / requests / scanner publish into
// the same instance. Background workers (request reconciler, scan
// scheduler) live in cmd/minstrel/main.go where they're constructed
// before Router() runs; they read s.Bus directly so they share this
// process's bus. When Router() runs before main set the bus (tests,
// or future contexts) we fall back to a fresh local instance.
// Live-event bus for SSE subscribers, one per process: producers in
// playevents / requests / scanner publish into the same instance.
// Background workers are built in cmd/minstrel/main.go before Router()
// runs and share s.Bus. With no bus set (tests), a fresh local one is
// used.
bus := s.Bus
if bus == nil {
bus = eventbus.New()
@@ -240,8 +238,8 @@ func (s *Server) handleHealthz(w http.ResponseWriter, _ *http.Request) {
}
// handleAdminScan runs a scan synchronously and returns the resulting stats.
// Kept synchronous for v1: libraries are small and the operator can tell when
// it's done. Async jobs with status polling are a later-milestone concern.
// Synchronous, so the caller can tell when it's done; the scan's progress is
// also published as scan-run events.
func (s *Server) handleAdminScan(w http.ResponseWriter, r *http.Request) {
stats, err := s.Scanner.Scan(r.Context(), nil)
w.Header().Set("Content-Type", "application/json")
+5 -7
View File
@@ -244,13 +244,11 @@ func TestRouter_AdminSubtreeNotShadowed(t *testing.T) {
}
}
// TestRouter_ReacquisitionSettingsSavedThroughTheAPIReachTheSweeper is a
// regression test for #3936. Router() used to construct a
// reacquisition.SettingsService of its own, so a save from the admin card
// refreshed THAT instance's cache while the sweeper in cmd/minstrel/main.go
// kept serving what it had loaded at boot. The card showed the new policy, the
// feature kept running the old one, and only a restart reconciled them — the
// exact thing rule 25 says a setting must not need.
// TestRouter_ReacquisitionSettingsSavedThroughTheAPIReachTheSweeper: a
// Router() that built a reacquisition.SettingsService of its own would refresh
// THAT instance's cache on a save, while the sweeper in cmd/minstrel/main.go
// kept serving what it loaded at boot. The card would show the new policy and
// the feature run the old one until a restart.
//
// The assertion is made against the instance main.go hands the sweeper: save
// through the router, then read that instance. A second service leaves it stale.
+1 -1
View File
@@ -6,4 +6,4 @@ package server
const MinClientVersion = "0.1.0"
// The build's version and channel live in internal/buildinfo, shared with
// the Subsonic envelope and the admin Overview (M504).
// the Subsonic envelope and the admin Overview.