Conflict resolution + cross-PR integration:
- player.ts: kept #88's POST /:botId/fm route AND gated it with
requirePermission('player.control') so the new control endpoint honors #80's
permission model (it was added without gating).
- bot.ts: kept #81's relocated /settings routes (the relocation fixes the GET
/settings shadow bug) and dropped #80's now-duplicate bottom copy; gated
POST /settings with requirePermission('bot.manage').
- Navbar.vue: composed #82's dedicated-link scope with #80's permission filter —
displayedBots is now the INTERSECTION (scope ∩ controllable allow-list).
- database.ts: kept BOTH new table sets (#87 favorite_playlists + #80
user_permissions/user_bot_access).
- bot.test.ts: updated to createRequireAuth(sessions, permissions) for #80's new
two-arg signature.
#80 review fixes (credential exposure / IDOR, adversarially verified):
- GET /:id/config now requires bot.manage + bot access AND redacts ts6ApiKey +
identity from the response (was readable by any authenticated member).
- GET /:id and GET /:id/avatar now require bot access (were ungated read oracles).
Capability flags (player.control/player.queue/bot.manage/platform.auth/quality) + per-member bot allow-list, layered under the existing member role; admin is super-user. Backend-enforced via requirePermission/requireBotAccess; existing members backfilled to full on upgrade, new members get a basic tier.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Spec for adding username+password auth to the WebUI to close the
unauthenticated-API exposure (all /api/* and /ws currently open).
Design: SQLite users + sessions tables, bcryptjs, 7-day rolling
HTTP-only cookie sessions, first-run setup wizard, Origin/Referer
CSRF check, WebSocket upgrade gated on the same session cookie.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spec for issue #51: custom avatar with idle/playback precedence rules,
and surfacing albums in search results + album detail playback. Two
features grouped in one spec; will land as two separate PRs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Eight tasks: queue history field/helper, history-aware prev with
TDD tests, addNext with TDD tests, REST + command surface, store
action, SongCard third button, view wiring, final verify + smoke.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two queue features:
- prev walks back through actual play history (50-entry stack), so
random modes navigate predictably instead of falling back to the
meaningless currentIndex-1 array walk.
- addNext inserts at currentIndex+1, exposed via new /play-next-song
endpoint, !playnext command, and a third "下一首播放" button on
SongCard. Insert path keeps playedIndices and history index refs
valid by shifting entries > currentIndex.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Step-by-step plan for per-platform tabs on Home and Library: SourceTabs
component, store refactor with authStatus and per-platform data, view
migrations with localStorage persistence, build verification, and
3-scenario manual smoke test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design for adding NetEase / QQ source switcher tabs to recommend
playlists, daily songs, and user playlists on Home, plus user playlists
on Library. Tabs auto-hide when only one source is available; selection
persists per-section in localStorage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add BotProfileManager that updates the bot's TeamSpeak presence when
songs change: album cover as avatar, song info in nickname, away status
toggled on stop/play. Each feature is independently configurable via
REST API and persisted to the database. Permission-safe — features that
fail due to insufficient server permissions are silently disabled until
reconnect. Description falls back to nickname display on TS3 (only
supported via TS6 HTTP Query).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>