# seiche-server Backend Fastify 5 (TypeScript strict, Node 22 via `tsx`). Sert l'API `/api/*` et, en production, le front prébuildé (`SEICHE_PUBLIC_DIR`) sur le même port — zéro CORS, 1 conteneur. ## Scripts | Script | Rôle | |---|---| | `pnpm dev` | Serveur en watch sur `http://localhost:8787` (défauts config) | | `pnpm start` | Serveur en mode prod (idem, sans watch) | | `pnpm setup` | Crée le compte admin initial (idempotent ; `SEICHE_ADMIN_USERNAME` / `SEICHE_ADMIN_PASSWORD`, mdp ≥ 12 car.) | | `pnpm db:generate` | `drizzle-kit generate` — génère les migrations dans `drizzle/` | | `pnpm test` | Vitest (API injectée, SQLite `:memory:`) — 30 tests | | `pnpm typecheck` | `tsc --noEmit` | Les migrations sont **appliquées automatiquement au boot** (`migrate()` de Drizzle, dossier `drizzle/`). ## Structure ``` src/ ├── main.ts # boot : dataDir, DB + migrations, listen, shutdown propre ├── app.ts # buildApp (trustProxy, logger, plugins, routes) ├── config.ts # toutes les variables d'env (voir .env.example racine) ├── validation.ts # schémas Zod partagés ├── setup.ts # création idempotente du compte admin ├── auth/ # password (argon2id), session + CSRF, rate-limit ├── routes/ # auth, external, health ├── db/ # client libsql (WAL) + schema Drizzle ├── external/ # client du service REST externe (adaptateurs example/http) └── drizzle/ # migrations versionnées (drizzle/) ``` ## API | Route | Accès | Rôle | |---|---|---| | `GET /api/health` | public | healthcheck | | `POST /api/auth/login` | rate-limit | session httpOnly + cookie CSRF (double-submit) | | `POST /api/auth/logout` · `GET /api/auth/session` | session | révocation / état de la session | | `GET /api/external/health` · `GET /api/external/items` · `POST /api/external/items` | session | pont vers le service externe (adaptateurs `example` / `http`) | Erreurs : corps JSON `{ statusCode, error, message, code, ... }` (le code machine est stable, le message ne fuit jamais les détails internes). ## Tests ```bash pnpm test ``` Les tests injectent Fastify (`app.inject`) avec une base `:memory:` par worker (`tests/helpers.ts` : `makeConfig`, `openTestDb`, cookies) — pas de dépendance au réseau.