# Backend — Risques & vigilance : Next.js

> Extrait de la base de connaissance Lead_tech. Voir `knowledge/backend/risques/README.md` pour l'index complet.

---

<a id="risque-prisma-init-module-build"></a>
## Prisma initialisé au chargement de module — casse le build Next.js

### Risques

- Un import global qui initialise Prisma immédiatement peut faire échouer la collecte de pages/routes au build si `DATABASE_URL` n'est pas disponible dans l'environnement de build

### Symptômes

- `PrismaClientInitializationError` ou `Error: Environment variable not found: DATABASE_URL` au `next build`
- L'app tourne en dev mais le build CI échoue

### Bonnes pratiques / mitigations

- Préférer une initialisation lazy-safe : retarder l'accès DB au moment de l'appel métier
- Retourner un proxy qui lève une erreur claire uniquement lors du premier accès réel à la DB
- Ne jamais instancier `new PrismaClient()` au top-level d'un module importé par Next.js

- Contexte technique : Next.js App Router / Prisma — app-template-resto 16-03-2026

---

<a id="risque-server-only-repositories-tests"></a>
## `server-only` dans les repositories — bloque les tests unitaires

### Risques

- `import "server-only"` empêche l'exécution des fichiers hors runtime Next.js
- Les tests Node.js échouent avec `Error: This module cannot be imported from a Client Component module`

### Symptômes

- Tests qui passent via le dev server mais échouent via `jest` en mode node
- Erreur au `require()` d'un repository depuis un test unitaire

### Bonnes pratiques / mitigations

- Ne mettre `server-only` que dans les fichiers qui utilisent des APIs Next.js runtime (`cookies()`, `headers()`, `redirect()`)
- **Ne pas** mettre `server-only` dans les repositories purs (qui n'appellent que Prisma)
- Alternative de secours : créer un stub `node_modules/server-only/index.js` no-op pour les tests

- Contexte technique : Next.js App Router / Jest — app-template-resto 16-03-2026

---

<a id="risque-redirect-boucle-infinie"></a>
## Redirect vers la page désactivée elle-même (boucle infinie feature flags)

### Risques

- Une page désactivée redirige vers elle-même via le fallback — boucle infinie silencieuse absorbée par Next.js mais UX cassée

### Symptômes

- Page `/` désactivée → redirect vers `buildLocalizedPath("home")` = `/` → boucle
- Next.js absorbe la boucle mais l'utilisateur voit un écran bloqué ou vide

### Bonnes pratiques / mitigations

```typescript
// Si la page est sa propre destination de fallback, ne pas rediriger
if (pageKey === "home") return null; // évite redirect home → home
return buildLocalizedPath(locale, "home");
```

- Règle : dans tout mécanisme de redirection sur page désactivée, toujours vérifier que `pageKey !== fallbackKey`
- Retourner `null` (accès non bloqué) plutôt que de boucler

- Contexte technique : Next.js App Router / feature flags tenant — app-template-resto 17-03-2026

---

<a id="risque-server-action-self-request"></a>
## Server Action : self-request / loopback HTTP vers sa propre API

### Risques

- Latence réseau inutile (aller-retour HTTP interne)
- Fragilité sur `APP_URL` en environnement Docker (loopback non résolu)
- Double authentification (cookies reconstitués manuellement)
- Surface d'attaque SSRF

### Symptômes

- `fetch(process.env.APP_URL + '/api/...')` dans une Server Action
- Reconstitution manuelle de cookies de session dans l'appel

### Bonnes pratiques / mitigations

- Une Server Action peut importer et appeler directement des modules marqués `server-only` sans `fetch` interne — les deux s'exécutent côté serveur.
- **Règle** : si tu te retrouves à reconstituer des cookies de session pour faire un `fetch` vers ta propre API depuis une Server Action, c'est le signal que l'appel doit être direct.

- Contexte technique : Next.js App Router / Server Actions — app-template-resto 31-03-2026

---

<a id="risque-exdev-atomic-write"></a>
## Écriture atomique (tmp + rename) : EXDEV si tmp sur device différent

### Risques

- `rename()` lève `EXDEV` si le fichier temporaire et la destination sont sur deux devices différents (cas courant Docker bind-mount).
- L'erreur survient uniquement en production (Docker) — invisible en dev local.

### Symptômes

- `Error: EXDEV: cross-device link not permitted, rename '/tmp/...' → '/data/...'`
- Upload de fichier fonctionnel en dev, cassé en production Docker

### Bonnes pratiques / mitigations

- Créer le fichier temporaire dans **le même répertoire** que la destination finale, pas dans `os.tmpdir()`.
- S'assurer que le répertoire cible existe avant l'écriture du fichier temporaire.
- **Règle** : `os.tmpdir()` est interdit pour les fichiers qui seront renommés vers un volume Docker bind-mounté.

- Contexte technique : Node.js / Docker / fichiers media — app-template-resto 31-03-2026

---

<a id="risque-csp-strict-routes-html-api"></a>
## CSP strict casse les routes HTML dans une API Next.js

### Risques

- Appliquer un CSP strict (`default-src 'self'`) via `headers()` dans `next.config.ts` sur toutes les routes `/api/*` casse les routes qui servent du HTML avec des dépendances externes (Swagger UI, pages de documentation, etc.)

### Symptômes

- La page HTML se charge mais reste blanche — les scripts et styles externes sont bloqués silencieusement par le navigateur

### Bonnes pratiques / mitigations

- Quand on ajoute des headers de sécurité via un pattern global, vérifier s'il existe des routes qui servent du HTML (pas uniquement du JSON)
- Si oui, ajouter une règle dédiée plus spécifique **en premier** dans le tableau `headers()` (Next.js matche dans l'ordre de déclaration) avec un CSP adapté
- Factoriser les headers communs dans une constante partagée

- Contexte technique : Next.js / CSP — RL799_V2 08-04-2026

---

<a id="risque-middleware-faux-argument-edge"></a>
## Middleware Next.js — faux argument "Edge Runtime incompatible" pour éviter les imports

### Risques

- Dupliquer la logique métier dans `middleware.ts` au lieu d'importer depuis `src/lib/` sous prétexte que "Edge Runtime ne supporte pas les imports cross-boundary"
- C'est faux pour les modules purs (pas de `fs`, `child_process`, `crypto` Node-only, etc.)

### Symptômes

- Logique dupliquée entre middleware et utilitaires, dérive garantie à la prochaine modification
- Commentaire dans le code justifiant la duplication par une incompatibilité Edge non vérifiée

### Bonnes pratiques / mitigations

- Le middleware Next.js peut importer n'importe quel module local tant que celui-ci n'utilise que des API compatibles Edge (Web APIs, `process.env`, opérations JS pures)
- Factoriser la logique partagée dans un module commun et l'importer depuis le middleware
- **Signal review** : logique dupliquée dans `middleware.ts` avec un commentaire "Edge incompatible"

- Contexte technique : Next.js / middleware — RL799_V2 08-04-2026

---

<a id="risque-app-router-private-folders"></a>
## App Router — dossiers `_*` exclus silencieusement du routing

### Risques

- Tout segment d'URL préfixé par `_` (ex : `_e2e`, `_helpers`, `__internal`) est traité par Next.js App Router comme un *private folder* et **exclu silencieusement du routing**
- Le `route.ts` ou `page.tsx` existe sur le filesystem, le typecheck passe, mais l'URL retourne 404
- Aucune erreur au boot, aucun warning

### Symptômes

- "Ma route existe pourtant je vois le fichier" — `apps/api/src/app/api/__e2e/visitor-token/route.ts` qui retourne 404
- Temps de debug perdu à chercher une cause obscure

### Bonnes pratiques / mitigations

- Ne **jamais** préfixer un segment de route par `_` ou `__` même pour signaler une intention "interne / e2e / debug"
- Utiliser des noms explicites : `/api/e2e/`, `/api/internal/`, `/api/dev/` (sans underscore initial)
- Pour gater l'accès en prod : check `process.env` au début du handler (`if (process.env.E2E !== '1') return 404`)
- Référence : Next.js docs — Project Structure → Private folders. Convention héritée de l'écosystème React/Webpack pour exclure les dossiers de la résolution

- Contexte technique : Next.js App Router — RL799_V2 30-04-2026
