L'override précédent forçait @cucumber/cucumber-expressions à 10.0.0
(épinglé pour rester CommonJS, comme les autres) — mais ce paquet
n'est en réalité jamais require() directement côté Node (le seul
chemin qui a besoin d'un CJS synchrone) : il n'est utilisé que dans
`browser-runtime.js`/`registry.js` du preprocessor, tous les deux
uniquement chargés côté navigateur, où esbuild les bundle (pas de
souci ESM/CJS là — c'est une restriction du require() runtime de
Node, pas des bundlers).
Confirmé par l'échec CI : `cucumber-expressions@10.0.0` (contrairement
à sa version moderne) importe le module natif `util` de Node en
interne, qu'esbuild ne peut pas résoudre pour une cible navigateur
("The package 'util' wasn't found on the file system but is built
into node"). En le laissant résoudre vers sa version moderne (ESM,
pas de dépendance à `util`), plus besoin de l'épingler du tout.
Vérifié qu'aucun des paquets encore épinglés (gherkin, messages,
tag-expressions) n'importe `util` ou un autre built-in Node.
Épingle 6 dépendances transitives du preprocessor à leurs dernières
versions publiées encore en CommonJS (via pnpm.overrides, scopé à
"@badeball/cypress-cucumber-preprocessor>..." — n'affecte pas le
@cucumber/cucumber@13.2.1 utilisé côté apps/api) :
- @cucumber/gherkin@22.0.0, @cucumber/messages@17.1.1,
@cucumber/tag-expressions@4.1.0, @cucumber/cucumber-expressions@10.0.0,
@cucumber/ci-environment@8.0.1 : ces 5 étaient déjà tentées dans une
itération précédente — elles suffisaient à passer le require() du
preprocessor lui-même, mais pas celui d'un de ses propres bundled
dependencies.
- @cucumber/pretty-formatter@1.0.1 : la pièce manquante. Le blocage
précédent (`TypeError: Cannot read properties of undefined (reading
'BEFORE_TEST_RUN')`) venait de pretty-formatter@4.x, qui utilise
`messages.HookType` — absent de messages@17.1.1 (introduit en
amont dans une version ultérieure). pretty-formatter@1.0.1
n'utilise pas du tout `HookType` (vérifié : aucune occurrence dans
son code), donc reste compatible avec l'ancien messages.
Vérifié en local (le blocage GPU/Electron de cet environnement
n'empêche pas ça, qui se joue entièrement côté Node avant même le
lancement du navigateur) :
- `import { addCucumberPreprocessorPlugin }` charge sans ERR_REQUIRE_ESM
- `cypress run` progresse jusqu'au même crash GPU habituel (limitation
d'environnement déjà documentée dans le README, indépendante de ce
fix) — preuve que le chargement de la config passe désormais
intégralement
- Appel réel de `addCucumberPreprocessorPlugin(on, config)` avec un
contexte Cypress minimal : résout sans erreur, enregistre tous ses
event handlers (before:run, after:run, before:spec, after:spec,
after:screenshot, task)
Corrige ma conclusion précédente (voir l'historique de cette branche) —
je n'avais pas identifié pretty-formatter comme bloqueur restant,
juste testé messages/gherkin/tag-expressions et conclu trop vite à
l'incompatibilité totale.
* 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.
* Fix CI: generate Prisma Client via postinstall
CI failed with "@prisma/client did not initialize yet" — pnpm install
never ran `prisma generate`, and `prisma migrate deploy` (unlike
`migrate dev`) doesn't do it either. Worked locally only because prior
`prisma migrate dev` runs had already generated the client as a side
effect.
Adding a postinstall script fixes it for CI and for anyone cloning the
repo fresh and running plain `pnpm install`.
* Scaffold generic pnpm monorepo (api + web + shared)
Sets up the initial project infrastructure only, no business modules yet:
- apps/api: Express/TypeScript backend skeleton (healthcheck route, zod-validated
env config, error handling, Prisma initialized with no models yet, Postgres
as the target DB)
- apps/web: React/Vite/TypeScript frontend skeleton, Capacitor-ready for the
future mobile app
- packages/shared: empty placeholder for types/schemas shared between api and
web once the data model is defined
- Tooling: Biome (lint/format), Mocha+Chai+Supertest (api tests), Cypress
(web e2e smoke test), GitHub Actions CI (lint + test + build + e2e)
- docker-compose.yml for local Postgres
- README documents setup steps, including the Cypress binary caveat (pnpm
install doesn't always fetch the native binary — needs `cypress install`
run locally per machine)
Fixes along the way:
- apps/web/cypress.config.ts: disable GPU on browser launch for
headless/sandboxed environments
- apps/web/tsconfig.*: split into solution/app/node tsconfig files (standard
Vite pattern) — the previous single-file setup caused `tsc -b` to emit
compiled .js/.d.ts next to vite.config.ts and cypress.config.ts
* Remove hardcoded credentials from committed env/compose files
.env.example and apps/api/.env.example had a real usable default
credential pair (batchcooking/batchcooking) baked in, and
docker-compose.yml fell back to the same values via ${VAR:-default}
if .env was missing. Neither should ship a working credential:
- .env.example / apps/api/.env.example now use "changeme" placeholders
that must be edited before use.
- docker-compose.yml uses ${VAR:?...} instead of ${VAR:-default} for
POSTGRES_USER/PASSWORD/DB, so compose fails loudly if .env isn't set
up rather than silently falling back to a guessable credential.
Healthcheck reads the container's own env var ($$POSTGRES_USER)
instead of duplicating the value in the compose file.
- README updated to say .env.example must be edited, not just copied.
Verified: `docker compose config` fails with a clear message when
.env is absent, and resolves correctly once .env is filled in.
* Fix CI: remove pnpm version conflict with packageManager field
pnpm/action-setup@v4 errored with "Multiple versions of pnpm
specified" because the workflow pinned version: 10 while
package.json's packageManager field pins pnpm@10.12.4. The action
already reads packageManager automatically, so drop the redundant
version input.
* Fix CI: install Cypress binary explicitly before running e2e
Same root cause as the README caveat: pnpm install doesn't reliably
trigger Cypress's postinstall binary download, so `cypress run` failed
in CI with "The cypress npm package is installed, but the Cypress
binary is missing." Add an explicit `cypress install` step, and cache
~/.cache/Cypress keyed on the lockfile so subsequent runs don't
re-download it.
* Fix Cypress config loading: give the solution tsconfig a module system
apps/web/tsconfig.json (the tsc -b "solution" file) had no
compilerOptions, only files/references. Cypress's bundled ts-node
picks the nearest tsconfig.json to transpile cypress.config.ts, and
with no "module" specified it defaulted to CommonJS while
package.json declares "type": "module" — causing:
ReferenceError: exports is not defined in ES module scope
Adding module/moduleResolution to the solution config (harmless for
tsc -b itself, since it only builds the referenced projects) fixes
the mismatch. This regressed after the earlier fix for the stray
vite.config.js emission and was never re-verified against Cypress
until CI caught it.