HouseholdSetupForm.test.ts: explain that touched+empty drives the $derived
error, not a submit event on the disabled button.
page.server.test.ts: remove unused response key from mockSuccess() —
household creation doesn't set a session cookie.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fails fast before the API call with a clear German error message.
Tests boundary: 100 chars accepted, 101 rejected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
text-[18px] md:text-[28px] matches auth form pattern.
font-medium (500) replaces font-semibold (600) per design system rules.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
font-['var(--font-display)'] → font-[var(--font-display)] so Fraunces
display font is applied correctly to the h1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace getByText with getByRole(heading) in page test to disambiguate
the duplicate "Haushalt benennen" text between sidebar and form.
Revert defaultIgnore change in test-setup.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 comment to SecurityConfig explaining why CSRF is disabled
- Add SecurityContextHolder.clearContext() to logout for clean thread state
- Add Javadoc on authenticateInSession() explaining manual session setup
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>