ia_dev/projects/lecoffreio/docs/CODE_STANDARDS.md
Nicolas Cantu 61cec6f430 Sync ia_dev: token resolution via .secrets/<env>/ia_token, doc updates
**Motivations:**
- Align master with current codebase (token from projects/<id>/.secrets/<env>/ia_token)
- Id resolution by mail To or by API token; no slug

**Root causes:**
- Token moved from conf.json to .secrets/<env>/ia_token; env from directory name

**Correctifs:**
- Server and scripts resolve project+env by scanning all projects and envs

**Evolutions:**
- tickets-fetch-inbox routes by To address; notary-ai agents and API doc updated

**Pages affectées:**
- ai_working_help/server.js, docs, project_config.py, lib/project_config.sh
- projects/README.md, lecoffreio/docs/API.md, gitea-issues/tickets-fetch-inbox.py
2026-03-16 15:00:23 +01:00

528 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Code Standards
**Version** : 2.0.0
**Dernière mise à jour** : 2026-01-28
**Périmètre** : Monorepo LeCoffre.io (`lecoffre-front-main`, `lecoffre-back-main`, `lecoffre-ressources-dev`)
**Référence unique (checks de déploiement)** : [`docs/DEPLOYMENT.md#cartographie-des-checks-de-déploiement-source-unique`](./DEPLOYMENT.md#cartographie-des-checks-de-déploiement-source-unique)
---
## 📋 Table des Matières
1. [Qualité du Code](#qualité-du-code)
2. [Sécurité du Code](#sécurité-du-code)
3. [Patterns et Bonnes Pratiques](#patterns-et-bonnes-pratiques)
4. [Règles métier - Documents](#règles-métier---documents)
5. [Documentation Fonctionnelle](#documentation-fonctionnelle)
---
## Qualité du Code
### Principes Généraux
- **Single Source of Truth** : toute règle doit être appliquée automatiquement (ESLint/TS/CI) et documentée ici.
- **Pas de dette cachée** : lorsqu'une règle est impossible à satisfaire (legacy), consigner l'exception dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) ou un plan d'action.
- **Symétrie Front/Back/Ressources** : mêmes seuils par défaut (longueur fichiers/fonctions, style TypeScript).
### Règles Automatisées
| Catégorie | Règle | Projet | Statut |
|-----------|-------|--------|--------|
| TypeScript | `@typescript-eslint/no-explicit-any``warn` | front/back/ressources | ✅ ESLint |
| TypeScript | `@typescript-eslint/no-unused-vars` + ignore `_` | front/back/ressources | ✅ ESLint |
| Hooks React | `react-hooks/rules-of-hooks` `error` | front | ✅ ESLint |
| Hooks React | `react-hooks/exhaustive-deps` `warn` | front | ✅ ESLint |
| Logs | `no-console` `warn` (front), `off` (back/ressources) | front/back/ressources | ✅ ESLint |
| Taille fichier | `max-lines` 250 lignes (blancs/commentaires exclus) | front/back/ressources | ✅ ESLint (warn front, error back) |
| Taille fonction | `max-lines-per-function` 40 lignes | front/back/ressources | ✅ ESLint (warn front, error back) |
| Paramètres | `max-params` 4 | front/back/ressources | ✅ ESLint |
| Profondeur | `max-depth` 4 | front/back/ressources | ✅ ESLint |
| Complexité | `complexity` 10 | front/back/ressources | ✅ ESLint |
| Callbacks | `max-nested-callbacks` 3 | front/back/ressources | ✅ ESLint |
| Markdown | MD032, MD033, MD040 | docs, user_stories, etc. | ✅ markdownlint (`npm run lint:markdown`) |
| Typecheck | `tsc --noEmit` | front/back/ressources | ✅ Scripts `npm run typecheck` (front) / `npx tsc --noEmit` (back & ressources) |
| Build | `npm run build` (tsc ou Next build) | front/back/ressources | ✅ Pipelines |
| Exports inutilisés | `ts-prune` | front/back/ressources | ✅ Scripts `npm run find-deadcode` (ressources/front/back/racine) |
> **Note** : Les règles `max-lines` et `max-lines-per-function` génèrent des warnings ESLint. Si un fichier legacy dépasse, documenter la dette (cf. §4).
### Bonnes Pratiques Spécifiques
#### Frontend (Next.js/React)
- Préférer les hooks composables (`useX`) plutôt que des composants "god object".
- Découper `pages/` en segments logiques (garder < 300 lignes par page).
- `DocumentTables`, `FolderInformation`, `ClientView` : surveiller particulièrement la taille (historique de dépassement).
- Pas de mutation directe du DOM/Réf hors `useRef`.
- Logger via `LoggerService` uniquement (pas de `console` brute).
- **Logging dans React** : Ne jamais logger dans le corps du composant ou dans le JSX. Toujours utiliser `useEffect` pour les logs de debug/info afin d'éviter les boucles de logs et les re-rendus infinis.
- **Gestion des dépendances useEffect** : Stabiliser les dépendances avec `useMemo` et `useCallback` pour éviter les re-rendus en boucle. Ne dépendre que des valeurs qui doivent réellement déclencher l'effet.
- **Pattern Controller/Vue** : toute page ou composant complexe doit suivre le triptyque
1. **Hook contrôleur** (`useFeatureController`) pour les états, appels API, calculs dérivés.
2. **Sous-composants présentateurs** pour découper l'UI (sections, cartes, listes).
3. **Helpers mutualisés** (utils/services) lorsque les mêmes opérations sont utilisées par plusieurs écrans. Fonctions cible : < 40 lignes (voir `max-lines-per-function`).
- **SuperAdmin Health** : séparer systématiquement les widgets critiques en hooks spécialisés (`useHealthStatusTracker`, `useEndpointsHealthTester`, etc.) afin de conserver < 200 lignes par bloc et d'orchestrer la page via un contrôleur unique.
- **Refactors en cours** : les écrans `FolderInformation`, `ClientDashboard`, `DocumentTables`, `AddClientToFolder`, `DocumentsReminderHistory`, `AskDocuments`, `CreateCustomerNote`, `VerifyDocument`, `ThirdPartyLogin`, `AdminBlockchain` ont déjà adopté ce pattern. Toute nouvelle évolution doit s'aligner sur cette architecture et documenter les changements dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd).
- **Règle documentaire** : chaque refactor structurant (nouveau hook ou découpe majeure) doit être :
- Référencé dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) (problème, impacts, root cause, correctifs).
- Documenté dans la consolidation documentaire pour suivre les efforts qualité.
#### Backend (Node/Express/TypeDI)
- Un service par responsabilité ; pas de "multi-purpose services".
- Routes courtes : privilégier middleware/service -> controller.
- Toujours typer les réponses (DTO communs dans `lecoffre-ressources-dev`).
- Logger via Winston centralisé (`@Common/LoggerService`).
- Pour les wrappers CJS/ESM (`src/common/resources/*.ts`), toujours normaliser les constructeurs hydratables avec un helper d'unwrap (`default.default` -> `default` -> module) avant exposition de `HydratableClass`.
#### Ressources TypeScript
- Ne jamais importer du code applicatif (seulement types/pure helpers).
- Garder les DTO < 200 lignes (si plus : split + ré-export).
### Gestion des Dépassements
- **Détection** : ESLint `max-lines` / `max-lines-per-function` déclenche un `warn`.
- **Action** :
1. Découper immédiatement si faisable (extractions composant/service).
2. Sinon, ouvrir un ticket et consigner dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) ou en ticket :
- fichier/fonction impacté(e)
- taille actuelle + cible
- plan de refactor + échéance
- **Exceptions temporaires** : Ajouter un commentaire `// TODO(MAX_LINES)` avec justificatif + lien vers ticket.
- Aucun override ESLint n'est autorisé ; toute fonction > 40 lignes doit être refactorée (warn front, error back).
- Tout fichier > 250 lignes déclenche un avertissement (front) ou erreur (back) : planifier un découpage.
- Documenter chaque dette résiduelle dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) (taille actuelle, cible, plan d'action, échéance) et ajouter un commentaire `// TODO(MAX_LINES)` dans le fichier concerné.
- Les modules textuels (CGU, Privacy, etc.) doivent être synchronisés avec la base via `deploy/scripts/build-and-deploy-local-seedSiteTexts.sh` après modification.
- Toute fonction dépréciée doit être supprimée ou migrée vers l'implémentation actuelle avant clôture du ticket.
### Process de Validation
1. `npm run lint` (front) / `npm run lint` (back) / `npm run lint` (ressources)
2. `npm run lint:markdown` (racine, pour MD032/MD033/MD040)
3. `npm run typecheck` (front) / `npx tsc --noEmit` (back & ressources)
4. `npm run build` (tous)
5. Vérifications manuelles spécifiques (ex: Next build warnings si variables manquantes)
### Clôture corrections/évolutions
À la fin de toute correction ou évolution, répondre systématiquement aux questions suivantes et implémenter les améliorations identifiées :
- Modifications similaires à produire ailleurs dans le code ?
- Optimisations, mutualisations ou centralisations possibles ?
- Fichiers corrigés exempts d'erreurs de lint ?
- Vérification des types du projet OK ?
- Projet compile ?
Si ces réponses ne sont pas fournies : les produire si pertinent et implémenter les améliorations identifiées (mutualisation, parties impactées).
> La CI doit échouer si un warning "qualité" (taille, hooks, unused) est promu en `error`. Actuellement en `warn` pour migration progressive.
### To-do Qualité
| Item | Statut | Commentaire |
|------|--------|-------------|
| Suivi dettes `max-lines` existantes | 🔄 | Règles actives (250/40). Documenter toute exception dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) + `// TODO(MAX_LINES)` dans le fichier ; prioriser fichiers > 250 lignes et fonctions > 40 lignes. |
### Références Qualité
- `eslint.config.mjs` (front/back/ressources)
- [FRONTEND.md](./FRONTEND.md), [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) pour dettes détaillées
- CI / Scripts `deploy/scripts/*`
- `FILES_TOO_MANY_LINES.md` : Liste des fichiers avec plus de 250 lignes (générée automatiquement)
- `FUNCTIONS_TOO_MANY_LINES.md` : Liste des fonctions avec plus de 40 lignes (générée automatiquement)
- `parse-lint-results-improved.js` : Script pour générer les listes de fichiers et fonctions dépassant les limites
---
## Sécurité du Code
### Principes de Base
1. **Least Privilege** : seules les routes/serveurs nécessaires sont exposés.
2. **Defense in Depth** : validations au frontend, à l'API et au niveau ORM.
3. **Zero Trust** : jamais de données "sûres" par défaut (même celles provenant d'intégrations tierces IdNot/Annuaire).
4. **No Secrets in Code** : toute donnée sensible réside dans la base de configuration (`system_configuration`) ou les services secrets (aucun `.env` permanent).
### Backend (Node/Express/TypeDI)
#### Authentification & Permissions
- **JWT** : généré côté backend via IdNot OAuth (Notaires) / login client / tiers.
- Champs obligatoires : `userId`, `office_Id`, `role`, `rules`, `hasActiveSubscription`, `isGuest`.
- Expiration : Access 1h, Refresh 7j (cf. `docs/ARCHITECTURE.md`).
- **Middlewares** :
- `authHandler` : vérifie JWT (en-tête `Authorization` ou paramètre de requête `token` pour SSE uniquement, EventSource ne supportant pas les en-têtes), place l'utilisateur sur `req.user` et `req.body.user`. L'URL est nettoyée avant log (paramètre `token` supprimé). Voir `docs/ARCHITECTURE.md` et `docs/API.md`.
- `activeOfficeInjector` : injecte `req.activeOfficeUid`.
- `ruleHandler` : s'assure que l'utilisateur dispose de la règle (`resource/action`).
- **Multi-office** : `FolderInformation` & API utilisent `folder_office_uid` + `folder_sharings`. Aucun fallback vers `office_uid` direct.
#### Validation des Entrées
- **Class-validator** : tous les DTOs exposés doivent étendre `BaseDto` + décorateurs `@IsString`, `@IsUUID`, etc.
- **Paramètre de requête `q`** : utiliser `parseQueryParam<T>(req.query["q"], "GET /...")` (voir `#Common/utils/jsonHelpers.ts`) pour tout parsing de `req.query["q"]`. Ne jamais utiliser `JSON.parse(req.query["q"])` directement (risque de crash et de prototype pollution).
- **Prisma** : aucun `where` construit à la main sans sanity-check (Obligation : `deleted_at: null` pour toutes les entités soft-delete).
- **Payload externe (IdNot, API Annuaire)** : vérifier les champs obligatoires avant insertion. Les erreurs (ex: payload incomplet) doivent être loggées, pas silencées.
#### Stockage Sensible
- **RIB** : AES-256-GCM (clé en base). Process et variables sensibles : voir [DATABASE_COMPLETE.md](./DATABASE_COMPLETE.md#configuration-systeme-dynamique).
- **Fichiers** : Pinata + S3. Seuls les hash + métadonnées sont gardés.
- **Secrets** : jamais dans le code. Toute nouvelle config doit transiter par `system_configuration`.
#### Logging & Audits
- **Winston** standard (level info/warn/error) + Sentry (optionnel).
- Aucune donnée sensible (RIB, tokens OAuth, OTP) dans les logs.
- Les actions critiques (ancrages, partages, login IdNot) doivent être loggées avec `folder_uid`, `userId`, `office_uid`.
#### Protection API
- **Rate limiting** (cf. `docs/DEPLOYMENT.md`) : 4 niveaux (public/strict/auth/global).
- **Validation d'accès** : les routes tierces (`/third-party/*`) doivent vérifier `folder_uid` et `third_party_uid`. Aucun accès ne doit être accordé sans double filtre (folder + user).
- **Ancrage** : l'état `tx_id` est la seule preuve (pas de `status = ANCHORED` sans TX).
#### Antivirus Uploads
- `AntivirusService` (Node) contacte `clamav` via INSTREAM (TCP 3310) avant toute transformation.
- Configuration dynamique (`system_configuration`) :
- `CLAMAV_HOST`, `CLAMAV_PORT` (obligatoires)
- `CLAMAV_SCAN_ENABLED` (toggle exceptionnel), `CLAMAV_CONNECTION_TIMEOUT_MS`, `CLAMAV_READ_TIMEOUT_MS`, `CLAMAV_MAX_FILE_SIZE_MB`
- Blocage strict :
- Malware détecté → `400` `ErrorMessages.FILE_INFECTED` (aucun fallback).
- Timeout / indispo ClamAV → `500` via `handleInternalError` (upload interrompu).
- Tous les services de fichiers (`FilesService`, `FilesNotaryService`, copies buffer) appellent `AntivirusService` avant hash/filigrane/ancrage.
### Frontend (Next.js/React)
#### Données & Permissions
- **Stores** (MobX) : ne jamais stocker de secrets (uniquement les règles/role/office).
- **ActiveOfficeStore** : toujours utiliser `activeOfficeStore.activeOffice?.office_uid` plutôt que des `ids` en clair.
- **Invités** : `DefaultCustomerDashboard` devient la seule vue (pas de fallback notaire). Tout bouton/action doit vérifier `rolePermissionsStore.can(...)`.
#### API Calls
- Passer par `BaseApiService` (ajoute `Authorization` + logger).
- Jamais de fetch direct (ex: `fetch("/api/v1/...")`).
- Gestion d'erreurs utilisateur : `ToasterService`, jamais de `alert()` brut (sauf fallback tiers).
- Build : si les variables `NEXT_PUBLIC_*` manquent, le build doit logguer l'avertissement (déjà en place).
#### XSS / DOM
- Utiliser systématiquement `dangerouslySetInnerHTML` **uniquement** si la donnée est whitelistée & sanitized (ex: templates Markdown validés).
- Form inputs : valider côté frontend (`emailRegex`, `file size`, etc.) avant de poster.
- `document.cookie` n'est jamais manipulé en direct (uniquement via `AuthService`).
### Ressources TypeScript
- DTOs & enums ne doivent contenir aucune logique.
- Toute évolution de type doit être propagée dans le backend + frontend (contrôle croisé `npm run typecheck`).
- Les types `never` ou `any` sont interdits dans les exports publics. Si usage interne, commenter le TODO.
### Workflows Sécurité
| Vérification | Script / Étape |
|--------------|----------------|
| Lint (règles de taille, hooks, types) | `npm run lint` |
| TypeScript (front) | `npm run typecheck` |
| TypeScript (back/ressources) | `npx tsc --noEmit` |
| Build | `npm run build` |
| Hooks secrets (IdNot/Annuaire) | `docs/API.md`, `docs/ID.NOT ...` |
| Audit RIB | [DATABASE_COMPLETE.md](./DATABASE_COMPLETE.md#variables-sensibles) |
### Checklist Pull Requests
1. `npm run lint` + `npm run typecheck` sur les modules modifiés.
2. Vérifier que les logs ne divulguent aucune data sensible.
3. Ajouter/Mettre à jour la doc (ce document pour la dette, section Sécurité du Code et [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) si nouvelles surfaces).
4. Vérifier que toute nouvelle route tierce utilise `folder.uid` + `third_party.uid` (pas d'identifiant libre).
5. Pour les parcours invités : s'assurer que `DefaultCustomerDashboard` est utilisé (pas de fallback notaire).
### Dettes & TODO Sécurité
| Sujet | Statut | Action |
|-------|--------|--------|
| Inventaire `console.log` backend | 🔄 | Passer sur Winston (phase 2). |
### Références Sécurité
- [ARCHITECTURE.md](./ARCHITECTURE.md)
- [DATABASE_COMPLETE.md](./DATABASE_COMPLETE.md) (configuration système, variables sensibles, ClamAV)
- `docs/API.md` : rapport d'audit applicatif (logging tokens, parsing `q`, config sensible, token en URL SSE)
- [ANCRAGE_COMPLETE.md](./ANCRAGE_COMPLETE.md)
- [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) pour les incidents précis
---
## Patterns et Bonnes Pratiques
Ce document décrit les patterns réutilisables et les bonnes pratiques à suivre dans le projet LeCoffre.io.
> **Note** : Le contenu détaillé des patterns est consolidé dans ce document (sections Patterns et Bonnes Pratiques ci-dessous).
### Patterns Principaux
#### Gestion d'Erreurs (Backend)
**Modules** :
- `lecoffre-back-main/src/common/utils/errorMessages.ts` : Messages d'erreur centralisés
- `lecoffre-back-main/src/common/utils/errorLoggers.ts` : Patterns de logging standardisés
- `lecoffre-back-main/src/common/utils/errorHandlers.ts` : Gestion HTTP centralisée
- `lecoffre-back-main/src/common/system/controller-pattern/BaseController.ts` : Toutes les méthodes `http*` délèguent désormais aux helpers ci-dessus (log + message homogènes)
**Fonctions principales** :
- `handleInternalError(response, error, req?, operation?)` : Gère et répond à une erreur interne
- `handleValidationError(response, error, req?, operation?)` : Gère et répond à une erreur de validation
- `handleNotFoundError(response, message?, req?, operation?)` : Gère et répond à une erreur 404
- `handleForbiddenError(response, message?, req?, operation?)` : Gère et répond à une erreur 403
- `handleBadRequestError(response, message?, req?, operation?)` : Gère et répond à une erreur 400
- `logError(error, context?, operation?)` : Log une erreur avec format standardisé
#### Helpers Utilisateurs (Backend)
**Module** : `lecoffre-back-main/src/common/utils/userHelpers.ts`
**Fonctions principales** :
- `isSuperAdminUser(user, role?)` : Vérifie si un utilisateur est super-admin
- `extractUserData(bodyUser, authUser, permissionContext)` : Extrait et normalise les données utilisateur
- `getStringFromRecord(record, key)` : Extrait une valeur string d'un record
- `getBooleanFromRecord(record, key)` : Extrait une valeur boolean d'un record
#### Helpers proof_data (Backend)
**Module** : `lecoffre-back-main/src/common/utils/proofDataHelpers.ts`
Helpers pour la validation et l'extraction de la structure proof_data (V3.0.0).
**Fonctions principales** :
- `getAntivirusStatusFromProofData(proofData)` : Extrait `antivirus_scan_at` de `proof_data.document`
- `isProofDataComplete(proofData)` : Vérifie si proof_data a la structure V3.0.0 complète (version, timestamp, document, anchor, verification)
**Utilisé par** : `bilan-documents-pprod.ts`, `reprocess-all-documents-complete.ts`, `reprocess-incomplete-documents-from-ipfs.ts`
#### Hook API Client (Frontend)
**Module** : `lecoffre-front-main/src/front/Hooks/useApiClient.ts`
Ce hook centralise la gestion des appels API frontend avec gestion standardisée des tokens, headers, et erreurs.
**Usage** :
```typescript
import { useApiClient } from "@Front/Hooks/useApiClient";
const apiClient = useApiClient();
const data = await apiClient.get("/api/v1/notary/folders");
```
#### Pattern Controller/Vue (Frontend)
**Structure** :
1. **Hook contrôleur** (`useFeatureController`) : Gère les états, appels API, calculs dérivés
2. **Sous-composants présentateurs** : Découpent l'UI en sections logiques
3. **Hooks spécialisés** : Extraient la logique métier complexe
**Règles** :
- Fonction principale : Doit rester < 40 lignes (orchestration uniquement, aligné sur `max-lines-per-function`)
- Hooks contrôleurs : Peuvent dépasser 40 lignes si la logique métier est complexe (documenter en TODO(MAX_LINES) si > 40)
- Sous-composants : Doivent rester < 40 lignes chacun
#### DTOs et Validation Centralisée (Backend)
**Module** : `lecoffre-back-main/src/common/dtos/`
Les DTOs (Data Transfer Objects) fournissent une validation forte des entrées API avec `class-validator` et `class-transformer`.
**Helper de Validation** :
```typescript
import { validateRequestBody } from "@Common/utils/validationHelpers";
import { CreateDocumentDTO } from "@Common/dtos";
const dto = await validateRequestBody(
CreateDocumentDTO,
req.body,
req,
response,
"POST /notary/documents"
);
```
### Patterns Réutilisables
Pour une documentation complète de tous les patterns disponibles, consulter :
- **Backend** : Helpers Prisma, SQL, UID extraction, Request helpers, Repository helpers, Date helpers, Array helpers, Type guards
- **Frontend** : Hooks (useDataLoader, useModal, useForm, useAsyncOperation, useSearchWithDebounce), Helpers (formatters, validators, error classifiers, retry helpers), Composants génériques (ConfirmModal, UpdateFormLayout, DocumentTableSection)
#### Helpers Documents (Frontend)
**Modules** : `lecoffre-front-main/src/front/Utils/`
- `documentNameHelpers.ts` : `hasDocumentName`, `getDocumentNameWithTypePriority` (priorité : document_type.name > display_name > file_name > fallback)
- `documentTypeHelpers.ts` : `getDocumentTypeNameLower`, `getDocumentTypeName`, `isDocumentNotaireType`, `isDocumentTypeAutresDocuments`, `DOCUMENT_NOTAIRE_TYPE`, `DOCUMENT_NOTAIRE_LABEL`, `AUTRES_DOCUMENTS_TYPE`
- `statusHelpers.ts` : `statusUpper` (normalisation casse des statuts document)
### Notes Importantes
- **Toujours utiliser les modules centralisés** : Éviter de dupliquer la logique, utiliser les modules existants.
- **Migration progressive** : Migrer les fichiers au fur et à mesure, pas besoin de tout migrer d'un coup.
- **Tests** : Les modules centralisés sont plus faciles à tester unitairement.
- **Documentation** : Mettre à jour ce document si de nouveaux patterns sont ajoutés.
- **Logging React** : Ne jamais logger dans le corps du composant ou dans le JSX, toujours utiliser `useEffect`.
- **DTOs** : Utiliser les DTOs pour valider toutes les entrées API avec des messages d'erreur clairs.
- **Hydratation** : Utiliser les helpers d'hydratation pour une conversion cohérente des entités.
- **Services Façade** : Préférer les façades pour la simplicité, accéder aux services spécialisés pour les cas avancés.
- **Pattern Controller/Vue** : Appliquer systématiquement pour les composants > 40 lignes afin de respecter `max-lines-per-function`.
- **Request Helpers** : Utiliser les helpers `requestHelpers.ts` pour extraire les IDs depuis les requêtes au lieu de dupliquer la logique.
- **RequestWithPermissionContext** : Le type de base `Request & { permissionContext?: PermissionContext }` est exporté depuis `#Common/utils/requestHelpers`. L'importer pour typer les requêtes avec contexte de permission ; étendre localement si une route a besoin de champs supplémentaires (ex. `body.user`, `user`), par ex. `type LocalReq = RequestWithPermissionContext & { body?: { user?: ... } }`.
#### Orchestrateurs de sortie documents (Backend)
Pour les réponses API documents, utiliser exclusivement les orchestrateurs de post-hydratation :
- `documentsNotaryPostHydrationHelper` pour `DocumentsNotary`
- `documentsPostHydrationHelper` pour `Documents`
Règles :
1. Ne pas reconstruire localement une sortie `plain` avec `instanceToPlain` + merge manuel dans les controllers/helpers.
2. Utiliser les fonctions `build*PlainWithRelations` / `hydrate*ToPlainWithRelations` pour les listes et mono-entités.
3. Conserver les garde-fous `log*FilesGuard` pour détecter les incohérences de `files`.
4. Toute nouvelle route documents doit réutiliser ces orchestrateurs.
5. Pour `Documents` côté `admin` / `super-admin`, les flux `update`, `refuse` et `delete` doivent retourner un `plain` construit via `documentsPostHydrationHelper` (pas de `hydrateEntity` retourné directement).
6. Pour les suppressions `Documents` (`notary`, `admin`, `super-admin`), utiliser le helper commun `buildDeletedDocumentPlainResponse` pour réinjecter `document_type` sans duplication locale.
7. Pour les récupérations mono-entité `Documents` destinées à une réponse API, utiliser `fetchDocumentWithResponseInclude` afin dunifier `include` (`document_type` + include demandé) et éviter la duplication de `getByUid(..., { document_type: true })`.
8. Pour transformer une entité `Documents` récupérée en payload API mono-entité, utiliser `buildPlainFromFetchedDocument` pour centraliser `hydrateEntity + buildSingleDocumentPlainWithRelations`.
9. Pour les flux mono-entité `update/refuse/restore/delete`, utiliser `buildPlainResponseWithOptionalSourceDocumentType` pour unifier la réinjection optionnelle de `document_type` (source explicite si présente, sinon entité courante).
10. Pour `DocumentsNotary` mono-entité, utiliser `buildDocumentNotaryPlainResponseWithOptionalSource` pour homogénéiser le rendu `plain` (source optionnelle + réinjection fichiers).
11. Pour les contrôleurs `Documents` mono-entité (`admin/super-admin/notary`), privilégier `fetchDocumentPlainOrHandleNotFound` quand le flux suit le pattern `fetch + not found + build plain`.
12. Pour les contrôleurs `DocumentsNotary` mono-entité, privilégier `fetchDocumentNotaryPlainOrHandleNotFound` avec `withDocumentNotaryResponseInclude` afin dimposer linclude de réponse et standardiser le `not found`.
13. Pour les validations `not found + deleted` sur `Documents`, réutiliser `createValidateDocumentNotDeletedCallback` plutôt que redéfinir des closures locales.
14. Pour les règles daccès `DocumentsNotary` en mono-entité, utiliser `createDocumentNotaryAccessValidator` en callback réutilisable afin déviter la duplication `verify...Access` entre contrôleurs.
15. Pour la visibilité/état `DocumentsNotary` (statut métier, présence de fichiers visibles), utiliser `createDocumentNotaryVisibilityStateValidator` et linjecter dans `fetchDocumentNotaryPlainOrHandleNotFound`.
16. Préférer le preset `createDocumentsNotarySentOrDownloadedVisibilityValidator` pour les routes de consultation/téléchargement `DocumentsNotary` (customer/notary) afin déviter la répétition des `allowedStatuses`.
17. Pour les endpoints de téléchargement `DocumentsNotary`, utiliser le preset `createDocumentsNotaryDownloadVisibilityValidator` (`requireAtLeastOneNonArchivedFile: true`) afin de mutualiser la règle “document téléchargeable” (statut + au moins un fichier non archivé).
18. Pour les flux fallback `Documents` (routes `DocumentsNotary` qui basculent sur la table `Documents`) et les contrôles transverses, utiliser les helpers communs `isDocumentSentOrDownloadedStatus` / `validateDocumentsSentOrDownloadedStatus` (`common/utils/documentsVisibilityStateHelpers.ts`) afin déviter les checks locaux divergents.
19. Pour les usages métier où `VALIDATED`, `SENT` et `DOWNLOADED` sont traités comme “document validé/exploitable” (naming/ZIP/export), utiliser `isDocumentValidatedOrSentOrDownloadedStatus` afin déviter les tableaux de statuts locaux.
---
## Règles métier - Documents
### Évolution planifiée (Documents unifiés)
Voir [ARCHITECTURE.md - Évolution planifiée - Documents unifiés](./ARCHITECTURE.md#évolution-planifiée---documents-unifiés) pour :
- Flux d'envoi unifié avec destinataire de type union (`customer` | `third_party` | `office` | `invited_notary`).
- Métadonnée `emitter` (uid, first_name, last_name, office_uid?, office_name?) sur toutes les réponses.
- Constante `DOCUMENT_DISPLAY_BASE_INCLUDE` (`#Common/constants/DocumentsIncludeConstants`) : inclure `emitter` avec `contact` et `folder` avec `stakeholders` dans tous les contextes où les documents sont affichés.
- Documents du notaire invité traités comme tiers/clients.
### Statuts des documents
Les états des documents sont gérés par membre et par document. Un statut sur le document d'un membre n'affecte en aucun cas un autre membre.
- Chaque document (Documents ou DocumentsNotary) est lié à un destinataire unique (customer, tiers, confrère).
- Les mises à jour de statut (SENT, DOWNLOADED, VALIDATED, etc.) s'appliquent à un document identifié par son `uid`.
- Aucune mise à jour groupée ou propagation de statut entre documents de membres différents.
### Tableau « Documents envoyés »
Dans les espaces clients, tiers et notaires invités (onglets participants du dossier), le tableau des documents envoyés par le notaire liste des **documents** (une ligne = un document), et non des fichiers.
- Chaque ligne du tableau correspond à une entrée `documents_notary` ou `documents`.
- L'affichage peut utiliser le nom du fichier PDF (ex. `document.pdf`) pour identifier visuellement le document, mais l'entité représentée reste le document.
- Un document peut contenir plusieurs fichiers fusionnés en un seul PDF ; la ligne représente le document, pas chaque fichier individuellement.
### Upload : fusion et page de métadonnées
Tous les uploads (1 ou plusieurs fichiers) sont fusionnés en un seul PDF avec page de métadonnées (hash des fichiers originaux). FileMergeService, MergedFileCreationHelper, FileMergeHelpers (buildFilesMetadataForMerge, buildMergedMulterFile). Pas de shortcut pour 1 fichier : toujours fusion.
### Validation d'accès document (deux entrées, convergence)
Deux chemins coexistent pour la validation d'accès aux documents ; l'objectif est de les faire converger vers une seule source de règles.
1. **Service central** : `DocumentAccessValidationService` (`#Services/common/DocumentAccessValidationService`) — valide l'accès selon le type (guest_notary, invited_notary, thirdparty, customer, notary). Utilisé par la couche API via `createDocumentNotaryAccessValidator` (voir `documentsNotaryValidatorsHelpers.ts`) : les helpers (DocumentsNotaryGetOneByUidHelper, DocumentsNotaryMarkAsViewedHelper, DocumentsNotaryCaseHandlers) fournissent un callback `validateAccess` qui peut s'appuyer sur ce service.
2. **Middlewares** : `DocumentAccessValidationHelper` (OfficeMembershipHandlers), `FileHandlerAccessHelpers.validateDocumentAccess` / `validateFileAccess`, `DocumentHandlerAccessByUidHelper` — chargent le document, vérifient l'accès au dossier via `ensureFolderAccess` et appliquent des règles métier similaires.
**Convergence prévue** : faire appeler par les middlewares le `DocumentAccessValidationService.validateAccess` en construisant un `DocumentAccessContext` à partir du contexte requête, afin d'éviter la double maintenance et les écarts de comportement. En attendant, toute modification des règles d'accès doit être répercutée dans les deux chemins ou documentée comme temporaire.
---
## Documentation Fonctionnelle
Cette section décrit de façon fonctionnelle chaque fichier du projet, expliquant son intérêt dans le projet et ce qu'il fait de façon résumée.
> **Note** : Le contenu détaillé fichier par fichier est consolidé dans ce document (section Documentation Fonctionnelle ci-dessous).
### Synthèse Optimisations Fiabilité & Simplicité (déc. 2025)
| Axe | État | Détails |
| --- | --- | --- |
| Gestion d'erreurs | **Terminé** | `errorHandlers.ts`, `errorLoggers.ts`, `errorMessages.ts` et depuis 2025-12, toutes les méthodes `http*` du `BaseController` délèguent à ces helpers (logs Winston homogènes, messages centralisés). |
| Résolution permissions/rôles | **Terminé** | Découpage de `RulesHandler` en `decisionHandlers`, `ruleMatcher`, `resourceResolver`, `roleResolver` + helpers `userHelpers.ts`, `roleNormalizer.ts`, `uidExtractors.ts`. |
| API client frontend | **Terminé** | Hook `useApiClient` + helpers `errorClassifiers`, `retryHelpers`, `formValidators`, `formatters` pour supprimer les appels `fetch` dupliqués. |
| Duplication helpers JWT / extraction utilisateur | **✅ Terminé** | Helpers centralisés dans `userHelpers.ts` (`getStringFromRecord`, `getBooleanFromRecord`, `getStringArrayFromRecord`, `extractUserData`) - tous les fichiers migrés. |
| Validation formulaires frontend | **✅ Terminé** | Validations centralisées dans `front/Utils/formValidators.ts` (`validateEmail`, `validatePassword`, `validateRequired`, etc.) - regex inline remplacées. |
| Formatage prix / données | **✅ Terminé** | Fonctions centralisées dans `front/Utils/formatters.ts` (`formatPrice`, `formatDate`, `formatMonthString`, `truncateHash`, etc.) - tous les fichiers utilisent les helpers centralisés. |
| Tests & documentation | **En cours** | Chaque lot migré doit être consigné dans [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) (root cause, impacts) et dans ce document (CODE_STANDARDS.md). |
### Structure du Projet
#### Backend (lecoffre-back-main/src/)
- **Entries** : Points d'entrée (`App.ts`, `Cron.ts`)
- **App** : Configuration Express, middlewares, routes
- **App/api/customer** : Contrôleurs et helpers customer ; constantes statuts dans `api/customer/constants/documentStatusConstants.ts` (`DOCUMENTS_TO_SEND_STATUSES`, `DOCUMENT_STATUSES_RECEIVED_FROM_NOTARY`) pour alignement sémantique avec le front et réutilisation (ex. filtre « documents à envoyer »). `DocumentsQueryHelper` et requêtes customer peuvent s'y référer (voir JSDoc).
- **Common** : Utilitaires partagés (error handlers, helpers, DTOs, emails)
- **Services** : Services métier (Files, Documents, Folders, Users, etc.)
#### Frontend (lecoffre-front-main/src/)
- **Pages** : Pages Next.js (routes)
- **Front** : Composants, hooks, stores, API clients, utils
#### Ressources (lecoffre-ressources-dev/src/)
- **Admin** : Types et DTOs pour l'administration
- **Customer** : Types et DTOs pour les clients
- **Notary** : Types et DTOs pour les notaires
- **SuperAdmin** : Types et DTOs pour le super-admin
- **MemberTypes** : Types centralisés pour `userType` (JWT), `role` (role_permissions_matrix) et `UserContext` (frontend). Constantes : `USER_TYPE_THIRDPARTY`, `USER_TYPE_CUSTOMER`, `ROLE_CLIENT`, `ROLE_NOTARY`, `ROLE_GUEST_NOTARY`, `USER_CONTEXT_CUSTOMER`, `USER_CONTEXT_NOTARY`, `USER_CONTEXT_INVITED_NOTARY`, `USER_CONTEXT_THIRD_PARTY`, `THIRD_PARTY_UI_VARIANT`, `ROLES`. Helpers : `isRole`, `isThirdParty`, `isCustomer`, `isGuestNotary`, `isNotaryRole`.
### Documentation Complète
La documentation détaillée fichier par fichier a été archivée (voir historique Git). Les patterns et la structure sont dans les sections ci-dessus. README des sous-projets : `lecoffre-back-main`, `lecoffre-front-main`, `lecoffre-ressources-dev`.
---
## Sécurité Applicative
Résumé : **Chiffrement** (clé maître `FILE_ENCRYPTION_MASTER_KEY`, AES-256-GCM, tous les fichiers) ; **2FA tiers** (request-code/verify-code, codes 6 chiffres, JWT `userType: 'thirdparty'`) ; **Déconnexion** (table `revoked_tokens`, `POST /api/v1/auth/logout`) ; **ClamAV** (AntivirusService, daemon clamd, config dans `system_configuration`). Détail : [DATABASE_COMPLETE.md](./DATABASE_COMPLETE.md) et [SCRIPTS.md](./SCRIPTS.md).
---
## Références Générales
- `eslint.config.mjs` (front/back/ressources)
- `docs/ARCHITECTURE.md` : Architecture générale du système
- `docs/DEPLOYMENT.md` : Guide de déploiement
- `docs/API.md` : Documentation des APIs externes
- [README.md](./README.md#consolidation-operationnelle-ex-operationsmd) : Documentation des problèmes et correctifs
- [ARCHITECTURE.md](./ARCHITECTURE.md) et [FRONTEND.md](./FRONTEND.md) : Documentation des évolutions
---
**Dernière mise à jour** : 2026-02-27