Ajout de l'authentification (compte unique, JWT, reset par email)

Application mono-utilisateur : inscription unique, connexion par JWT (12 h),
protection de toutes les routes de données, réinitialisation de mot de passe
par email avec repli de journalisation, onboarding réorganisé en deux étapes
(inscription → connexion → profil + véhicule).

Backend (SchotzIadKmTracker.Api) :
- Entités Compte (singleton) et ResetPasswordToken + migration AjoutAuthentification.
- Hachage PasswordHasher, JwtService (HS256, durée configurable), IEmailService
  (MailKit + repli LoggingEmailService selon Smtp:Host).
- AuthService (register 409 si compte existant, login 401 générique, forgot-password
  non-divulgation, reset à usage unique + expiration), AuthController (5 endpoints
  publics), DTOs + validateurs FluentValidation.
- Sécurité pipeline : JwtBearer + filtre d'autorisation global, UseAuthentication
  avant UseAuthorization ; /health et /api/auth/* publics.

Frontend (schotziad-km-tracker, zoneless + signals) :
- AuthService (localStorage), authInterceptor (Bearer + purge/redirection 401),
  authGuard, écrans Login/Register/ForgotPassword/ResetPassword, routes publiques
  et protection [authGuard, profilConfigureGuard].

Configuration : .env.example et docker-compose.yml (JWT__SecretKey, durées, Smtp__*).

Tests : 54 tests backend (propriétés FsCheck P1–P14, exemples, intégration
WebApplicationFactory) + tests frontend (AuthService, authGuard, authInterceptor,
ResetPasswordComponent). Suite complète au vert.

Spec : .kiro/specs/authentification (requirements, design, tasks).
This commit is contained in:
2026-09-14 09:07:08 +02:00
parent 0e6a97ca61
commit dd36bbc425
66 changed files with 6282 additions and 27 deletions
@@ -0,0 +1,654 @@
{
"pbtResults": {},
"executionHistory": {
"1.1 Créer les entités `Compte` et `ResetPasswordToken`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367186782
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367202818
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367320120
}
],
"1.2 Déclarer les DbSet et la configuration `OnModelCreating`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367186971
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367333400
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367482585
}
],
"1.3 Générer la migration EF `AjoutAuthentification`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187066
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368256169
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368286823
}
],
"2.1 Créer les classes d'options et les lier à la configuration": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187157
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367204303
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367321104
}
],
"3.1 Intégrer `PasswordHasher<Compte>` en DI": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187246
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367496182
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367655104
}
],
"4.1 Implémenter `IJwtService` / `JwtService`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187341
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367677548
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367800474
}
],
"5.1 Implémenter `IEmailService` et ses deux implémentations": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187432
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367334259
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367483557
}
],
"5.2 Câbler la sélection DI selon `Smtp__Host`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187526
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367817812
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367870446
}
],
"6.1 Créer les DTOs d'authentification et les validateurs FluentValidation": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187612
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367678436
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367801818
}
],
"6.2 Implémenter `IAuthService` / `AuthService`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187704
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367871329
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368076060
}
],
"7.1 Implémenter `AuthController` avec les 5 endpoints": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187799
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368077733
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368159447
}
],
"8.1 Configurer l'authentification JWT et l'autorisation globale": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367187890
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368160204
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368254979
}
],
"9. Checkpoint backend": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188045
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369554684
}
],
"10.1 Créer les modèles TS et `AuthService` (signals + localStorage)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188156
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367205129
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367322447
}
],
"10.2 Implémenter `authInterceptor` et l'enregistrer avant `timeoutInterceptor`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188248
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367335669
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367484979
}
],
"10.3 Implémenter `authGuard`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188340
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367337185
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367486334
}
],
"11.1 Implémenter `LoginComponent` (`/login`)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188465
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367337987
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367487169
}
],
"11.2 Implémenter `RegisterComponent` (`/register`, Etape 1)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188550
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367498335
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367651865
}
],
"11.3 Implémenter `ForgotPasswordComponent` (`/forgot-password`)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188651
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367498477
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367652784
}
],
"11.4 Implémenter `ResetPasswordComponent` (`/reset-password`)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188757
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367499473
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367654113
}
],
"12.1 Mettre à jour `app.routes.ts`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188847
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367679881
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367802793
}
],
"13.1 Mettre à jour `.env.example` et `docker-compose.yml`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367188965
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367680868
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367803900
}
],
"13.2 Vérifier les builds": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367189105
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368287520
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368322862
}
],
"14. Checkpoint final": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367189198
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369555493
}
],
"2. Backend — Options de configuration": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367321242
}
],
"10. Frontend — Service, modèles, interceptor et garde": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367486494
}
],
"11. Frontend — Écrans standalone (signals)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367654216
}
],
"3. Backend — Hachage des mots de passe": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367655230
}
],
"4. Backend — Service JWT": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367800614
}
],
"12. Frontend — Routes et onboarding en deux étapes": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367802947
}
],
"5. Backend — Service email": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789367870646
}
],
"6. Backend — DTOs, validateurs et service d'authentification": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368076248
}
],
"7. Backend — Controller d'authentification": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368159632
}
],
"8. Backend — Sécurité du pipeline": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368255118
}
],
"1. Backend — Modèle de données et persistance": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368286988
}
],
"13. Configuration et déploiement": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368322956
}
],
"3.2 Écrire le test de propriété du hachage": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368508497
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369503520
}
],
"6.3 Écrire le test de propriété inscription crée le compte": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368509798
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369504375
}
],
"8.2 Écrire le test d'intégration de protection des routes": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368511227
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369505830
}
],
"10.4 Écrire les tests de service, interceptor et garde": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789368512087
},
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369506703
}
],
"2.2 Écrire un test de liaison des options": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369516660
}
],
"4.2 Écrire le test de propriété émission/validation et claims": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369517664
}
],
"4.3 Écrire le test de propriété jeton expiré": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369519001
}
],
"4.4 Écrire le test de propriété signature invalide": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369519964
}
],
"5.3 Écrire le test de sélection DI de `IEmailService`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369521121
}
],
"6.4 Écrire le test de propriété inscription rejetée si compte existant": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369525805
}
],
"6.5 Écrire le test de propriété mot de passe trop court à l'inscription": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369527195
}
],
"6.6 Écrire le test de propriété connexion (émission/rejet)": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369528183
}
],
"6.7 Écrire le test de propriété non-divulgation forgot-password": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369529620
}
],
"6.8 Écrire le test de propriété expiration du jeton de reset": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369530512
}
],
"6.9 Écrire le test de propriété réinitialisation valide remplace le mot de passe": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369535219
}
],
"6.10 Écrire le test de propriété jeton de reset à usage unique": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369536677
}
],
"6.11 Écrire le test de propriété jeton de reset expiré ou inconnu": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369537543
}
],
"6.12 Écrire le test de propriété nouveau mot de passe trop court à la réinitialisation": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369538945
}
],
"6.13 Écrire les tests d'exemples de validation et d'exclusion du hash": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369540419
}
],
"8.3 Écrire le test d'intégration bout en bout": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369541873
}
],
"11.5 Écrire le test de lecture du token par `ResetPasswordComponent`": [
{
"executionId": "dc2d2428-de30-4d42-8076-ba61cb79b626",
"chatSessionId": "sess_20c9bee5-b332-43f8-922c-20b9225bb8d8",
"timestamp": 1789369543071
}
]
}
}