Skip to main content

Bugs & failles actives connues

Contrairement à Dette technique connue (différable, pas urgent), tout ce qui est listé ici est un dysfonctionnement ou un risque de sécurité déjà actif en l'état du code — pas une amélioration future. À traiter en priorité, pas "quand l'occasion se présente".

Dernière vérification contre le code

Vérifié le 2026-08-13. Tous les points identifiés à ce jour sont corrigés.

✅ Corrigés (2026-08-13)

updateLoanStatus n'avait aucune vérification d'appartenance à une agence

backend/src/controllers/loan.controller.js, fonction updateLoanStatus (PATCH /api/loan-requests/:id) — contrairement aux 3 autres endpoints du contrôleur, celle-ci ne vérifiait jamais que req.user avait le droit d'agir sur le dossier ciblé : tout utilisateur backoffice authentifié pouvait changer le statut de n'importe quelle demande de prêt, y compris celles d'une autre agence — le point le plus sensible du contrôleur puisqu'il exécute la décision (pas juste une consultation). canAccessAgency(req.user, currentLoan.id_agence) ajouté juste après le chargement du dossier.

account_requests : lecture entièrement publique, sans authentification

backend/src/routes/account_requests.routes.js : GET / et GET /:id n'avaient aucun middleware verifyToken — n'importe qui, sans être connecté, pouvait lister l'intégralité des demandes d'ouverture de compte (identité, téléphone, email, adresse, données FATCA/TIN). verifyToken ajouté sur les deux routes, et agencyScopeWhere/canAccessAgency appliqués à getAll/getById (account_requests.controller.js, account_requests.service.js::getAll accepte désormais un where) — un utilisateur authentifié ne voit maintenant que les demandes de sa propre agence (ou de sa zone pour CHEF_ZONE), cohérent avec account.controller.js et loan.controller.js.

loan_parameters modifiable sans authentification

PUT /api/loan-parameters/:id exige désormais verifyToken (GET reste public, consommé par les formulaires publics).

Alertes lisibles sans authentification

GET /api/alertes et GET /api/alertes/:id exigent désormais verifyToken.

POST /api/users accessible à tout utilisateur authentifié

POST/PUT/DELETE /api/users exigent désormais isSuperAdmin (même middleware que /api/roles).

Le bypass 000000 de la 2FA n'existe pas (mais était documenté comme existant)

Le README backend et le commentaire dans SchoolLoanView.vue ont été corrigés pour ne plus affirmer l'existence de ce bypass. Le placeholder OTP côté prêt scolaire (000000) reste en place — c'est un mécanisme distinct, volontaire, en attendant l'intégration Sopra Banking Amplitude, voir Demande de prêt scolaire.

Mise à jour de statut d'une demande de compte : route inexistante

AccountRequestDetailView.vue/AccountRequestsView.vue appellent désormais PATCH /api/account-requests/:id/status (route réellement exposée).

LoanDocumentsConfigView.vue appelait le mauvais endpoint de suppression

Corrigé : DELETE /loan-document-requirements/:id (au lieu de /loan-requirements/:id).

CNI (signataires/bureau/promoteur) jamais enregistrées comme documents

OpenAccountView.vue les inclut désormais dans additional_data.documents (mêmes clés descriptives : signataire_N_cni, bureau_{role}_cni, promoteur_cni) — elles passent maintenant par le mécanisme générique déjà utilisé pour les autres pièces, aucun changement backend nécessaire. Voir Ouverture de compte.

Sauvegarde des slides : suppression totale sans transaction

Un nouvel endpoint PUT /api/slides (slidesService.replaceAll) remplace l'ancienne séquence DELETE/POST multiples non transactionnelle par une seule transaction Prisma (delete + recreate atomiques, éléments inclus). Voir Éditeur de bannières.

URL de setup-password codée en dur

utils/mailer.js lit désormais process.env.FRONTEND_URL (repli sur http://localhost:5173 si absent) ; FRONTEND_URL ajoutée à .env.example.

loan_field_requirements réservé SUPER_ADMIN, incohérent avec loan_document_requirements

La restriction isSuperAdmin a été retirée — les deux routers de configuration de prêt exigent maintenant uniformément verifyToken seul.

CHEF_ZONE ne filtrait pas réellement par zone

Cette entrée a été marquée "corrigée" une première fois à tort

Le module agencyScopeWhere/canAccessAgency (backend/src/utils/agency-scope.js) avait bien été écrit et branché sur loan.controller.js/account.controller.js/account_requests.controller.js, mais restait inopérant pour deux raisons cumulées, découvertes seulement en testant avec un vrai compte CHEF_ZONE (login + 2FA + appels API réels) :

  1. CHEF_ZONE avait la permission view_all_agencies (seed/seed_roles.js) — cette permission court-circuite agencyScopeWhere/canAccessAgency en premier (accès total, sans restriction), rendant la logique "restreindre à la zone" écrite juste en dessous inatteignable. Retirée des permissions de CHEF_ZONE.
  2. Une fois ce point corrigé, plus aucun dossier n'était visible pour CHEF_ZONE (régression inverse) : id_zone n'était jamais inclus dans le JWT émis par verify2fa — seul id_agence l'était. Ajouté au payload JWT et à la sélection Prisma de getMe (auth.controller.js).

Leçon : une correction non testée en conditions réelles (vrai login, pas juste une relecture de code) peut sembler correcte tout en étant totalement inopérante.

Un CHEF_ZONE est désormais réellement restreint aux agences de sa propre zone (id_zone), vérifié par un test de bout en bout (accès accepté sur une agence de sa zone, 403 sur une agence d'une autre zone). Voir Agences, zones & GAB et Authentification & 2FA.

README backend : message de démarrage NLP trompeur

"NLP Model Trained Successfully with 26 intents" a été retiré — ce message décrivait un ancien moteur NLP (@nlpjs) que le code actuel ne charge plus (le vrai moteur actif est un système RAG + Ollama, désactivé côté serveur par choix, pas un bug — voir Chatbot (NLP + RAG)). Le serveur n'affiche désormais que UTB Backend Server running on port 3000 au démarrage, ce que le README reflète maintenant.

Doc Swagger de users.routes.js obsolète

Corrigée : password retiré des champs requis/documentés de POST /api/users (jamais utilisé par create(), qui crée le compte sans mot de passe et envoie une invitation) ; two_factor_secret/two_factor_enabled retirés (destructurés mais jamais utilisés) ; id_agence/id_zone ajoutés (réellement pris en compte, absents de la doc précédente).

seed_fields.js — entrée retirée, le fichier n'existe pas

Une version antérieure de cette page affirmait qu'un ancien script seed_fields.js traînait à la racine du dépôt backend, hérité d'avant la réorganisation des scripts de seed. Vérification faite le 2026-08-13 : ce fichier n'existe pas dans le dépôt actuel — l'affirmation provenait d'un contenu migré depuis l'ancienne doc du projet sans revérification indépendante à ce moment-là. Corrigé ici pour que l'erreur ne se propage pas plus loin.