Commit Graph
4 Commits
Author SHA1 Message Date
bvandeusenandClaude Opus 5.5 b46c080d19 fix(web): all accent text and icons use accent-fg (#5318)
release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m11s
release / go (push) Successful in 1m26s
release / integration (push) Successful in 4m18s
release / android (push) Successful in 4m44s
release / Build signed APK (releases and dev) (push) Successful in 4m53s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 26s
release / Verify release artifacts (tag releases only) (push) Skipped
The raw accent fails AA as text on every dark surface, not only on its
own tint: 3.04:1 on the page, 2.70 on iron, 2.21 on slate, against 4.5.
accent-fg (the house formula, 45% toward parchment) measures 5.62 at
worst across both modes. The operator chose the readable colour over the
signature teal for text, on 2026-10-08.

- 36 sites swap. They are 35 Tailwind uses: links, "Now playing", the
  ingest progress line, active shuffle/repeat, the liked heart, the app
  download icon and its hover. The last is the alphabet rail's pending
  spinner in CSS. Icons follow the text: as graphics they need only
  3:1, and the raw accent misses even that on iron.
- check-tint-contrast adds accent to TEXT_NEVER_RAW, so a new raw
  text-accent or color: var(--fs-accent) fails the web lane. Run against
  the files before the swap, it finds all 36. Borders, rings and fills
  keep the raw accent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 00:17:19 -04:00
bvandeusenandClaude Opus 5.5 3bfddd0862 feat(auth): throttle login, register, password reset and Subsonic auth failures (M462 #4976)
test-go / test (push) Successful in 1m54s
test-web / test (push) Successful in 1m34s
test-go / integration (push) Successful in 4m56s
android / Build + lint + test (push) Successful in 5m41s
release / Build signed APK (releases and dev) (push) Successful in 5m52s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
Every password-shaped check was mounted bare, so guessing was limited only
by bcrypt cost. A shared in-memory AttemptLimiter now sits in front of them:

- login: 10 failures per account and 50 per address per 15 min, checked
  before the user lookup and bcrypt; 429 with Retry-After. A success clears
  the account's count but not the address's.
- unknown usernames run a dummy bcrypt compare, so timing no longer says
  which accounts exist.
- register: 10 per address per hour; forgot-password: 5 per address and 3
  per email per hour (applied whether or not the email matches); reset: 20
  failed tokens per address per 15 min.
- Subsonic /rest: same limits as login, counting only wrong credentials,
  since clients authenticate on every request.

Web login, register, reset and forgot-password screens say how long to
wait; web and Android carry copy for the rate_limited code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 08:28:29 -04:00
bvandeusen 444144038a fix(ci): library_test Mount arg + 4 web test selectors + forgot-pw catch
Five fixes in one commit, all from the U1+U2+U3 push:

1. internal/api/library_test.go's Mount call wasn't updated when
   U3-T4 added the mailer.Sender param. 17 args, sig wants 18.
   Adds a trailing nil for the mailer. Same shape of test-fixture
   lag the project has hit before — flagged as a recurring pattern
   for the DRY-pass slice.

2. web/src/routes/settings/settings.test.ts mocked $lib/api/me with
   `getAPIToken: vi.fn()` (no return value). The new /settings API
   Token card's $effect calls `getAPIToken().then(...)` which threw
   "Cannot read properties of undefined (reading 'then')" on every
   ListenBrainz test. Default the mock to mockResolvedValue so any
   test that doesn't override gets a valid resolution.

3. web/src/routes/admin/users/users.test.ts queried row buttons by
   /^Delete$/ but T3 added per-user aria-labels ("Delete alice"),
   so the row buttons' accessible name is no longer "Delete". The
   modal's confirm button has no aria-label so its name IS "Delete"
   exactly. Tests now click by per-user aria-label first, then by
   /^Delete$/ for the modal confirm.

4. Same file: /Set password/i regex matched both the dialog's
   submit button AND the row's "Reset password for ..." buttons
   (because regex `Set` matches "ReSet" case-insensitively). Switched
   to /^Set password$/ exact-match.

5. web/src/routes/reset-password/[token]/reset-password.test.ts had
   /New password/i which matched both the "New password" and
   "Confirm new password" labels. Switched to exact-match string
   selectors.

6. web/src/routes/forgot-password/+page.svelte's onSubmit handler
   had no catch — a rejected forgotPassword() bubbled as an
   unhandled rejection in vitest. Added a silent catch since the
   page intentionally shows the same success message regardless of
   outcome (no-enumeration posture).
2026-05-07 18:05:30 -04:00
bvandeusen 72f46a885b feat(web/m7-user-mgmt): /settings expansion + /forgot-password (U3-T5a)
Lands four of the U3 frontend surfaces. Splits T5 because the
dispatch covering everything in one shot crashed the runtime
mid-execution; this is the salvageable half.

- /settings gains three cards alongside Appearance: Profile
  (display name + email), Password (current + new + confirm with
  client-side mismatch check), API Token (display + copy +
  regenerate-with-double-click-confirm). Server error codes map
  to clear toasts.
- /forgot-password — public; takes an email and always shows the
  success message regardless of whether the email is on file
  (mirrors the server's no-enumeration posture).
- Login page gets a "Forgot password?" link below the existing
  register link.
- API client functions for the four /me endpoints (changePassword,
  updateProfile, getAPIToken, regenerateAPIToken), the SMTP admin
  trio (getSMTPConfig, updateSMTPConfig, testSMTPConfig), and the
  forgot/reset auth pair (forgotPassword, resetPassword).

Tests for these surfaces + /reset-password page + admin SMTP card
land in T5b (next follow-up).
2026-05-07 17:33:48 -04:00