PD-240 — Confrontation (Étape 5 v1)¶
Gate AMBIGUITY — Review du plan d'implémentation
Documents confrontés¶
| Document | Version | Source |
|---|---|---|
| PD-240-specification.md | v3 | ChatGPT (Gate 3 GO) |
| PD-240-tests.md | v3 | ChatGPT (Gate 3 GO) |
| PD-240-plan.md | v1 | Claude |
| PD-240-code-contracts.yaml | v1 | Claude |
| PD-240-plan-review-v1.md | v1 | ChatGPT |
1. Convergences¶
| Point | Documents concernés | Analyse |
|---|---|---|
| Flux transactionnel | Spec §7, Plan §3.2 | Ordre sessions → purge → Keycloak conforme |
| Invariants mappés | Spec §6, Plan §4 | 9/10 invariants ont un mécanisme technique explicite |
| Codes erreur | Spec §8, Plan §6 | Codes ERR-240-* alignés avec implémentation |
| Guards de sécurité | Spec INV-240-01/02, Plan §7.1 | JwtAuthGuard + ReauthMiddleware conformes |
| Confirmation renforcée | Spec §5, Plan §3.2 | Format { "confirm": "DELETE_MY_ACCOUNT" } cohérent |
| Tests ↔ Plan | Tests §2, Plan §5 | Chaque test a un mécanisme vérifiable |
2. Divergences¶
DIV-01 — Incohérence interne à la spec (endpoint admin)¶
| Attribut | Valeur |
|---|---|
| Gravité | BLOQUANT |
| Source Review | Écart #1, #7 |
| Document concerné | PD-240-specification.md (v3) |
Constat :
La spec contient une incohérence interne entre deux sections :
- §4 Périmètre :
DELETE /admin/users/{userId}/audit - INV-240-05 :
GET /admin/audit/user/{userId}
Différences : 1. Méthode HTTP : DELETE vs GET 2. Path : /admin/users/{userId}/audit vs /admin/audit/user/{userId}
Impact : Le plan et les code contracts suivent INV-240-05 (GET), ce qui est cohérent avec l'observable défini. Le périmètre semble contenir une erreur de rédaction.
Verdict partiel : L'écart identifié par ChatGPT est dû à une incohérence dans la spec, pas à une non-conformité du plan. La spec doit être corrigée pour aligner §4 sur INV-240-05.
DIV-02 — purgedAt optionnel vs obligatoire¶
| Attribut | Valeur |
|---|---|
| Gravité | MAJEUR |
| Source Review | Écart #2, #5, #6 |
| Documents concernés | Spec INV-240-05, Code Contracts, Tests T-240-POST-02 |
Constat :
- Spec INV-240-05 :
{ "status": "purged", "purgedAt": "<ISO8601>" }— purgedAt présent dans la réponse type - Code Contract audit-controller :
{ status: 'purged' | 'active', purgedAt?: ISO8601 }— purgedAt optionnel (?) - Test T-240-POST-02 : attend
{ "status": "purged", "purgedAt": "<ISO8601>" }— purgedAt requis
Impact : Le code contract autorise une réponse sans purgedAt, ce qui ferait échouer le test T-240-POST-02.
Verdict partiel : Le code contract doit être aligné — purgedAt obligatoire quand status="purged".
DIV-03 — État dégradé post-invalidation sessions¶
| Attribut | Valeur |
|---|---|
| Gravité | MAJEUR |
| Source Review | Écart #3, #4 |
| Documents concernés | Spec §7, §8, Plan §7.3, §9 |
Constat :
- Spec §8 : Si invalidation sessions échoue → ERR-240-SESSION-INVALIDATION-FAILED (rollback complet)
- Plan §7.3 : "Si échec purge/Keycloak après invalidation sessions → compte verrouillé (sessions mortes, Keycloak intact) — état dégradé acceptable"
- Plan §9 : Mitigation proposée (logs d'audit + job de réconciliation)
Le plan introduit un état "limbo" non spécifié pour le cas où la purge ou Keycloak échoue APRÈS l'invalidation des sessions.
Analyse :
La spec définit : - ERR-240-SESSION-INVALIDATION-FAILED → aucune suppression (rollback) - ERR-240-DELETE-FAILED → "compte non supprimé" mais ne précise pas l'état des sessions
Le plan fait une distinction pragmatique : 1. Échec sessions → rollback complet (conforme) 2. Échec purge/Keycloak après sessions → état dégradé (non spécifié mais sécuritaire)
Impact : L'état dégradé n'est pas une violation de sécurité (sessions mortes = utilisateur déconnecté), mais il n'est pas contractualisé.
Verdict partiel : Divergence à clarifier. La spec doit explicitement définir le comportement en cas d'échec purge/Keycloak après invalidation réussie des sessions.
3. Zones d'ombre¶
ZO-01 — Comportement exact en cas d'échec purge/Keycloak¶
La spec ne définit pas explicitement ce qui se passe si : 1. Les sessions sont invalidées avec succès 2. La purge RGPD ou la suppression Keycloak échoue
Questions : - Le compte reste-t-il actif dans Keycloak ? - Peut-on réessayer la suppression ? - Faut-il un mécanisme de réconciliation ?
ZO-02 — Contenu exact de la réponse succès¶
Le plan propose 200 OK avec { success: true } ou body vide. La spec ne contractualise pas le format de réponse succès.
4. Synthèse¶
| ID | Type | Gravité | Action requise |
|---|---|---|---|
| DIV-01 | Incohérence spec | BLOQUANT | Corriger spec §4 (aligner sur INV-240-05) |
| DIV-02 | Code Contract | MAJEUR | Corriger code contract (purgedAt obligatoire si status=purged) |
| DIV-03 | Plan non contractualisé | MAJEUR | Clarifier spec §8 (comportement échec post-sessions) |
| ZO-01 | Zone d'ombre | MINEUR | À documenter dans le plan ou accepter |
| ZO-02 | Zone d'ombre | MINEUR | Contractualiser format réponse succès ou accepter |
5. Recommandation pré-verdict¶
DIV-01 est un écart dans la spec, pas dans le plan. La correction doit être apportée à PD-240-specification.md (§4 Périmètre).
DIV-02 et DIV-03 sont des écarts dans le plan/code contracts qui peuvent être corrigés par Claude.
Verdict recommandé : NON_CONFORME avec corrections ciblées sur : 1. Spec §4 : aligner endpoint sur GET /admin/audit/user/{userId} 2. Code contract audit-controller : purgedAt obligatoire si purged 3. Spec §8 ou Plan §7.3 : contractualiser l'état post-échec-purge