Update ia_dev agent playbooks and kogus docs to reflect two-line multisite (lecoffreio/genealogie), enforce SSH execution requirements in analyse mode, and refresh deployment/multisite documentation links.
218 lines
29 KiB
Markdown
218 lines
29 KiB
Markdown
# Code-Standards – Lint, refactors, rôles et droits
|
||
|
||
**Auteur** : Équipe 4NK
|
||
|
||
## Architecture front — URL API notaire
|
||
|
||
- Tout nouvel appel HTTP, flux SSE, refresh token ou URL backend dérivée pour l’API notaire doit passer par **`getBaseUrl()`** (`front-common/src/front/Api/helpers/configHelpers.ts`) ou **`baseApi.getBaseUrl()`** sur un service **`BaseApiService`**, pas par concaténation manuelle de **`BACK_API_*`** ni par composition d’URL à partir de **`process.env.NEXT_PUBLIC_BACK_API_*`** en dehors des chemins bootstrap / runtime déjà documentés.
|
||
|
||
- **Navigation notaire — contexte « Dossiers invités »** : toute évolution du basculement office / invité ou du retour depuis les écrans document doit tenir compte de **`notaryInvitedFoldersNavPersistence.ts`** (**`sessionStorage`**, **`pathnameEligibleForPersistedInvitedNav`**) et des consommateurs **`folderContextViewFlags`**, **`viewDocumentsBackUrlCompute`**, **`ActiveOfficeStore.reset`** — détail comportement et chemins dans **`docs/Frontend.md`** (section *Persistance du contexte « Dossiers invités »*).
|
||
|
||
### Next.js — `PublicSiteConfigProvider` et prerender (SSG)
|
||
|
||
- Tout hook qui appelle **`usePublicSiteConfigContext`** (y compris **`useApplyPublicSiteTheme`**) doit vivre **sous** **`PublicSiteConfigProvider`** dans **`front-common/src/pages/_app.tsx`**. Les hooks du shell parent (**`AppShell`**, ex. **`useAppFrontendBootstrap`**) restent limités au bootstrap env / session : pas de contexte site public à cet niveau.
|
||
- Pattern retenu : composant **`PublicSiteThemeEffect`** (enfant du provider) qui appelle **`useApplyPublicSiteTheme`** — voir **`docs/Frontend.md`** § *Config site public* et **`docs/Operations.md`** § *Next.js — prerender / SSG*.
|
||
- Préférer le hook **`useApiClient`** et le catalogue **`apiV1Paths`** pour les segments sous **`/api/v1`** ; exposer **`baseUrl`** du hook plutôt que **`protocol` + `host`** isolés.
|
||
- Politique **`process.env`**, liste des fichiers autorisés et commandes de contrôle : **`docs/Operations.md`** § *Front — URL API : centralisation sur getBaseUrl()*.
|
||
- Détail produit (réécriture d’hôte, **`invalidateBaseUrl()`**, anti-patterns) : **`docs/Frontend.md`** § *Base URL backend (API notaire)*.
|
||
|
||
## Multisite back-end — résolution de déploiement vs options `sites`
|
||
|
||
- **Routage** : lorsque le même binaire sert plusieurs hôtes publics, **`getEffectiveDeploymentSiteCode`** / ALS (`back-common/src/common/request/deploymentSiteContext.ts`) rattachent la requête à la **ligne `sites` effective** et aux enregistrements **`site_code`** concernés — aligné sur **`GET /v1/public/site-config`**.
|
||
- **Logique métier** : le code applicatif doit rester **agnostique des noms de site** (`lecoffreio`, `genealogie`). Il se pilote sur les **options activées** (**`integration_flags`**, contenu de **`theme_json`**, etc.) pour cette ligne, pas sur des branchements métier par libellé de ligne. Exceptions : couches **Host** / chemins secrets, **migrations** ou **seeds** SQL par partition documentés, **scripts shell** avec **`SITE_CODE`**.
|
||
- **Référence** : **`docs/features/multi-site-architecture.md`** § *Backend HTTP partagé* / *Règle code métier*.
|
||
|
||
## Déploiement Node — `deploy/scripts_v2/lib/` et PostgreSQL
|
||
|
||
- **Fichiers qui ouvrent une `Pool` `pg`** : uniquement **`deploy/scripts_v2/lib/pgPoolFromConnectDb.mjs`** (résolution **DATABASE_URL** **kogus** / surcharge env, **`createVerifiedPgPool`**, **`createVerifiedPgPoolFromUrl`**, **`resolveDatabaseUrlForDeployScript`**), **`connectDbUrl.mjs`** (**`loadDatabaseUrlFromConnectDb`**, **`tryLoadDatabaseUrlFromConnectDbFile`**, **`nestedLineConnectDbPath`**, chemins connectDB), et **`exportMandatoryLineArtifactsFromDb.mjs`** (**SELECT** multi-**`site_code`** pour les exports JSON ligne). C’est le périmètre **pg** du dossier **`lib/`** ; pas d’autre **`.mjs`** y créer une pool pour l’instant.
|
||
- **Autres `*.mjs` sous `lib/`** (`nestedSecretsMaterialize`, `mergeInfosV2DatabaseFromSiteLineEnv`, `mandatoryLineArtifactsTemplates`, `nestedSecretsEnsureGaps`, `generateEnvFullFromInfos`, `merge-env-full-site-keys-cli`, `stripInfosV2CrossLineSecrets`, `parseEnvFileValue`, `loadPg`, `warnConnectDbLoopback`) : disque uniquement (gabarits, **`infos_v2`**, merge env-full, avertissements) — **pas** d’accès PostgreSQL.
|
||
- **Nouveau script Node** sous **`deploy/scripts_v2/`** (racine ou **`lib/`**) qui doit lire PostgreSQL : réutiliser **`resolveDatabaseUrlForDeployScript`**, **`nestedLineConnectDbPath`** / **`tryLoadDatabaseUrlFromConnectDbFile`**, et **`createVerifiedPgPoolFromUrl`** comme **`nested-secrets-tool.mjs`** (**`export-db-artifacts`**) — une pool par **`DATABASE_URL`** de ligne lorsque le connectDB **ligne** diffère du défaut **kogus** ; éviter une résolution d’URL dupliquée ou une seule pool implicite pour tout le multisite.
|
||
- **Couche shell distante** : hors **`lib/`**, l’accès BDD sur les cibles passe par **`load_connectdb_v2`**, **`SITE_CODE`**, **`resolve_connect_db_path_on_target`** (**`deploy/scripts_v2/remote/_lib.sh`**). Ne pas court-circuiter cette résolution pour du métier runtime.
|
||
- **Références** : **`docs/features/secrets-multisite-kogus-and-sites.md`** § *CLI `nested-secrets-tool.mjs`* et inventaire **`lib/`** ; **`docs/features/multi-site-architecture.md`**.
|
||
|
||
## Déploiement shell — chemins cible (`APP_ROOT`) et multisite
|
||
|
||
- **Chemin dépôt distant (orchestrateur)** : une seule fonction **`get_env_remote_app_root <env> <site>`** dans **`deploy/scripts_v2/_lib/env-map.sh`** (forme **`/srv/4NK/<fqdn>`** dérivée de **`get_env_domain_for_site`**). Les scripts sous **`deploy/scripts_v2/`** (hors **`remote/`** qui reçoivent déjà **`<app_root>`** en argument) ne doivent **pas** recalculer **`/srv/4NK/${DOMAIN}`** ou dupliquer la règle FQDN → disque.
|
||
- **FQDN public aligné sur `APP_ROOT`** : **`get_env_domain_for_site <env> <site>`** avec le **même** **`site`** (`lecoffreio` \| `genealogie`) que pour **`get_env_remote_app_root`**.
|
||
- **Contexte déploiement** : **`lcf_deploy_export_target_context`** (**`deploy/scripts_v2/_lib/deploy-target-context.sh`**) résout **`site`** une fois depuis **`SITE_CODE`** / **`LECOFFRE_SITE_CODE`** / **`DEPLOY_SITE_CODE`**, pose **`DOMAIN`** et **`APP_ROOT`** via ces deux fonctions, puis les ports systemd via **`get_env_*_port`** lorsque demandé — pas de second chemin pour **`APP_ROOT`**.
|
||
- **Outils sans boucle `for site`** : second argument explicite ; **`lcf_site_code_for_remote_app_root_or_lecoffreio`** (**`env-map.sh`**) lorsque le défaut **lecoffreio** ou un **`SITE_CODE`** exporté hors boucle suffit ; boucles multisite : passer **`site`** / **`SITE`** en clair.
|
||
- **Détail opérateur** (arbres **`.secrets/`**, **kogus**, sync connectDB sur les trois **`APP_ROOT`**, matrice post-déploiement, exceptions stockage) : **`docs/features/secrets-multisite-kogus-and-sites.md`** — ne pas y recopier la norme ci-dessus ; renvoyer ici pour toute nouvelle règle shell sur **`APP_ROOT`** / **`DOMAIN`**.
|
||
|
||
## `front-backoffice` (cabinet) — `fetch` same-origin et `basePath`
|
||
|
||
- **Route Handlers Next** (`src/app/api/**`, même déploiement que l’App Router) : tout **`fetch`** navigateur vers ces chemins doit passer par **`fetchUnderCurrentAppBase`** ou **`nextAppSameOriginUrl`** (`front-backoffice/src/lib/oauth.ts`), afin d’inclure le préfixe **`/backoffice`**. **Inventaire actuel du dépôt** : un seul appel — **`docvOAuthBrowser.ts`** → **`/api/auth/docv-token`**. Toute nouvelle route **`app/api/...`** consommée en **`fetch`** côté client doit réutiliser ce mécanisme.
|
||
- **API docv-back** : les chemins **`/api/v1/...`** passent par **`docvFetch`** et **`docvApiBase()`** (`front-backoffice/src/lib/docv/client.ts`, origine **`/docv-api`**). **Ne pas** les faire transiter par **`pathWithBase`** / **`fetchUnderCurrentAppBase`**.
|
||
- **Liens et redirections** : **`Link`**, **`redirect()`**, **`router.replace()`** avec chemins commençant par **`/`** restent sans préfixe manuel **`/backoffice`** ; Next applique **`basePath`** automatiquement.
|
||
- Détail déploiement et smoke réseau : **`docs/features/monorepo-backoffice-oauth-default.md`** § *`fetch` same-origin : Route Handlers Next vs API docv-back*.
|
||
- **Typage i18n** : pour le code sous **`front-backoffice/src/`** qui appelle **`t("…")`** avec des clés du catalogue **`src/i18n/messages.*.ts`**, typer l’argument **`t`** avec **`TranslateFn`** depuis **`@/i18n`** (alias vers **`src/i18n`**) dans les helpers et modules extraits — aligné avec les écrans case / document déjà refactorés.
|
||
|
||
## Lint backend (back-common) – refactors restants
|
||
|
||
Après `npm run lint:fix`, les erreurs ESLint non auto-fixables sont traitées par refactors ciblés. Règles concernées (sans contournement ni désactivation) :
|
||
|
||
- **max-params** : regrouper les paramètres en objet d’options typé.
|
||
- **max-lines-per-function** : extraire sous-fonctions ou helpers.
|
||
- **max-lines** : découper les fichiers en modules plus petits (helpers, sous-services).
|
||
- **complexity** : simplifier les conditions, extraire des branches en fonctions.
|
||
|
||
### Corrections déjà réalisées (exemples)
|
||
|
||
- `FilesNotaryController` : constructeur 5→4 params via objet de dépendances (@Service).
|
||
- `ExecuteFilesNotaryDownloadOptions` pour réduire le nombre de paramètres.
|
||
- `NotificationBuilder` : 5→4 params via deps.
|
||
- `OfficeFoldersGetOneByUidHydrationHelper`, `OfficeRibGetHelper`, `FolderHandler`, `FolderNotaryAIIncludeHelper` : réduction complexité/lignes via extraction de helpers.
|
||
- `DatabaseOperationHelper` : `executeWithTimeoutAndRetry` et helpers en objet d’options.
|
||
- Variables inutilisées supprimées ; types extraits (`UserHydrated`) ; extraction de fonctions de log et de validation (`getEmailHintForLog`, `validateFolderNumberStep`, `hasSameOfficeAccess`, `checkSharingAccess`, etc.).
|
||
|
||
### À faire (refactors lourds)
|
||
|
||
- `validationHelpers.ts` : `validateRequestBody`, `validateQueryParams`, `validateEntity` (5–6 params) → objet d’options ; mettre à jour tous les appels.
|
||
- Fichiers > 250 lignes : découpage en modules (DocumentAccessValidationHelper, RulesHandler, DocumentEmailService, etc.).
|
||
- Fonctions > 40 lignes et complexité > 10 : extraction systématique (FolderNotaryAIController, FolderNotaryAIContextBuilder, decisionHandlers, ruleMatcher, EmailBuilder, services notary/common).
|
||
- **Cartographie post-refactor (login / email / tiers)** : `docs/features/login-and-email-helpers-structure.md` — à mettre à jour si de nouveaux modules sont extraits pour le lint (back + front).
|
||
- Constructeurs et méthodes > 4 paramètres : classes @Service de dépendances ou types d’options.
|
||
|
||
Vérification : `npm run lint`, `npm run lint:fix` dans back-common. Référence : `.cursor/rules/cloture-evolution.mdc`, agent fix-lint.
|
||
|
||
### Historique des correctifs lint (batches)
|
||
|
||
- **max-params via option objects (backend)** : ruleMatcher, decisionHandlers, RulesHandler ; EmailBuilder, NotificationEmailService, ThirdPartyEmailService, DocumentEmailService, DocumentEmailBatchHelper ; ConnectionPoolMonitor, AntivirusService, WatermarkService, DocumentRemindersService, FolderAnchorCertificatePdfHelpers, OfficesRibService, DocumentAnchorsBatchHelper, ZipService, OfficeFoldersRepository, etc. Backend 361 → 311 errors.
|
||
- **Batch 50+ (max-params, max-lines-per-function)** : AggregatedCertificatePdf*Helpers, ZipFileContextBuilder, RulesHelper, ConnectionPoolMonitor, MergedFileCreationHelper, DocumentWithMergedFilesHelper, OfficeFolderAnchorsService, AffiliationSyncRattachementHelper, FolderSearchService, OfficesRibService, UserOfficeAffiliationsGuestFoldersHelper, DocumentAnchorsBatchHelper, ZipPdfMetadataHelper, DocumentBatchCleanupHelper. Backend 312 → 284.
|
||
- **Batch 75 (2026-03)** : N0 = 170 → objectif ≥ 75 corrigées. Batch 1 : explicit return type (ProcessingStepsAggregate), max-lines (extractions ThirdPartyCodeDevLogger, OfficeFolderAnchorsReadmeSections, V1ToV2MergeConstants, FolderSearchFormatHelper, OfficesRibUtils, etc.), max-params (DocumentAnchorsBatchHelper, DocumentBatchCreationHelper options). Batch 2 : max-params (EmailBuilder, AuthService, ZipService, FileProcessingService, FilesNotaryService, DocumentAnchorsService, DocumentWithMergedFilesHelper, OfficeFoldersController handlers, NotificationEmailService, AntivirusService, DocumentAnchoringBlockchainHelper, IdNotOfficeService, OfficeFolderAnchorsService, FileProcessingStepHelper, FilesService, DocumentAnchoringFinalizationHelper, AggregatedCertificateService, IdNotService, CustomersService, NotaryFolderAIService, etc.), max-lines (extractions ThirdPartyUploadPermissionHelper, HealthChecksServiceUtils, HealthChecksServiceAnchorHelper, UserOfficeAffiliationsLicenseFilterHelper, IdNotDirectoryApiSearchHelper, DocumentBatchAnchoringErrorHelper, etc.), complexity et max-lines-per-function (helpers dans DocumentAnchoringFinalizationHelper, DocumentBatchProofDataHelper, IdNotRoleService, MailchimpService, RolePermissionsMatrixService, FolderBusinessService, OfficeFolderAnchorsVerificationHelper, CollaboratorsAggregationService, WatermarkBufferProcessorHelper, MailchimpEmailSenderHelper, IpfsService, IdNotDirectoryService, DeedTypeListSettingsService, DocumentRemindersService, DocumentAnchoringWatermarkHelper, AnchorCertificatePdfDrawingHelpers, IdNotSiteBaseSearchHelper, DocumentWithMergedFilesHelper). N_final = 85, 76 corrigées, objectif atteint. Reste 85 erreurs (max-lines, complexity) ; poursuivre avec option objects et extractions.
|
||
- **validationHelpers, userHelpers, FolderSharingSearchHelper** : ValidateRequestContext ; validateRequestBody/validateQueryParams/validateEntity(context) ; extractUserData → extractPayloadStrings, computeExtractedUserFields, getOfficeAndIdentityFields ; searchOffices → runOfficeSearch, logOfficeSearchResult, sendOfficeSearchUnconfiguredResponse ; getUserIdFromRequest → getUserIdFromPermissionContext, getUserIdFromBodyOrRequestUser. Backend 364 → 361.
|
||
- **FolderNotaryAIController, FolderNotaryAIContextBuilder** : buildMembersSummary, buildDocumentsSummary, getDocumentTypesForDeed ; rejectIfThirdPartyUser, getUidAndQuestion, executePostAiQuestionBody, executeGetAiResponseBody, sendAiResponseResult. Backend 370 → 364.
|
||
- **Frontend (unused vars, return types)** : useConfreresManager (_folderUid), useThirdPartiesData (_currentThirdPartyUid) ; FolderListStatsPanel, DocumentTables, useSyncV1Status, OfficeInformations, _document.tsx types explicites. Frontend 1010 → 1001 warnings.
|
||
- **Objectif 27 (2026-03-18)** : FileMergeService (FileMergeMetadataPageHelper), DocumentBatchProcessingHelper (Types, DocumentBatchSharedOfficeHelper), FolderBusinessService (FolderBusinessServiceWhereBuilder), WatermarkService (Types, WatermarkNotaryFlowHelper), RulesHandler (RulesHandlerEvaluation, RulesHandlerFallback, RulesHandlerTypes). N0 = 27 → N_final = 22 (5 corrigées). Reste : appliquer le même type d’extraction aux 22 fichiers restants.
|
||
- **Objectif 75 (session 2026-03-18)** : max-params (RolePermissionsMatrixService, WatermarkBufferProcessorHelper), max-lines (IdNotApiService/IdNotApiTypes, OfficeFolderAnchorsService/OfficeFolderAnchorsRegenerateHelper, DocumentsService/DocumentsServiceTypes, DocumentAnchoringFinalizationHelper/Types), complexity (MailchimpEmailSenderHelper, AnchorCertificatePdfDrawingHelpers, IdNotRoleService). N0 = 85 → N_final = 77 (8 corrigées). Objectif 75 non atteint ; poursuivre batches (max-lines, complexity, max-lines-per-function). Modalités : `cd back-common && npm run lint`.
|
||
- **fix-lint (2026-03-19)** : Priorité amont (config qualité + bypass). Frontend : lot 1 (exhaustive-deps useOfficeMembers, max-depth documentDownloadHelpers via tryCriticalErrorSessionFailure), lot 2 (downloadMultipleFiles → DownloadMultipleFilesOptions, processResponse/handleResponseText → options/context). Bypass : 1 supprimé (frontend), justifiés documentés par périmètre (voir section « Configuration qualité et inventaire des bypass » ci-dessous). N0 frontend ≈ 1004 → 996 warnings.
|
||
|
||
---
|
||
|
||
## Exécution exhaustive des agents lancés
|
||
|
||
Tout agent sous `.cursor/agents` doit veiller à l'exécution exhaustive des agents qu'il lance (ou des phases qu'il exécute) : vérification avant clôture ; en cas d'incomplétude : pas de clôture, documenter les manques, améliorer les instructions, relancer jusqu'à exécution exhaustive.
|
||
|
||
- **Agents de délégation** (agent-loop, fix, evol, docupdate, push-by-script, fix-search, deploy-by-script, fix-lint, gitea-issues-process, code, branch-align-by-script-from-test, change-to-all-branches, deploy-pprod-or-prod, notary-ai-process, notary-ai-loop) : section « Exécution exhaustive des agents lancés » avec vérification obligatoire avant clôture ; en cas d'incomplétude : 1) ne pas clôturer et documenter, 2) améliorer les instructions, 3) relancer l'agent concerné.
|
||
|
||
Aucun déploiement applicatif ; prise en compte à la prochaine invocation des agents.
|
||
|
||
---
|
||
|
||
## Vérifications rôles et droits (import v1, offices, notaire invité)
|
||
|
||
- **Import v1 – rôles et droits dossiers/offices** : vérification que l’import v1 préserve les rôles et droits sur les dossiers et offices (verification-import-v1-roles-et-droits-dossiers-offices).
|
||
- **Office notaire / notaire invité** : vérification des cas notaire titulaire vs notaire invité (verification-office-notaire-notaire-invite).
|
||
- **API annuaire – idNot et requêtes** : vérification des requêtes annuaire et usage idNot (verification-api-annuaire-idnot-requetes).
|
||
|
||
Ces vérifications alimentent les tests manuels et les scripts d’analyse (voir Operations.md).
|
||
|
||
---
|
||
|
||
## Configuration qualité et inventaire des bypass
|
||
|
||
**Date**: 2026-03-19
|
||
**Contexte**: Agent fix-lint projet lecoffreio — priorité amont (règles de qualité + bypass).
|
||
|
||
### Règles et exigences de qualité — état par sous-projet
|
||
|
||
#### Frontend (front-common)
|
||
|
||
- **ESLint** : `eslint.config.mjs` (flat config). Règles en `error` (hors désactivations documentées) : `no-explicit-any`, `explicit-function-return-type`, `explicit-module-boundary-types`, `max-lines` (250), `max-lines-per-function` (40), `max-params` (4), `max-depth` (4), `complexity` (10), `max-nested-callbacks` (3), `no-console`, `react/no-unescaped-entities`, `react-hooks/rules-of-hooks`, `react-hooks/exhaustive-deps`. Plugin `unused-imports` pour variables/imports inutilisés. Exécution : `scripts/run-lint.mjs` avec **`--max-warnings 0`** (tout warning fait échouer la commande).
|
||
- **TypeScript** : `tsconfig.json` avec `strict: true`, `noImplicitAny: true`, `strictNullChecks: true`.
|
||
- **Prettier** : `.prettierrc.json` présent.
|
||
|
||
#### Backend (back-common)
|
||
|
||
- **ESLint** : `eslint.config.mjs` (flat config). Règles en `error` : `no-explicit-any`, `explicit-function-return-type`, `explicit-module-boundary-types`, `no-non-null-assertion`, `no-require-imports`, `no-console`, `max-lines`, `max-lines-per-function`, `max-params`, `max-depth`, `complexity`, `max-nested-callbacks`. Plugin `unused-imports`. Script `npm run lint` : **`--max-warnings 0`**.
|
||
- **TypeScript** : `tsconfig.json` avec `strict: true`, `noImplicitAny: true`, `strictNullChecks: true`.
|
||
- **Prettier** : `.prettierrc.json` présent.
|
||
- **Texte d’erreur pour logs / interpolation** : utiliser **`coalesceThrownErrorText`** depuis `#Common/utils/coalesceThrownErrorText` à la place de `x instanceof Error ? x.message : String(x)` (y compris pour des jetables `{ message }` non-`Error`). **`back-admin`** expose la même logique dans `back-admin/src/coalesceThrownErrorText.ts` (pas de dépendance npm vers `back-common`).
|
||
|
||
#### Ressources partagées (ressources-common)
|
||
|
||
- **ESLint** : `eslint.config.mjs` (flat config). Règles en `error` : `no-explicit-any`, `explicit-function-return-type`, `explicit-module-boundary-types`, `no-non-null-assertion`, `no-console`, `max-lines`, `max-lines-per-function`, `max-params`, `max-depth`, `complexity`, `max-nested-callbacks`. Plugin **`unused-imports`** (aligné backend/front : `@typescript-eslint/no-unused-vars` désactivé au profit de `unused-imports/no-unused-imports` et `unused-imports/no-unused-vars`). Script `npm run lint` : **`--max-warnings 0`**.
|
||
- **TypeScript** : `tsconfig.json` avec `strict: true`, `noImplicitAny: true`.
|
||
- **Prettier** : `.prettierrc.json` présent.
|
||
|
||
Aucune config manquante ou désactivée de façon injustifiée. Exceptions locales ciblées dans `eslint.config.mjs` (fichiers précis) : voir tableau ci-dessous.
|
||
|
||
### Bypass — inventaire et justification
|
||
|
||
#### Frontend
|
||
|
||
| Fichier / zone | Type | Justification ou action |
|
||
|----------------|------|-------------------------|
|
||
| `LoggerServiceClass.ts` | Override `eslint.config.mjs` : `no-console` **off** pour ce fichier | **Justifié** : seul point de sortie console autorisé dans le bundle navigateur. |
|
||
| `Api/helpers/dynamicFactoryLoader.ts` | `/* eslint-disable @typescript-eslint/no-require-imports */` (fichier entier) | **Traité** : loader unique qui centralise tous les `require()` des factories LeCoffreApi et Auth ; les modules API (LeCoffreApi/**) et Auth/** n'ont plus de bypass et appellent `getLazyFactoryGetter(key)`. Un seul bypass restant (dans le loader) pour compatibilité Webpack/Next (lazy init, évitement TDZ). |
|
||
| Plusieurs hooks (useThirdPartiesData, useBurgerModalOfficeItems, useOfficeItemsFilter, etc.) | `// eslint-disable-next-line react-hooks/exhaustive-deps` | **À traiter** : soit ajouter les dépendances manquantes (ex. `useOfficeMembers` : ajout de `selectedOffice?.collaborators`), soit documenter l'exception (ex. `SiteTextsContext.tsx` avec commentaire explicite). |
|
||
| `SiteTextsContext.tsx` | `react-hooks/exhaustive-deps` avec commentaire | **Justifié** : commentaire indique que `preloadCacheKey` encode locale + scopes + textKeys et que le corps de l'effet utilise les valeurs courantes depuis la closure. |
|
||
|
||
**Bypass supprimés (2026-03-19)** : 1 — `useOfficeMembers.ts` : dépendance `selectedOffice?.collaborators` ajoutée au tableau de deps, suppression du besoin de bypass exhaustive-deps. 2 — `useInvitedDocuments.ts` (2026-03-19) : dépendances `currentOfficeUid`, `normalizedEmail` ajoutées au useCallback `loadDocuments` ; useEffect déclenché par `[loadDocuments]` ; suppression du `eslint-disable-next-line react-hooks/exhaustive-deps`.
|
||
|
||
**Bypass justifiés documentés** : LoggerServiceClass (no-console), SiteTextsContext (exhaustive-deps). **no-require-imports** : centralisation réalisée dans `Api/helpers/dynamicFactoryLoader.ts` ; tous les modules API (LeCoffreApi/**) et Auth (Auth/Customer, Auth/IdNot, Auth/IdNot/User) utilisent désormais `getLazyFactoryGetter(key)` ; un seul bypass reste dans le loader. Les exhaustive-deps sans commentaire restent à justifier ou corriger dans les prochains batches. Autres fichiers avec require (Stores, Toasts, etc.) : requestHelpers, headerHelpers, useApiClient, ConfigRuntime, ApiErrorHandlerService, Toasts.tsx — chargement optionnel / circulaire ; justifiés et laissés en l'état.
|
||
|
||
#### Backend
|
||
|
||
| Fichier / zone | Type | Justification ou action |
|
||
|----------------|------|-------------------------|
|
||
| `LogSanitizer.ts` | Override `eslint.config.mjs` : `no-console` **off** pour ce fichier | **Justifié** : utilitaire de sanitization des logs, sortie console désignée. |
|
||
| `V1ToV2MergeHelper.ts` | (refactor 2026-03-19) | **Bypass supprimés** : options objects pour upsertBatch/mergeTable ; handlers dans V1ToV2MergeTableHandlers.ts ; plus aucun eslint-disable. |
|
||
| `import-stripe-subscriptions.ts` | `// @ts-expect-error` (x2) | **Justifié** : conflit de types Stripe.Subscription vs modèle local Subscription ; commentaire explicite sur place. |
|
||
|
||
**Bypass supprimés** : 1 (V1ToV2MergeHelper.ts — refactor complet).
|
||
**Bypass justifiés** : 2 (no-console, @ts-expect-error). **max-params / max-lines-per-function / complexity** : non justifiables ; tout bypass doit être supprimé et le code refactoré.
|
||
|
||
#### Ressources partagées
|
||
|
||
Aucun bypass trouvé.
|
||
|
||
### Synthèse par périmètre
|
||
|
||
- **Frontend** : bypass supprimés 1 + no-require-imports centralisés (loader unique) ; justifiés (no-console 1, exhaustive-deps 1 avec commentaire, no-require-imports 1 dans dynamicFactoryLoader uniquement). Exhaustive-deps sans commentaire : à justifier ou corriger en priorité.
|
||
- **Backend** : bypass supprimés 0 ; justifiés 2 (no-console, @ts-expect-error typage Stripe). max-params / max-lines-per-function / complexity : non justifiables, à corriger par refactor.
|
||
- **Ressources** : bypass supprimés 0 ; justifiés 0 (aucun bypass).
|
||
|
||
### Corrections effectuées (2026-03-19)
|
||
|
||
- **Lot 2 (max-params)** : useNavigationEffects, useMenuEffects, useSplashVisibility, useFolderListData (processAndSortFolders, executeFolderLoad, useFolderListLoader), useExternalFoldersBootstrap, useCustomerFoldersLoader, useFolderSelectionCallback, createOfficeItem (officeItems.tsx), useNumberPickerValue — paramètres regroupés en options objects.
|
||
- **Lot 4 (max-lines-per-function)** : SearchOfficesFactory (normalizeSearchOfficesError + doSearchOffices), SearchNotariesFactory (id.), CircleProgress (useCircleProgressAnimation), HealthFactory (buildHealthTriggers), DeedsFactory, DeedTypesFactory, DocumentTypesFactory, CustomersFactory, DocumentsFactory (SuperAdmin), SiteTextsFactory, ThirdParty DocumentsFactory, DefaultCollaboratorDashboard (loadCollaborators), DefaultDeedTypeDashboard (loadDeedTypes), DefaultDocumentTypesDashboard (loadDocumentTypes), useSubscriptionLoader (loadSubscriptionCancelState), buildConfirmModalHandlers, DepositContent (DepositDropZone), processUpload (createDocumentAndUpload), EyeWithThumbnailTooltip (THUMBNAIL_TOOLTIP_SLOT_PROPS), useDepositFileHandlers (applyFilesToPendingState), getOfficeItems (OFFICE_ITEMS_PARAMS), renderSplashModal (SplashModalCard + constantes), DefaultDashboardWithList (DashboardSidebar, DashboardRightSide).
|
||
- **no-require-imports** : non retraité cette exécution ; centralisation déjà en place (dynamicFactoryLoader.ts) comme documenté en section 2.
|
||
|
||
#### Suite fix-lint 2026-03-19 (lots 2 à 5, objectif ≥75 erreurs)
|
||
|
||
- **errorClassifiers.ts** : réduction complexité isAuthError, isNetworkError, isRetryableError (extraction getAuthStatusFromObject, hasAuthMessage, NETWORK_PATTERNS, messageHasNetworkPattern, errorNameIsNetworkOrType, is5xxStatus, getStatusFromError).
|
||
- **httpStatusHelpers.ts** : handleHttpStatusError (lignes + complexité) via tryPatternMatch, try403BackendMessage, try401403Contextual, try404Element ; extract404ElementMessage raccourcie (ELEMENT_404_NAMES en constante, try404Element réutilisé).
|
||
- **zipSingleDocumentHelpers.ts** : tryDownloadViaFilesNotaryCustomer 7 params → TryDownloadViaFilesNotaryCustomerParams ; parseSingleDocumentInput → parseFromDocument + parseFromFilesInput ; handleSingleDocumentZipDownload → tryCustomerOrInvitedNotaryPath, tryNotaryDocumentNotaryPath.
|
||
- **documentNameHelpers.ts** : getDocumentNameWithTypePriority complexité → getTypeName, getFirstFileDisplayName, getFirstFileName.
|
||
- **downloadHelpers.ts** : ensurePdfExtension complexité → isValidatedStatus, addValidatedSuffixToFileName, isPdfContentType.
|
||
- **folderHelpers.ts** : extractOfficeUid complexité → nonEmptyString, getOfficeUidFromDeed.
|
||
- **formatters.ts** : normalizePhone complexité → stripSpacesAndDots, toFrenchInternational.
|
||
- **errorExtractionHelpers.ts** : extractErrorMessage complexité → getMessageFromHttpPayload.
|
||
- **folderSharingHelpers.ts** : computeFolderSharingStatus lignes + complexité → isSharingActive, isSharingNotExpired, sharingMatchesOffice, sharingMatchesIdNot.
|
||
- **folderQueryBuilders.ts** : buildFolderListQueryParams lignes → FOLDER_LIST_INCLUDE constant.
|
||
- **useRolePermissionsControllerHelpers.ts** : logMatrixStateUpdate complexité → buildMatrixStateLogPayload.
|
||
|
||
Résultat : N0 = 754, N_final = 679, corrigées = 75 (objectif ≥75 atteint).
|
||
|
||
### max-params / max-lines-per-function / complexity : non justifiables
|
||
|
||
**Règle** : les règles `max-params`, `max-lines-per-function` et `complexity` **ne sont pas justifiables**. Aucun bypass (eslint-disable) n'est accepté pour ces règles. Le code doit être refactoré pour les respecter (options objects pour max-params, extraction de fonctions pour max-lines-per-function et complexity, split de fichiers si nécessaire).
|
||
|
||
**Action** : tout bypass existant pour ces règles doit être supprimé et le code corrigé par refactor. Fichiers concernés (liste à mettre à jour au fil des corrections) : backend `V1ToV2MergeHelper.ts` ; frontend fichiers ayant reçu un disable au niveau fichier (DeedTypeListSettingsForm, useFolderAndCustomer, OfficeInformations, InformationSection, participantTabsHelpers, documentsDataLoader, useOfficeChangeRedirect, ReminderModal, useClientDashboardDocuments, commonUiI18nPart1, commonUiI18nPart2, commonUiMessageBuilders).
|
||
|
||
### Modalités de vérification
|
||
|
||
- Lint : `npm run lint` dans chaque répertoire (front-common, back-common, ressources-common). Les trois scripts passent **`--max-warnings 0`** : aucun warning ESLint ne doit rester.
|
||
- Compilation : `npm run build` (ou `type-check` si défini) dans chaque sous-projet.
|
||
- Bypass : `grep -r "eslint-disable\|@ts-ignore\|@ts-expect-error\|@ts-nocheck" lecoffre-*` puis vérifier chaque occurrence.
|
||
|
||
---
|
||
|
||
## Conventions projet (rappel)
|
||
|
||
- Pas de fallback implicite ; erreurs remontées et journalisées.
|
||
- Messages utilisateur en français, fonctionnels ; messages techniques (logs, codes) en anglais.
|
||
- Types de retour explicites pour les fonctions (TypeScript).
|
||
- Documentation des choix non évidents (invariants, hypothèses, contrats, cas limites).
|
||
- Respect des règles de lint et de typage sans désactivation.
|