Files
SchotzIAD/.kiro/specs/schotziad-km-tracker/design-requirements.md
T
MadJax e9f34e59e8 Refonte mise en page des exports PDF (en-tête, pied de page, tables)
En-tête (mensuel + annuel) :
- Titre « RAPPORT DE TRAJETS » en majuscules
- Logo agrandi (120 pt) à gauche, bloc titre centré sur l'espace restant,
  bloc d'infos placé dessous, trait séparateur sur toute la largeur

Pied de page (mensuel + annuel) :
- Mention légale (déclaration sur l'honneur, calcul indicatif, non
  opposable aux administrations) en 5 pt justifiée, au-dessus de la
  pagination

Rapport mensuel :
- Adresse d'arrivée à la ligne sous le départ, précédée de « → »
- Colonne dédiée « A/R » (marqueur « X ») avant les Kms ; largeurs
  ajustées (A/R minimale, Kms jusqu'à « 9 999 », adresses maximisées)

Rapport annuel :
- Espace après « Véhicule » ; barème applicable et total km sur deux
  colonnes
- Titre du tableau barème complété « — Kms parcourus × Coef + Base »
- Espace avant la régularisation, régularisation centrée

Steering : nouvelle règle workflow (valider l'approche avant de coder,
l'utilisateur lance le dev).

Specs requirements.md / design-requirements.md / design.md synchronisées
(Exigence 7 : critères + maquettes PDF + glossaire Mention_Legale).
2026-10-10 10:33:23 +02:00

30 KiB
Raw Blame History

Requirements Document

Design Requirements (exigences techniques)

Introduction

Ce document rassemble les exigences techniques dérivées des exigences fonctionnelles métier décrites dans requirements.md. Là où requirements.md exprime l'attendu fonctionnel, le mode opératoire et les règles de gestion fournis par le Product Owner business, le présent document précise les choix techniques associés : rendu visuel détaillé, API externes et leurs URL, codes HTTP précis, délais et débounce, mécanismes de sécurité (jetons, hachage, clés), politique de cache, fallbacks de calcul, rendu cartographique et documentaire.

Ces exigences sont destinées à être définies et arbitrées conjointement par le PO business et le PO IT, dans un second temps, une fois le besoin fonctionnel stabilisé. Elles peuvent évoluer sans remettre en cause le besoin métier tant que le comportement observable décrit dans requirements.md est respecté.

Le document est organisé en miroir des exigences de requirements.md : chaque section reprend le même numéro et le même titre suivi de « — aspects techniques », afin de faciliter les références croisées. Seules les exigences comportant effectivement des critères techniques apparaissent ici. Les exigences purement métier (Requirements 4, 18) ne figurent pas dans ce document.

Précision des distances : les aspects techniques du paramètre Precision_Distance (endpoint, entité, formule d'arrondi) sont résumés au Requirement 22 ci-dessous, avec renvoi vers la spec séparée precision-distances-km (design.md) pour le détail complet (DTOs, service, migration).


Glossary (termes techniques)

  • BAN : Base Adresses Nationale, le référentiel officiel des adresses françaises accessible via l'API publique https://api-adresse.data.gouv.fr. Fournit l'autocomplétion d'adresses et les coordonnées géographiques (latitude, longitude) sans clé d'authentification. Support technique du Geocodeur défini dans requirements.md.
  • ORS : OpenRouteService, l'API externe utilisée exclusivement pour le calcul d'itinéraire routier entre deux points géographiques dont les coordonnées sont déjà connues.
  • Haversine : Formule orthodromique de calcul de distance à vol d'oiseau entre deux points, utilisée en repli (fallback) lorsque le calcul d'itinéraire routier échoue.
  • Leaflet.js : Bibliothèque JavaScript de rendu cartographique interactif employée par le Frontend pour la Carte.
  • OpenStreetMap : Fournisseur des tuiles cartographiques (fond de carte) affichées via Leaflet.js.
  • GeoJSON : Format d'échange des géométries d'itinéraire (liste de points) transmises par le Backend au Frontend.
  • JWT : JSON Web Token signé (HS256) émis par le Backend à la connexion, portant l'identifiant du Compte et une durée de validité configurable (12 heures par défaut). Support technique de la Session définie dans requirements.md.
  • Cache_Adresses : La table de base de données stockant les couples (adresse textuelle normalisée BAN, coordonnées géographiques) des adresses déjà saisies, soumise à une politique de rétention LRU.
  • Mermaid : Syntaxe de définition de diagrammes (ex. graph TB) rendue graphiquement lors de l'affichage des Documents_Specification.
  • ParametresApplication : L'entité backend singleton (une seule ligne, Id = 1, sur le modèle de Profil/Compte) portant la colonne PrecisionDistanceKm, contrainte par un CHECK SQL IN (0, 1, 2). Détaillée intégralement dans la spec precision-distances-km, design.md.

Requirements

Requirement 1: Saisie d'un trajet — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 1.

Acceptance Criteria

  1. WHEN l'utilisateur soumet le formulaire de saisie avec tous les champs obligatoires valides, THE Frontend SHALL envoyer les données du Trajet au Backend via l'API dans un délai maximum de 3 secondes.
  2. IF le Backend reçoit un Trajet dont la date est absente ou dont le format ne correspond pas à JJ/MM/AAAA, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message indiquant que la date est absente ou invalide.
  3. IF le Backend reçoit un Trajet dont l'adresse de départ ou l'adresse d'arrivée est absente, vide ou dépasse 255 caractères, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message identifiant le champ concerné.
  4. IF le Backend reçoit un Trajet dont le commentaire dépasse 500 caractères, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message indiquant que le commentaire est trop long.
  5. IF le Frontend ne reçoit pas de réponse du Backend dans un délai de 10 secondes après la soumission, THEN THE Frontend SHALL afficher un message d'erreur indiquant que le serveur est indisponible et conserver les données saisies dans le formulaire.
  6. WHEN l'utilisateur saisit au moins 3 caractères dans le champ adresse de départ ou adresse d'arrivée, THE Frontend SHALL interroger l'API BAN (https://api-adresse.data.gouv.fr/search/) et afficher une liste de suggestions d'adresses françaises correspondant à la saisie dans un délai de 2 secondes.
  7. WHEN l'utilisateur sélectionne une suggestion de l'API BAN, THE Frontend SHALL stocker les coordonnées géographiques (latitude, longitude) associées à l'adresse sélectionnée pour transmission au Backend.
  8. WHEN l'utilisateur soumet le formulaire avec une adresse sélectionnée via l'API BAN, THE Frontend SHALL transmettre au Backend les coordonnées géographiques (latitude, longitude) de chaque adresse en même temps que le texte de l'adresse.
  9. WHEN l'utilisateur sélectionne une Adresse_Nommee dans le sélecteur associé à un champ adresse, THE Frontend SHALL associer les coordonnées géographiques (latitude, longitude) de l'Adresse_Nommee pour transmission au Backend.

Requirement 2: Calcul automatique de la distance — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 2.

Acceptance Criteria

  1. WHEN le Backend reçoit un Trajet valide dont les coordonnées de départ et d'arrivée sont toutes deux connues, THE Calculateur_Distance SHALL calculer la Distance via l'API ORS en utilisant ces coordonnées.
  2. WHEN OpenRouteService (ORS) retourne avec succès la distance routière entre les deux points géographiques d'un Trajet, THE Calculateur_Distance SHALL utiliser cette valeur comme Distance du Trajet.
  3. IF OpenRouteService (ORS) ne parvient pas à calculer la distance routière entre les coordonnées de départ et d'arrivée, THEN THE Calculateur_Distance SHALL calculer la Distance en utilisant la formule orthodromique (Haversine) comme fallback, sans retourner d'erreur à l'utilisateur.
  4. IF le Backend reçoit un Trajet dont les coordonnées de départ ou d'arrivée sont absentes (adresse saisie manuellement sans BAN), THEN THE Backend SHALL tenter le géocodage de l'adresse manquante via l'API BAN avant d'appeler ORS ; si le géocodage BAN échoue également, THE Backend SHALL stocker le Trajet avec une Distance nulle et retourner une réponse HTTP 201 avec un avertissement indiquant que la distance n'a pas pu être calculée.
  5. IF le Calculateur_Distance ne reçoit pas de réponse d'OpenRouteService (ORS) dans un délai de 10 secondes, THEN THE Backend SHALL appliquer le fallback Haversine et stocker la Distance calculée orthodromiquement, sans erreur bloquante pour l'utilisateur.

Requirement 3: Consultation du résumé mensuel — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 3.

Acceptance Criteria

  1. IF le Backend reçoit une requête de Résumé_Mensuel avec un mois hors de la plage 1–12 ou une année hors de la plage 2000–2100, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message descriptif.
  2. WHEN le Backend calcule avec succès un Résumé_Mensuel, THE Backend SHALL retourner une réponse HTTP 200 avec le Résumé_Mensuel correspondant.

Requirement 5: Modification et suppression d'un trajet — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 5.

Acceptance Criteria

  1. WHEN l'utilisateur demande la modification d'un Trajet existant, THE Frontend SHALL afficher le formulaire de saisie pré-rempli avec les données actuelles du Trajet dans un délai de 500 ms.
  2. WHEN un Trajet est modifié ou supprimé, THE Frontend SHALL mettre à jour l'affichage du Résumé_Mensuel dans un délai de 1000 ms sans nécessiter un rechargement complet de la page.
  3. IF un Trajet possède une Distance nulle suite à l'absence de coordonnées, THEN THE Backend SHALL tenter de recalculer la Distance en utilisant les coordonnées disponibles via le Cache_Adresses ou l'API BAN pour les nouvelles adresses soumises.

Requirement 6: Persistance et cohérence des données — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 6.

Acceptance Criteria

  1. THE Backend SHALL persister l'ensemble des Trajets dans une base de données relationnelle.
  2. WHEN un Trajet est supprimé, THE Backend SHALL viser la mise à jour du Résumé_Mensuel et du Résumé_Annuel correspondants dans un délai de 5 secondes ; ce délai est un objectif de performance et non une contrainte stricte lorsque la charge du système l'empêche, la cohérence des données restant prioritaire.

Requirement 7: Export PDF des résumés — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 7.

Acceptance Criteria

  1. IF le Backend ne parvient pas à générer le fichier PDF dans un délai de 15 secondes, THEN THE Backend SHALL retourner une erreur et THE Frontend SHALL afficher un message indiquant que la génération du PDF a échoué.
  2. WHEN le Backend compose l'en-tête d'un Export_PDF (mensuel ou annuel), THE Backend SHALL disposer l'en-tête sur une rangée comportant le logo carré aligné en haut à gauche à une largeur de 120 pt, puis à droite du logo un bloc titre (titre "RAPPORT DE TRAJETS" en 16 pt gras et sous-titre spécifique en 11 pt) centré sur l'espace restant, le bloc d'infos étant placé sous le bloc titre, et SHALL tracer un trait séparateur horizontal sur toute la largeur de la page sous l'en-tête.
  3. WHEN le Backend compose le pied de page d'un Export_PDF (mensuel ou annuel), THE Backend SHALL afficher la Mention_Legale en police de 5 pt, en gris, justifiée, positionnée au-dessus de la pagination « Page X / Y ».
  4. WHEN le Backend compose la colonne "A/R" de la table des Trajets d'un Export_PDF mensuel, THE Backend SHALL afficher le marqueur « X » (et non une coche Unicode, non rendue par la police par défaut Lato) pour un Trajet Aller_Retour.
  5. WHEN le Backend définit les largeurs de colonnes de la table des Trajets d'un Export_PDF mensuel, THE Backend SHALL dimensionner la colonne "A/R" à sa largeur minimale, la colonne "Kms" pour afficher jusqu'à « 9 999 » (avec séparateur de milliers), et la colonne des adresses de façon maximisée pour que l'adresse de départ et l'adresse d'arrivée tiennent majoritairement sur deux lignes.
  6. WHEN le Backend compose le bloc d'infos de l'en-tête d'un Export_PDF annuel, THE Backend SHALL insérer un espace après la ligne « Véhicule » et présenter « Barème applicable » et « Total kilométrique de l'année » sur deux colonnes côte à côte.
  7. WHEN le Backend compose la fin d'un Export_PDF annuel, THE Backend SHALL conserver la ligne « Formule réelle » alignée à gauche, insérer un espace, puis centrer la ligne « Régularisation (réel − payé) » sur la largeur de la page.

Requirement 8: Visualisation des trajets sur une carte — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 8.

Acceptance Criteria

  1. WHEN la carte est affichée pour une journée donnée, THE Frontend SHALL rendre la Carte via Leaflet.js sur un fond de tuiles OpenStreetMap, et représenter chaque Trajet par un tracé polyline avec marqueurs de départ et d'arrivée.
  2. IF la géométrie d'itinéraire d'un Trajet n'est pas disponible (coordonnées manquantes ou ORS indisponible), THEN THE Frontend SHALL afficher ce Trajet comme une ligne droite entre le point de départ et le point d'arrivée, avec une indication visuelle que l'itinéraire est approximatif.
  3. WHEN le Backend reçoit une requête de trajets pour une journée donnée avec visualisation, THE Backend SHALL retourner pour chaque Trajet la géométrie de l'itinéraire sous forme de liste de points GeoJSON si disponible dans le Cache_Adresses.
  4. IF le service de carte (Leaflet.js ou les tuiles OpenStreetMap) est indisponible ou inaccessible, THEN THE Frontend SHALL afficher un message d'erreur indiquant que la carte ne peut pas être chargée et proposer à l'utilisateur de réessayer.

Requirement 9: Cache et réutilisation des adresses géocodées — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 9.

Acceptance Criteria

  1. WHEN l'utilisateur sélectionne une adresse via l'autocomplétion BAN lors de la création ou modification d'un Trajet, THE Backend SHALL stocker dans le Cache_Adresses le libellé normalisé BAN de l'adresse, sa latitude et sa longitude si cette adresse n'y est pas déjà présente.
  2. WHEN le Backend reçoit un Trajet dont l'adresse correspond exactement à une entrée du Cache_Adresses, THE Backend SHALL utiliser les coordonnées du Cache_Adresses sans appeler l'API BAN.
  3. WHEN l'utilisateur saisit au moins 3 caractères dans un champ adresse, THE Frontend SHALL d'abord interroger le Cache_Adresses local via le Backend pour afficher les suggestions d'adresses déjà connues, puis compléter avec les résultats de l'API BAN si le Cache_Adresses retourne moins de 5 suggestions.
  4. IF le Cache_Adresses contient plus de 1 000 entrées, THEN THE Backend SHALL conserver les 1 000 entrées les plus récemment utilisées et supprimer les plus anciennes (politique LRU).
  5. THE Cache_Adresses SHALL stocker pour chaque adresse : le libellé normalisé BAN (255 caractères maximum), la latitude (précision de 6 décimales), la longitude (précision de 6 décimales) et la date de dernière utilisation.

Requirement 10: Profil utilisateur, adresse de domicile et véhicules — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 10.

Acceptance Criteria

  1. IF le matricule reçu dépasse 8 caractères, THEN THE Backend SHALL rejeter le matricule avec une erreur HTTP 400.
  2. WHEN l'utilisateur sauvegarde une Adresse_Domicile, THE Backend SHALL géocoder l'adresse via l'API BAN pour obtenir ses coordonnées et les stocker dans le Profil ainsi que dans le Cache_Adresses ; si le géocodage BAN échoue, THE Backend SHALL persister l'Adresse_Domicile textuelle sans coordonnées.
  3. WHEN l'utilisateur modifie l'Adresse_Domicile dans le Profil et sauvegarde, THE Backend SHALL re-géocoder la nouvelle adresse via l'API BAN pour mettre à jour les coordonnées dans le Profil et dans le Cache_Adresses.

Requirement 11: Insertion d'un trajet entre deux saisies existantes — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 11.

Acceptance Criteria

  1. WHEN l'utilisateur sélectionne une Adresse_Nommee dans le formulaire d'insertion pour un champ adresse, THE Frontend SHALL associer les coordonnées géographiques (latitude, longitude) de l'Adresse_Nommee pour transmission au Backend.
  2. WHERE l'insertion utilise l'autocomplétion pour une nouvelle adresse, THE Frontend SHALL s'appuyer sur l'API BAN pour proposer les suggestions et récupérer les coordonnées, selon les mêmes modalités techniques que le formulaire de saisie (voir Requirement 1).

Requirement 12: Navigation temporelle et mise en page — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 12.

Acceptance Criteria

  1. WHEN l'utilisateur change de mois via le Sélecteur_Temporel, survole un Trajet d'une autre journée, ou change de Véhicule, THE Frontend SHALL mettre à jour la liste, le Panneau_Totaux et la Carte concernés dans un délai de 1000 ms sans rechargement complet de la page.
  2. WHEN l'utilisateur change de Véhicule sélectionné, THE Frontend SHALL mettre à jour la liste mensuelle des Trajets, le Panneau_Totaux et la Carte dans un délai de 1000 ms sans rechargement complet de la page.

Requirement 13: Barème kilométrique et indication de versement — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 13.

Acceptance Criteria

  1. WHEN le Backend calcule le Montant_Previsionnel_Mensuel ou le Montant_Previsionnel_Annuel, THE Backend SHALL utiliser des distances déjà arrondies selon Precision_Distance (et non les distances brutes), conformément à la spec precision-distances-km, Requirements 6 et 7.

Requirement 14: Montant réglé mensuel et régularisation annuelle — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 14.

Acceptance Criteria

  1. IF l'utilisateur saisit un Montant_Regle négatif, THEN THE Backend SHALL rejeter la saisie avec une erreur HTTP 400.

Requirement 15: Carnet d'adresses nommées — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 15.

Acceptance Criteria

  1. WHEN l'utilisateur saisit au moins 3 caractères dans le champ adresse d'une Adresse_Nommee, THE Frontend SHALL interroger l'API BAN après un délai d'inactivité de 300 millisecondes et afficher au maximum 5 suggestions.
  2. WHEN l'utilisateur sélectionne une suggestion de l'API BAN lors de la saisie du champ adresse d'une Adresse_Nommee, THE Frontend SHALL pré-remplir le champ avec le libellé normalisé et associer les coordonnées géographiques (latitude, longitude) pour transmission au Backend.
  3. WHEN le Backend reçoit une Adresse_Nommee valide, THE Backend SHALL persister en base de données la Dénomination, le texte d'adresse et, lorsqu'elles sont disponibles, les coordonnées géographiques (latitude, longitude).
  4. IF le Backend reçoit une Adresse_Nommee dont la Dénomination est absente, vide ou dépasse 100 caractères, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message indiquant que la Dénomination est absente ou invalide.
  5. IF le Backend reçoit une Adresse_Nommee dont la Dénomination est identique, après normalisation (suppression des espaces de début et de fin, comparaison insensible à la casse et aux accents), à celle d'une Adresse_Nommee déjà enregistrée, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message indiquant que la Dénomination est déjà utilisée.
  6. IF le Backend reçoit une Adresse_Nommee dont le texte d'adresse est absent, vide ou dépasse 255 caractères, THEN THE Backend SHALL retourner une erreur HTTP 400 avec un message indiquant que l'adresse est absente ou invalide.
  7. WHEN le Backend persiste une Adresse_Nommee dont les coordonnées géographiques sont disponibles, THE Backend SHALL enregistrer le couple (libellé normalisé, latitude, longitude) dans le Cache_Adresses s'il n'y est pas déjà présent, afin que cette adresse soit réutilisable et mise en cache.
  8. WHEN le Backend reçoit une Adresse_Nommee dont le texte d'adresse correspond, après normalisation (suppression des espaces de début et de fin, comparaison insensible à la casse et aux accents), à une entrée du Cache_Adresses, THE Backend SHALL réutiliser les coordonnées du Cache_Adresses sans appeler l'API BAN.
  9. WHEN l'utilisateur modifie le texte d'adresse d'une Adresse_Nommee existante et enregistre, et que ce texte ne correspond à aucune entrée du Cache_Adresses après normalisation, THE Backend SHALL re-géocoder la nouvelle adresse via l'API BAN dans un délai maximal de 5 secondes afin de rafraîchir les coordonnées géographiques (latitude, longitude) de l'Adresse_Nommee.
  10. IF l'API BAN est indisponible ou ne répond pas dans le délai de 5 secondes lors du géocodage ou du re-géocodage d'une Adresse_Nommee, THEN THE Backend SHALL persister l'Adresse_Nommee sans coordonnées géographiques et retourner une réponse indiquant que les coordonnées n'ont pas pu être obtenues.
  11. WHEN l'utilisateur active la création d'une Adresse_Nommee (bouton « Ajouter une adresse ») ou la modification d'une Adresse_Nommee existante depuis la liste, THE Frontend SHALL présenter le formulaire de saisie dans une fenêtre modale superposée à la liste, et SHALL fermer cette fenêtre modale après un enregistrement réussi, après annulation par l'utilisateur, ou lors d'un clic sur l'arrière-plan de la fenêtre modale.
  12. THE Frontend SHALL présenter la liste des Adresses_Nommées sous forme d'une grille de cartes, chaque carte disposant d'un contour et d'une ombre portée.

Requirement 16: Initialisation du profil à la première utilisation — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 16.

Acceptance Criteria

  1. THE Backend SHALL exposer un indicateur de configuration du Profil (estConfigure) valant vrai lorsque le Profil est un Profil_Configure et faux dans le cas contraire.
  2. WHEN l'utilisateur valide le parcours d'Onboarding avec un Profil et au moins un Véhicule valides, THE Backend SHALL retourner un indicateur estConfigure valant vrai.
  3. WHEN le Backend confirme l'enregistrement d'un Profil_Configure, THE Frontend SHALL naviguer vers la Vue_Consultation dans un délai de 1000 ms.
  4. IF la récupération de l'indicateur estConfigure échoue lors de l'ouverture de l'Application, THEN THE Frontend SHALL afficher un message d'erreur indiquant un problème de connexion au serveur et proposer de réessayer, sans présenter la Vue_Consultation.

Requirement 17: Authentification par compte unique — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 17.

Acceptance Criteria

  1. WHEN l'utilisateur soumet la création du Compte avec une Adresse_Email valide et un Mot_De_Passe d'au moins 8 caractères, THE Backend SHALL créer le Compte en stockant uniquement un hachage salé du Mot_De_Passe (jamais le mot de passe en clair).
  2. WHEN l'utilisateur soumet la page de connexion avec des identifiants correspondant au Compte, THE Backend SHALL émettre un JWT signé (HS256) portant l'identifiant du Compte et une durée de validité configurable (12 heures par défaut), et THE Frontend SHALL conserver ce jeton pour authentifier les appels suivants.
  3. THE Backend SHALL protéger tous les endpoints de données (Trajets, résumés, totaux, profil, véhicules, barème, carnet d'adresses, export PDF) en exigeant un JWT valide, et SHALL retourner une erreur HTTP 401 en l'absence de jeton valide.
  4. WHEN le Backend valide un JWT dont le Compte associé n'existe plus, THE Backend SHALL rejeter la requête (jeton invalide).
  5. THE Backend SHALL exposer un endpoint permettant au Frontend de valider la Session courante (existence du Compte et validité du jeton), utilisé par la garde de navigation du Frontend avant d'afficher les vues protégées.
  6. IF l'envoi de l'e-mail de réinitialisation n'est pas possible (service e-mail non configuré ou indisponible), THEN THE Backend SHALL journaliser le lien de réinitialisation en repli (fallback) afin que la réinitialisation reste possible, sans faire échouer la demande.
  7. WHEN l'utilisateur suit un Jeton_Reinitialisation valide et fournit un nouveau Mot_De_Passe valide, THE Backend SHALL remplacer le hachage du Mot_De_Passe du Compte et invalider le Jeton_Reinitialisation.
  8. THE Backend SHALL exiger la présence d'une clé secrète de signature JWT au démarrage (variable d'environnement obligatoire) et SHALL refuser de démarrer si elle est absente.
  9. WHEN la case « Se souvenir de moi » est cochée lors d'une connexion réussie, THE LoginComponent SHALL écrire l'Adresse_Email saisie dans le localStorage du navigateur sous la clé schotziad.login.emailMemorise via setItem, et SHALL n'y stocker que l'Adresse_Email (jamais le Mot_De_Passe).
  10. WHEN la case « Se souvenir de moi » est décochée lors d'une connexion réussie, THE LoginComponent SHALL supprimer la clé schotziad.login.emailMemorise du localStorage du navigateur via removeItem.
  11. WHEN le LoginComponent est initialisé (ngOnInit), IF la clé schotziad.login.emailMemorise est présente et non vide dans le localStorage, THEN THE LoginComponent SHALL pré-remplir le champ Adresse_Email avec cette valeur et cocher la case « Se souvenir de moi ».
  12. WHERE l'Identifiant_Mémorisé est conservé dans le localStorage du navigateur, THE LoginComponent SHALL s'appuyer sur la portée propre du localStorage (limitée à l'origine — scheme, host et port — et au navigateur courant) pour réaliser l'absence de pré-remplissage sur une autre machine ou un autre navigateur tant qu'aucune connexion « se souvenir » n'y a eu lieu.
  13. IF un accès au localStorage échoue (navigation privée, quota dépassé ou stockage désactivé), THEN THE LoginComponent SHALL intercepter l'erreur et l'ignorer silencieusement, la mémorisation de l'Identifiant_Mémorisé restant sans effet sans faire échouer la connexion ni le chargement de la page de connexion.

Requirement 19: Consultation des documents de spécification — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 19.

Acceptance Criteria

  1. WHEN l'utilisateur sélectionne un Document_Specification dans le menu latéral, THE Frontend SHALL rendre le contenu à partir de sa source Markdown (titres, listes, tableaux, blocs de code), ET SHALL rendre les blocs de diagramme Mermaid (ex. graph TB) sous forme de schémas graphiques.
  2. THE Backend SHALL exposer les Documents_Specification en lecture seule via une API, en restreignant les documents accessibles à une liste fermée (exigences, conception, tâches) afin d'empêcher tout accès à un fichier arbitraire.
  3. THE Backend SHALL exiger un utilisateur authentifié (JWT valide) pour accéder aux Documents_Specification ; en l'absence de jeton valide, THE Backend SHALL retourner une erreur HTTP 401.
  4. IF l'utilisateur demande un Document_Specification inconnu ou absent, THEN THE Backend SHALL retourner une erreur HTTP 404.
  5. THE Frontend SHALL assainir le contenu HTML issu du rendu Markdown avant affichage, afin d'éviter l'injection de contenu actif.
  6. IF un diagramme Mermaid ne peut pas être rendu (syntaxe non reconnue), THEN THE Frontend SHALL conserver l'affichage du bloc de code brut correspondant sans empêcher le rendu des autres diagrammes ni du reste du document.

Requirement 20: Changement de mot de passe par un utilisateur authentifié — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 20.

Acceptance Criteria

  1. WHEN l'utilisateur soumet le changement de Mot_De_Passe, THE Backend SHALL exiger un jeton JWT valide pour la vérification du mot de passe actuel.
  2. IF le mot de passe actuel fourni ne correspond pas au Compte, THEN THE Backend SHALL rejeter le changement avec une erreur HTTP 400 explicite, sans modifier le Mot_De_Passe existant.
  3. THE Backend SHALL exposer l'endpoint de changement de mot de passe sur un contrôleur soumis à l'autorisation globale (utilisateur authentifié), et non sur un contrôleur autorisant les accès anonymes, afin qu'un [Authorize] posé sur une seule action ne puisse pas être contourné par une déclaration [AllowAnonymous] au niveau de la classe.

Requirement 21: Navigation utilisateur (avatar, paramétrage, maintenance) — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 21.

Acceptance Criteria

  1. THE Frontend SHALL masquer entièrement la barre de navigation (y compris l'Avatar_Utilisateur) sur les pages non authentifiées (connexion, inscription, mot de passe oublié, réinitialisation), MÊME SI un jeton résiduel expiré ou invalide est encore présent localement, la présence locale d'un jeton ne garantissant pas la validité réelle de la Session sur ces pages.
  2. THE Frontend SHALL proposer, sur chaque champ de saisie d'un Mot_De_Passe (connexion, inscription, réinitialisation, changement de mot de passe), un contrôle permettant de basculer l'affichage entre masqué et visible, afin que l'utilisateur puisse vérifier la saisie ; ce contrôle SHALL présenter un rendu visuel identique à celui des autres champs de saisie du formulaire.

Requirement 22: Précision configurable des distances — aspects techniques

Exigence fonctionnelle : voir requirements.md, Requirement 22. Détail complet (DTOs, service, migration) dans la spec precision-distances-km, design.md.

Acceptance Criteria

  1. THE Backend SHALL exposer les opérations de lecture et de modification de Precision_Distance via un endpoint GET/PUT /api/parametres-application, protégé par le même filtre d'autorisation JWT global que les autres endpoints de données, retournant 401 en l'absence de jeton valide.
  2. IF le Backend reçoit sur PUT /api/parametres-application une valeur de Precision_Distance différente de 0, 1 ou 2, THEN THE Backend SHALL retourner une erreur HTTP 400.
  3. WHEN le Backend traite avec succès une requête sur GET/PUT /api/parametres-application, THE Backend SHALL retourner un code HTTP 200 accompagné de la configuration courante.
  4. THE Backend SHALL persister Precision_Distance dans une entité singleton ParametresApplication (une seule ligne, Id = 1), avec une contrainte CHECK SQL garantissant PrecisionDistanceKm IN (0, 1, 2).
  5. THE Backend SHALL calculer toute distance arrondie selon la formule Ceiling(distanceBrute × 10^precision) / 10^precision, appliquée à la lecture, jamais à l'écriture de la colonne Trajet.Distance.