PD-32 — Confrontation Gate AMBIGUITY (Step 5)¶
1. Contexte¶
- Story ID : PD-32
- Gate : AMBIGUITY (Review Plan d'implementation)
- Date : 2026-02-05
- Reviewer initial : ChatGPT
- Confrontation : Claude (Orchestrateur)
2. Documents confrontes¶
| Document | Version | Hash/Date |
|---|---|---|
| PD-32-specification.md | v2 | 2026-02-05 |
| PD-32-tests.md | v2 | 2026-02-05 |
| PD-32-plan.md | v1 | 2026-02-05 |
| PD-32-code-contracts.yaml | v1 | 2026-02-05 |
| PD-32-plan-review.md | v1 | 2026-02-05 |
3. Analyse des ecarts identifies¶
DIV-01 : Champ plan expose dans GET (BLOQUANT)¶
Source : Review ChatGPT - Ecart #1 Observation ChatGPT : Le flux GET planifie retourne { name, email, plan, avatar_url, preferences } alors que plan est un champ protege.
Analyse confrontation : - Plan §2.1 step 8 : "Response 200 → { name, email, plan, avatar_url, preferences }" - Spec §3 : "plan est liste dans Champs proteges" - Spec CA-32-04 : "GET ne contient aucun champ sensible/protege" - Code contract INV-32-08 : "GET DOIT retourner UserProfileResponseDto (name, email, avatar_url)"
Verdict confrontation : ✅ VALIDE - Incoherence triple : Plan vs Spec, Plan vs Code Contract, Definition "protege" vs champs retournes - Le champ plan NE DOIT PAS apparaitre dans la reponse GET selon la spec - Le plan doit etre corrige pour retourner uniquement { name, email, avatar_url, preferences }
Gravite confirmee : BLOQUANT
DIV-02 : Tests acces croise irrealisables (BLOQUANT)¶
Source : Review ChatGPT - Ecart #3 Observation ChatGPT : TC-ERR-03/04 exigent une cible U2 explicite mais l'endpoint ne permet pas de cibler un autre utilisateur.
Analyse confrontation : - Tests §8 prerequis : "Mecanisme explicite de simulation d'acces croise en environnement de test" - TC-ERR-03 GIVEN : "Le contexte de donnees cible U2" - Plan §5 mapping : "Point d'observation: Absence donnees U2" - Le plan ne decrit PAS comment etablir "un contexte ciblant U2"
Verdict confrontation : ✅ VALIDE - L'endpoint /user/profile n'expose aucun parametre de cible - Le seul moyen de tester est de manipuler le contexte RLS au niveau test - Le plan doit expliciter le mecanisme de test (ex: injection directe SET LOCAL app.current_user_id en test, verification SELECT sur table avec deux users)
Gravite confirmee : BLOQUANT
DIV-03 : Mapping code erreur ERR-32-* non contractualise (MAJEUR)¶
Source : Review ChatGPT - Ecart #2 Observation ChatGPT : Le mecanisme de production des codes ERR-32-* n'est pas garanti explicitement.
Analyse confrontation : - Plan §6.3 : "Si le filter global ne produit pas le format attendu, creer UserProfileExceptionFilter" - Cette formulation est conditionnelle, pas contractuelle - Spec §6 exige le format {"error":"ERR-32-XXX","message":"..."}
Verdict confrontation : ✅ VALIDE - Le plan devrait affirmer le mecanisme (ExceptionFilter dedie ou configuration globale verifiee) - La formulation "si ... alors" n'est pas un engagement
Gravite confirmee : MAJEUR
DIV-04 : Seuil rate limiting non documente (MAJEUR)¶
Source : Review ChatGPT - Ecart #4 Observation ChatGPT : Les parametres seuil/fenetre necessaires a TC-ERR-08 ne sont pas documentes.
Analyse confrontation : - Tests §8 prerequis : "Configuration explicite du rate limiting (seuil N requetes, fenetre T secondes)" - Plan §1.3 : "RateLimitGuard global" (reutilise, pas de parametres) - Plan HT-03 : "RateLimitGuard global applique sur routes /user/*"
Verdict confrontation : ✅ VALIDE - Le plan devrait referencer la configuration existante ou documenter les valeurs pour testabilite - Suggestion : ajouter une note sur la configuration globale existante avec reference au fichier de config
Gravite confirmee : MAJEUR
DIV-05 : Hypothese RLS sans verification (MAJEUR)¶
Source : Review ChatGPT - Ecart #5 Observation ChatGPT : Le plan suppose RLS actif sans mecanisme de verification explicite.
Analyse confrontation : - Plan §8 HT-02 : "RLS PostgreSQL actif en environnement cible" avec impact si faux - C'est une hypothese explicite, pas un ecart implicite - La verification RLS est une responsabilite infra/ops, hors scope PD-32
Verdict confrontation : ❌ NON VALIDE - L'hypothese est explicitement documentee avec son impact - La verification de RLS est hors perimetre PD-32 (cf. H-32-02 dans spec)
Gravite revue : NON RETENU
DIV-06 : Risque serialisation non contractualise (MAJEUR)¶
Source : Review ChatGPT - Ecart #6 Observation ChatGPT : La protection @Exclude() repose sur une discipline non explicitee.
Analyse confrontation : - Plan §9.1 : "Verifier que ClassSerializerInterceptor est bien applique globalement" - C'est identifie comme risque mais pas comme invariant - Spec HT-04 : "class-transformer @Exclude() fonctionne avec intercepteur global"
Verdict confrontation : ⚠️ PARTIELLEMENT VALIDE - Le risque est identifie mais pas contractualise - Suggestion : ajouter invariant dans code contract controller ou verifier HT-04 en test
Gravite revue : MINEUR (risque identifie, non bloquant)
DIV-07 : AppModule non couvert dans code contracts (MAJEUR)¶
Source : Review ChatGPT - Ecart #7 Observation ChatGPT : AppModule est modifie mais aucun code contract ne le couvre.
Analyse confrontation : - Plan §1.2 : "AppModule | Import UserModule | src/app.module.ts" - Code contracts : 6 modules listes, AppModule absent - La modification AppModule est triviale (ajout import)
Verdict confrontation : ⚠️ PARTIELLEMENT VALIDE - Formellement, tout composant modifie devrait avoir un contract - Pragmatiquement, l'import est trivial et verifiable par compilation - Suggestion : ajouter un contract minimal ou documenter explicitement l'exclusion
Gravite revue : MINEUR (modification triviale)
DIV-08 : Invariant supplementaire user-module (MAJEUR)¶
Source : Review ChatGPT - Ecart #8 Observation ChatGPT : L'invariant "export UserProfileService" n'est pas dans la spec.
Analyse confrontation : - Code contract user-module : "Le module DOIT exporter UserProfileService pour injection externe si necessaire" - Aucun invariant spec ne mentionne cet export - C'est une decision technique d'implementation
Verdict confrontation : ✅ VALIDE - Les code contracts devraient tracer les invariants spec, pas en inventer - Si l'export est une decision technique, documenter dans §9 (points de vigilance), pas comme invariant
Gravite confirmee : MAJEUR (incoherence contractuelle)
DIV-09 : Incoherence GET payload Plan vs Code contracts (MAJEUR)¶
Source : Review ChatGPT - Ecart #9 Observation ChatGPT : Le code contract controller exige name,email,avatar_url mais le plan retourne aussi plan et preferences.
Analyse confrontation : - Code contract INV-32-08 : "GET DOIT retourner UserProfileResponseDto (name, email, avatar_url)" - Plan §2.1 : retourne { name, email, plan, avatar_url, preferences } - Cette incoherence est liee a DIV-01
Verdict confrontation : ✅ VALIDE (mais lie a DIV-01) - La correction de DIV-01 resoudra cette incoherence - Le payload correct est { name, email, avatar_url, preferences } selon spec §5 F-32-01 step 4 - Note : le code contract INV-32-08 omet preferences qui est dans la spec
Gravite confirmee : MAJEUR (subsume par DIV-01)
DIV-10 : Composants reutilises non traces (MINEUR)¶
Source : Review ChatGPT - Ecart #10 Observation ChatGPT : Guards et middleware critiques non traces dans code contracts.
Analyse confrontation : - Plan §1.3 : "Composants reutilises (sans modification)" - Ces composants sont hors perimetre PD-32 - Leurs invariants sont geres par leurs stories respectives
Verdict confrontation : ❌ NON VALIDE - Les composants reutilises sans modification n'ont pas besoin de code contract PD-32 - La tracabilite est assuree par reference dans le plan
Gravite revue : NON RETENU
4. Synthese des ecarts retenus¶
| ID | Description | Gravite | Correction requise |
|---|---|---|---|
| DIV-01 | Champ plan expose dans GET | BLOQUANT | Retirer plan du payload GET dans le plan §2.1 |
| DIV-02 | Mecanisme test acces croise non decrit | BLOQUANT | Ajouter description du mecanisme de test dans plan §5 ou §9 |
| DIV-03 | Mapping ERR-32-* non contractualise | MAJEUR | Affirmer le mecanisme dans plan §6.3 |
| DIV-04 | Seuil rate limiting non documente | MAJEUR | Ajouter reference config globale dans plan §1.3 |
| DIV-08 | Invariant supplementaire user-module | MAJEUR | Retirer invariant non-spec ou documenter comme decision technique |
| DIV-09 | Code contract INV-32-08 incomplet | MAJEUR | Ajouter preferences au contrat de sortie |
| DIV-06 | Serialisation non contractualisee | MINEUR | Renforcer HT-04 ou ajouter note §9.3 |
| DIV-07 | AppModule non contractualise | MINEUR | Ajouter contract minimal ou documenter exclusion |
5. Bilan¶
- Ecarts BLOQUANTS : 2
- Ecarts MAJEURS : 4
- Ecarts MINEURS : 2
- Ecarts non retenus : 2
6. Verdict confrontation¶
Le plan d'implementation presente des incoherences significatives avec la specification et les code contracts. Les deux ecarts BLOQUANTS concernent : 1. L'exposition d'un champ protege (plan) dans la reponse GET 2. L'absence de description du mecanisme de test pour les scenarios d'acces croise
Le plan necessite des corrections avant passage a l'implementation.
Statut : ⛔ NON CONFORME (corrections requises)