batchCooking/apps/api/features/auth.feature
Nicolas e986edfd00 Add signup/login (profile creation + JWT auth)
API:
- POST /auth/signup — creates a house + user_profile (transactional),
  hashes the password with argon2, sets a JWT in an httpOnly cookie
- POST /auth/login — verifies credentials (generic 401 for both wrong
  email and wrong password, doesn't leak which), sets the cookie
- POST /auth/logout — clears the cookie
- GET /auth/me — current profile, behind requireAuth middleware
- requireAuth verifies the JWT and re-checks tokenVersion against the
  DB, so a stateless JWT can still be invalidated (password change /
  logout-everywhere, not built yet but the field is in place)

Schema: user_profiles gets password_hash + token_version (not in the
original spec doc — required for auth). New migration, with
COMMENT ON for the new columns per the established pattern.

Decisions from the auth planning discussion: JWT in httpOnly cookie
(not server-side sessions), first profile created also creates its
house, argon2 for hashing.

argon2 pinned to 0.31.2 (not ^, deliberately): 0.45.1 segfaults at
runtime on this Windows machine — reproduced consistently across bash
(sandboxed and unsandboxed) and PowerShell, while 0.31.2 works fine
with the same API. Documented in the README as a trap for future
upgrades, since `tsc`/`prisma generate` succeeding doesn't catch a
runtime native-binding crash.

Tests: Mocha (unit-style, apps/api/test/auth.test.ts) and a Cucumber
feature (apps/api/features/auth.feature) covering the full signup →
authenticated flow, duplicate email, wrong password. Both share
test-support/reset-db.ts (TRUNCATE ... CASCADE) to start each
test/scenario from a clean slate. Test-only argon2 cost parameters
(NODE_ENV=test) keep the suite fast — argon2's real cost is
deliberately expensive, which made hashing dozens of times per run
slow and occasionally timeout-flaky at default cost.

CI: added a Postgres service container to lint-and-test (previously
none — tests didn't touch a real DB), runs `prisma migrate deploy`
before the test steps.

Verified end-to-end manually against the dev server (curl): signup,
duplicate email (409), wrong password (401), valid login (200),
validation errors (400), /me with and without cookie, logout (204) —
all behave as intended. Full suite (lint, mocha, cucumber, build) run
multiple times locally with no flakiness after the timeout/cost fixes.
2026-08-16 13:06:31 +02:00

33 lines
1.6 KiB
Gherkin

Feature: Account creation and login
As a new user
I want to create a profile and log in
So that I can access my household's batch-cooking planning
Scenario: A visitor creates a new profile
When I sign up with the following details:
| firstName | Alice |
| lastName | Martin |
| email | alice@example.com |
| password | correct-horse-battery-staple |
Then the response status should be 201
And I am authenticated as "alice@example.com"
Scenario: A visitor cannot sign up twice with the same email
Given a profile already exists with email "alice@example.com"
When I sign up with the following details:
| firstName | Alice |
| lastName | Martin |
| email | alice@example.com |
| password | correct-horse-battery-staple |
Then the response status should be 409
Scenario: A registered user logs in with correct credentials
Given a profile already exists with email "alice@example.com" and password "correct-horse-battery-staple"
When I log in with email "alice@example.com" and password "correct-horse-battery-staple"
Then the response status should be 200
And I am authenticated as "alice@example.com"
Scenario: A registered user cannot log in with the wrong password
Given a profile already exists with email "alice@example.com" and password "correct-horse-battery-staple"
When I log in with email "alice@example.com" and password "wrong-password"
Then the response status should be 401