Creates household via POST /v1/households, redirects to /household/staples.
Load guard redirects users who already have a household to /planner.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add secure: true to cookies.set() in login and signup actions
- Add tests verifying JSESSIONID is forwarded to browser on successful
login and signup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add response object to mockSuccess() in login and signup tests so
response.headers.get() no longer throws
- Validate ?redirect= param: must start with / and not // to prevent
redirecting users to external domains
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three root causes fixed:
1. CSRF blocked all backend POSTs — Spring Security's CSRF filter ran
before permitAll() authorization, returning 401 for signup and login.
Disabled CSRF since SvelteKit is the only client (never the browser
directly) and handles its own CSRF via Origin header checks.
2. Login/signup didn't establish Spring Security authentication — they
stored email in the HTTP session manually but never set the
SecurityContext, so Principal in /v1/auth/me was always null and
hooks.server.ts redirected every authenticated request to /login.
Fixed with authenticateInSession() helper that sets and persists
the SecurityContext under SPRING_SECURITY_CONTEXT_KEY. Login also
now invalidates the old session before creating a new one to prevent
session fixation.
3. redirect() missing throw in hooks.server.ts, signup action, and
login action — SvelteKit never saw the redirect, so pages silently
reloaded with no navigation. Also forward JSESSIONID from backend
response to browser explicitly, since SvelteKit does not
auto-forward Set-Cookie for cross-origin server-side fetches.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POSTs to /v1/auth/login, validates email/password server-side,
redirects to ?redirect param or /planner on success.
Returns generic error on bad credentials to prevent enumeration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Email/password fields, client-side validation, password show/hide,
server error display via form prop, signup link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parameterized test verifying the exact boundary of the 8-character
minimum password requirement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies all three validation errors (name, email, password) appear
simultaneously when submitting a completely empty form.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SignupForm now uses use:enhance for progressive enhancement.
Accepts form prop for server-side error display. Shows general
form errors in a banner and field-specific errors inline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validates displayName, email, password server-side before calling
the backend API. Handles null from formData.get() safely.
Returns structured field errors via fail(400, { errors }).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Form container now horizontally centered on md+ viewports,
left-aligned on mobile for full-width usage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sets <title>Konto erstellen — Mealprep</title> via svelte:head
for browser tab and accessibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spec shows green text with font-weight 500, no underline by default.
Was dark text with underline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
--green (#3D8C4A) gives 4.16:1 against white — fails AA.
--green-dark (#2E6E39) passes comfortably.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies signup page renders form and brand panel but no
navigation elements (tabs, sidebar, links to app routes).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Composes BrandPanel + SignupForm in responsive split layout.
Server action POSTs to /v1/auth/signup and redirects to
/household/setup on success.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Form with name/email/password fields, client-side validation,
inline error messages, and password show/hide toggle.
Uses native form action for progressive enhancement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renders brand identity with logo, app name, tagline, and feature icons
on green-dark background. Responsive: banner on mobile, 440px column
on desktop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The signup page needs its own brand panel, so the shared layout
becomes a simple slot. Login page now owns its brand panel markup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Applies hover:bg-[var(--color-subtle)] to inactive nav links for
visual feedback on pointer devices.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renders emoji icons in MobileTabBar (stacked above label),
TabletNavBar (inline), and DesktopSidebar (16px, 20px column).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Proves active state logic generalizes beyond /planner by testing
all 4 mobile nav routes with writable page store.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts isActiveRoute() into shared nav module. Matches exact path
or path + '/' prefix, preventing /settings from matching /settings-advanced.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes non-null assertions on householdId/householdName. Users who
haven't joined a household get a fallback name in the sidebar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Appends ?redirect= with the original pathname so the login page
can redirect back after successful authentication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents redirect loop when backend is down — login page CSS/JS
would otherwise be redirected to /login.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verified: SvelteKit's plugin overrides resolve.conditions for SSR
builds. The global 'browser' condition only affects vitest and dev.
Build output confirmed correct with npm run build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- (app) group with AppShell layout, loads user/household from locals
- (public) group with full-viewport split layout, /login placeholder
- Root / redirects to /planner for authenticated users
- Placeholder stubs for planner, recipes, shopping, settings, members
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Validates session cookie via GET /v1/auth/me, populates event.locals
with benutzer and haushalt, redirects to /login if unauthenticated.
Public routes (/login, /register, /invite) bypass auth.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Load Fraunces, DM Sans, DM Mono via Google Fonts preconnect in app.html
- Define all design tokens in @theme block: neutrals, green/yellow/blue/
purple/orange scales, spacing (--space-1..20), radii, shadows, button base
- Note --green-dark as button background (--green fails WCAG AA with white)
- Add @types/node for Node fs/path usage in design-system tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
White on --green-dark (not --green) is the correct button background;
--green (#3D8C4A) gives only 4.16:1 which fails AA for normal-size text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>