Rewrites the internal/api comment blocks to rule 32: task, milestone and
rule ids gone, the stories behind them restated as the constraint they
left, stale references corrected (the stream secret is wired from config,
the timezone handler already refreshes the scheduler, the Android app is
the native client, the design docs cited are not in the repo). Also
rewraps comment lines over 80 columns left by the earlier batches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PR1-T2 admin handler migration replaced bespoke 500-class messages
("lookup failed", "refetch failed", "trigger failed", "bump failed",
"remove failed", "update failed", "schedule row missing", "re-read
failed", "read failed") with apierror.Internal(err), which forces the
wire Message to "internal server error". That violates the PR1
contract that errEnvelope{Code, Message} must remain byte-identical
for existing clients.
Add apierror.InternalMsg(message, cause) — a 500-class constructor
that preserves the call site's user-facing message while keeping the
cause attached for logging and errors.Is. Re-migrate the 12 admin
sites whose pre-1cc7eb6 source had a non-empty bespoke Message so
they restore the original wire string. Sites whose original Message
was empty stay on Internal(err) (humanization to "internal server
error" is a tolerable improvement, not a regression).
admin_smtp.go's send_failed site (line 129) was already preserved
via a raw &apierror.Error literal in 1cc7eb6 and needs no fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewrite writeErr(w, err) to wrap *apierror.Error via apierror.From,
preserving the existing {"error": {"code", "message"}} wire envelope.
Add writeErrWithLog helper for 500-class errors that need an operator
log line. Migrate all 13 admin_*.go handler files (~76 call sites) to
the new signature; T3 will sweep the remaining api package.
The old 4-arg writeErr is removed, so non-admin call sites in
internal/api will not compile until T3 lands. This is by design — T2
and T3 are paired.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three endpoints for the admin Settings UI:
- GET /api/admin/cover-sources — lists registered providers with
current settings + capability badges + sources_version
- PATCH /api/admin/cover-sources/{provider_id} — updates enabled
and/or api_key; returns version_bumped: true only when the
enabled set changed
- POST /api/admin/cover-sources/{provider_id}/test — invokes
TestableProvider.TestConnection; returns ok:bool + duration_ms +
error string. Returns 200 in both success and failure cases (the
operation completed; the test result is data, not an error).
api_key is never echoed in GET — replaced with api_key_set: bool
to follow the standard credential-display convention. PATCH
api_key: "" clears; omitting the field leaves it unchanged. PATCH
on an unknown provider_id returns 404.
All under existing RequireAdmin middleware. Routes registered
alongside the library/coverage endpoint in the /api/admin/ tree.
handlers struct gains a coverSettings *coverart.SettingsService
field; server.New + cmd/minstrel/main.go plumb the existing
coverSettings instance through.
coverart.ResetRegistryForTests() exported wrapper added so api
package tests can reset the registry without importing internals.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>