Commit graph

4 commits

Author SHA1 Message Date
a37406532b fix(web): retire l'override cucumber-expressions, cassait le bundle navigateur
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.
2026-08-19 12:01:27 +02:00
650368daa9 fix(web): épingle un ancien set @cucumber/* pour débloquer le preprocessor
É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.
2026-08-19 11:53:45 +02:00
kyuno053
42d094764f
API: signup/login (profile creation + JWT auth) (#4)
* 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`.
2026-08-16 13:45:23 +02:00
kyuno053
746100e257
Scaffold generic pnpm monorepo (api + web + shared) (#1)
* 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.
2026-08-16 10:55:13 +02:00