Add audit.WriteOrLog: a one-line wrapper around Write that logs at
Warn and swallows the error, matching the package contract that
audit failures must not break user-facing operations.
Migrate the 13 call sites across 7 files in internal/api/ from the
3-line "if err != nil { logger.Warn(...) }" shape to a single call.
audit.Write stays exported for tests + any future caller that
needs strict semantics.
Adds three tests: success (no log), failure-via-closed-pool (Warn
record with action+err keys), and nil-logger (no panic). Tests
skip when MINSTREL_TEST_DATABASE_URL is unset, matching the
existing harness convention.
Four authenticated endpoints for the user's own account:
- PUT /api/me/password — change own password. Caller must
supply current_password (verified via bcrypt). Distinct from
admin-driven reset (which doesn't require knowing the old).
Audits ActionPasswordChangeSelf.
- PUT /api/me/profile — set display_name + email. Both fields
are nullable; empty string clears, omitted leaves unchanged.
Email is lowercased before store + format-validated. Unique
violation → 409 email_taken.
- GET /api/me/api-token — returns current API token (for
copy-paste into Subsonic clients).
- POST /api/me/api-token — regenerates token. Old one stops
working immediately. Audits ActionTokenRegenerate.
All four use the existing RequireUser middleware on the authed
sub-router; audit writes are best-effort (logged on failure).
Tests cover happy paths, wrong-password 401, password-too-short
400, email-invalid 400, email-taken 409, clear-by-empty-string,
omit-leaves-unchanged, token GET + regen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>