Merges Renovate's kit 3 (PR #149) and adapter-static 4 (PR #148) bumps,
plus the migration they need. The mechanical part is `sv migrate
sveltekit-3`, run one task at a time and reviewed:
- svelte.config.js is gone. Its options move into sveltekit() in
vite.config.ts, exported as kitOptions so vitest.config.ts runs the
same kit setup, including the $test-utils alias the tests import.
- $lib becomes #lib through package.json "imports". There is no
src/lib/index, so only the "#lib/*" entry is kept.
- tsconfig extends $app/tsconfig.
- Peer floors raised to kit 3's requirements: svelte ^5.57.1, vite
^8.0.12, svelte-check ^4.7.5.
By hand, from the codemod's list of non-automated tasks:
- goto's replaceState option is now replace; keepFocus becomes
reset: false. For the search typeahead, reset: false also stops the
scroll-to-top, which is wanted while typing.
- The test setup mocks drop pushState/replaceState and $app/paths
base/assets, which kit 3 removed, and mock refreshAll in place of
invalidateAll.
- The other flagged files only read page.url or goto internal routes,
so they needed no change.
TypeScript goes to ^6, not the ^7 Renovate offers: kit 3 declares
typescript ^6 as a peer and svelte-check 4.7 accepts ^5 || ^6. Move to
7 once both accept it.
With Tailwind 4 and kit 3 in, `npm audit` on the whole tree reports 0,
so the web lane now audits every dependency rather than only what
ships to browsers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While no accounts exist, the server mints a random setup token at boot and
logs it. Registering the first account (which becomes admin) must carry it,
so whoever reaches a freshly exposed instance first cannot claim it. The
register page asks GET /api/auth/setup-status and shows a "Setup token"
field in place of the invite field while setup is pending.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Web client posts Intl.DateTimeFormat().resolvedOptions().timeZone to
PUT /api/me/timezone after every successful login, register, and
bootstrap when the locally-stored tz_last_sent_at is >7 days old.
Cadence tracked in localStorage keeps the server stateless on the
"is this stale?" check.
Failures swallowed: the server's UTC default + last-known value keep
the scheduler functioning until the next successful attempt. SSR-
safe via the typeof window guard.
For #392 Half B. Companion Flutter change in next commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
auth/store.svelte.ts no longer imports from $lib/player. Logout
broadcasts via auth/sessionEnd.svelte.ts (a tiny tick + outgoing
userId pair); player subscribes through $effect.root and owns the
player-specific teardown (clearPersistedQueue + playQueue([]) +
closeQueueDrawer()).
Cycle fully inverted — auth is now a pure leaf for player; future
session-end consumers (download cache, recent-search history) plug
in by adding their own effect on the same signal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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).
Public /register form: username, optional display name, password +
confirm, optional invite token. Submits to POST /api/auth/register
via the new register() helper in auth/store.svelte.ts. On success
the server sets the session cookie and the frontend redirects to /;
on error the page shows a code-specific message (invite_required,
invite_invalid, username_taken, etc.).
Login page gets a "Don't have an account? Register" link below the
form for symmetry.
Tests cover form rendering, password-mismatch client-side rejection,
the happy-path submit + redirect, and the invite-invalid error
mapping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Central synchronous source of truth for 'who is signed in'. bootstrap()
runs once in +layout.ts load(); login/logout mutate _user and the
TanStack query cache. The silent option on logout is used by the 401
interceptor (next commit) to avoid POSTing /logout against an already-
invalid session.