PD-239 — Confrontation Step 5 (v1)¶
1. Objectif¶
Analyser les écarts identifiés dans la review du plan d'implémentation (PD-239-plan-review.md) et les confronter aux documents sources pour valider ou invalider chaque constat.
2. Documents confrontés¶
- PD-239-specification.md (v2)
- PD-239-tests.md (v2)
- PD-239-plan.md
- PD-239-code-contracts.yaml
- PD-239-plan-review.md
3. Analyse des écarts¶
ECT-S5-01 — Format d'erreur non conforme (BLOQUANT)¶
Constat review : Le plan impose {statusCode, timestamp, path, method, message, code} alors que la spec exige {error, message}.
Confrontation : - Spec §4 INV-239-06 : "Le format d'erreur DOIT être {error: "ERR-239-*", message: "..."}." - Spec §11 Contrat API : Réponses erreur listées sans détail de format enrichi. - Plan §8.3 : Format {statusCode, timestamp, path, method, message, code} avec champ code (pas error).
Verdict : ✅ CONFIRMÉ
Le plan utilise code au lieu de error. La spec contractuelle exige strictement {error, message}. Les champs supplémentaires (statusCode, timestamp, path, method) peuvent être tolérés comme enrichissement, mais le renommage error → code est une non-conformité.
Impact : Le client mobile PD-106 attend error, recevra code. Intégration en échec.
Correction requise : Renommer code en error dans le format d'erreur du plan et du code contract.
ECT-S5-02 — Code contract format incompatible (BLOQUANT)¶
Constat review : Code contract password-change-filter fixe un format différent de la spec.
Confrontation : - Code contract password-change-filter invariant : "Format: {statusCode, timestamp, path, method, message, code}" - Spec §4 INV-239-06 : "Le format d'erreur DOIT être {error: "ERR-239-*", message: "..."}."
Verdict : ✅ CONFIRMÉ
C'est le même écart que ECT-S5-01, manifesté dans le code contract. La correction de ECT-S5-01 doit être propagée au code contract.
Correction requise : Mettre à jour le code contract pour {error, message} (avec enrichissements optionnels mais error obligatoire).
ECT-S5-03 — Rate limiting non spécifié (MAJEUR)¶
Constat review : Le plan introduit MfaRateLimitGuard non prévu par la spec.
Confrontation : - Spec §2 Périmètre Inclus : Aucune mention de rate limiting. - Spec §2 Périmètre Exclu : Rate limiting non explicitement exclu. - Plan §11.2 : "Réutiliser le pattern MfaRateLimitGuard existant pour limiter les tentatives."
Verdict : ⚠️ PARTIELLEMENT CONFIRMÉ
Le rate limiting est effectivement non spécifié dans PD-239. Cependant, c'est une mesure de sécurité standard pour les opérations sensibles (changement de mot de passe). La formulation "points de vigilance" du plan suggère une recommandation, pas une exigence contractuelle.
Impact : Si implémenté sans spécification, risque de comportement non documenté. Si omis, risque de brute force.
Recommandation : Clarifier que le rate limiting est optionnel/recommandé et non contractuel, OU ajouter explicitement dans une future spec. Pour PD-239, retirer de la section contractuelle et placer en note d'implémentation.
ECT-S5-04 — Observable invalidation ≤30s insuffisant (MAJEUR)¶
Constat review : Pas de mécanisme d'observabilité pour prouver l'invalidation effective sous 30 secondes.
Confrontation : - Spec §4 INV-239-05 : "toutes les sessions utilisateur DOIVENT être invalidées dans un délai de 30 secondes maximum." - Plan §6 Mapping INV-239-05 : "SessionRevocationStore.revokeAllUserSessions()" avec observable "Logs revocation, TTL 24h". - Tests T-239-NOM-01 : "Toute session/token précédent de U1 est invalidé (refus d'un token antérieur)."
Verdict : ⚠️ PARTIELLEMENT CONFIRMÉ
Le test T-239-NOM-01 valide l'invalidation fonctionnelle (token antérieur refusé) mais ne prouve pas la borne de 30 secondes. Cependant : 1. Le test e2e exécuté immédiatement après l'appel suffit à prouver l'invalidation dans un délai court. 2. La borne de 30s est une SLA opérationnelle, pas une propriété testable en e2e sans instrumentation temporelle.
Impact : Le test fonctionnel suffit pour le scénario nominal. La SLA 30s relève du monitoring opérationnel.
Recommandation : Ajouter une note explicite dans le plan que la SLA 30s est garantie par l'architecture synchrone de revokeAllUserSessions() et vérifiable via logs opérationnels (hypothèse H-IMPL-03 déjà listée).
ECT-S5-05 — Confusion ReauthService.verifyPassword() (MAJEUR)¶
Constat review : Ambiguïté sur l'utilisation de ReauthService.verifyPassword() pour valider l'ancien mot de passe.
Confrontation : - Spec §4 INV-239-03 : "L'ancien mot de passe DOIT être vérifié avant modification." - Plan §5 étape 4 : "PasswordChangeService.verifyOldPassword() [...] Vérifie oldPassword via SRP verifier (timingSafeEqual)" - Plan §3.3 : ReauthService listée avec usage "verifyPassword()" - Code contract password-change-service dependencies : "reauth-service # existant (PD-238)"
Verdict : ✅ CONFIRMÉ
Il y a effectivement une ambiguïté : 1. Le flux (§5) mentionne PasswordChangeService.verifyOldPassword() avec SRP verifier. 2. Les dépendances listent ReauthService.verifyPassword(). 3. Il n'est pas clair si c'est la même fonction ou deux mécanismes distincts.
Le reauth token (PD-238) prouve que l'utilisateur s'est réauthentifié récemment, mais INV-239-03 exige de vérifier l'ancien mot de passe fourni dans le payload avant modification. Ce sont deux choses distinctes.
Impact : Si ReauthService.verifyPassword() est utilisé, il doit prendre en paramètre l'oldPassword du payload, pas réutiliser le mécanisme reauth token.
Correction requise : Clarifier dans le plan que verifyOldPassword() dans PasswordChangeService utilise l'oldPassword du payload (pas le reauth token) pour vérifier via SRP verifier. La dépendance ReauthService peut être pour la vérification du reauth token (guard) et non pour la vérification de l'ancien mot de passe.
ECT-S5-06 — Injection erreurs Keycloak non détaillée (MINEUR)¶
Constat review : Le plan ne précise pas comment injecter des erreurs Keycloak déterministes pour T-239-ERR-08.
Confrontation : - Tests T-239-ERR-08 : "Une erreur Keycloak déterministe est injectée (400, 401/403, 404, 5xx)." - Code contract password-change-tests-unit : "Mocker Keycloak et SessionRevocationStore" - Code contract password-change-tests-e2e : Aucun détail sur mocking Keycloak.
Verdict : ✅ CONFIRMÉ
Le plan et les code contracts mentionnent le mocking pour les tests unitaires mais pas pour les tests e2e. T-239-ERR-08 requiert une injection déterministe.
Impact : Mineur. C'est un détail d'implémentation des tests, pas un écart contractuel.
Recommandation : Ajouter une note sur le mécanisme d'injection (mock Keycloak en e2e ou test via mock service) dans le code contract des tests e2e.
4. Synthèse de la confrontation¶
| ID | Écart | Gravité review | Verdict confrontation | Action |
|---|---|---|---|---|
| ECT-S5-01 | Format code vs error | BLOQUANT | ✅ CONFIRMÉ | Corriger plan + code contract |
| ECT-S5-02 | Code contract incompatible | BLOQUANT | ✅ CONFIRMÉ (doublon ECT-S5-01) | Même correction |
| ECT-S5-03 | Rate limiting non spécifié | MAJEUR | ⚠️ PARTIELLEMENT CONFIRMÉ | Clarifier comme recommandation |
| ECT-S5-04 | Observable ≤30s | MAJEUR | ⚠️ PARTIELLEMENT CONFIRMÉ | Ajouter note architecture synchrone |
| ECT-S5-05 | Confusion ReauthService | MAJEUR | ✅ CONFIRMÉ | Clarifier flux et dépendances |
| ECT-S5-06 | Injection Keycloak tests | MINEUR | ✅ CONFIRMÉ | Ajouter note dans code contract e2e |
5. Écarts confirmés nécessitant correction¶
Corrections BLOQUANTES (2 écarts, 1 correction)¶
ECT-S5-01 + ECT-S5-02 : Renommer code en error dans : - Plan §8.3 : Format réponse erreur - Code contract password-change-filter : Invariant format
Corrections MAJEURES (1 écart confirmé)¶
ECT-S5-05 : Clarifier dans le plan §5 et §3.3 que : - PasswordChangeService.verifyOldPassword() vérifie l'oldPassword du payload via SRP verifier - ReauthService n'est PAS utilisé pour cette vérification (uniquement pour le guard reauth token) - Retirer ReauthService des dépendances de password-change-service (ou préciser son usage distinct)
Ajustements MINEURS (3 écarts)¶
ECT-S5-03 : Reformuler §11.2 comme recommandation non contractuelle. ECT-S5-04 : Ajouter note sur garantie architecturale synchrone. ECT-S5-06 : Ajouter mécanisme d'injection dans code contract tests e2e.
6. Recommandation PMO¶
Verdict suggéré : NON_CONFORME
Motif : 2 écarts BLOQUANTS confirmés (format d'erreur non conforme à INV-239-06) + 1 écart MAJEUR confirmé (ambiguïté sur vérification ancien mot de passe INV-239-03).
Corrections ciblées identifiées, permettant une re-soumission rapide.