PD-19 — Confrontation Gate 5 v1¶
Contexte¶
Analyse contradictoire des 10 points de la review ChatGPT gov-factual face aux documents sources (plan, code contracts, spécification, tests).
Point 1 — Cache-Control conditionnel (Review : Majeur)¶
Énoncé¶
Le plan ne précise pas de mécanisme explicite pour appliquer
Cache-Control: no-storeuniquement sur les réponses sensibles.
Confrontation¶
Code contracts (security_headers_config.cacheControl) :
cacheControl:
sensitiveRoutes:
value: "no-store"
routes:
- "/auth/*"
- "/users/me"
- "401 responses"
- "403 responses"
Verdict confrontation : - PARTIELLEMENT VALIDE — Le code contract définit les routes sensibles mais le plan (Phase 2) ne détaille pas le mécanisme d'application contextuelle. - Recommandation : Ajouter dans Phase 2 la logique de détection des réponses sensibles (path matching + status code).
Gravité maintenue : Majeur
Point 2 — HSTS conditionnel dev (Review : Majeur)¶
Énoncé¶
Le contrat ne explicite pas la règle conditionnelle HSTS en
dev(uniquement si HTTPS).
Confrontation¶
Code contracts (security_headers_config.strictTransportSecurity) :
strictTransportSecurity:
enabled:
type: "conditional"
condition: "env !== 'development' || process.env.HTTPS === 'true'"
maxAge:
values:
development: 300
production: 31536000
test: 31536000
Verdict confrontation : - INVALIDE (faux positif) — Le code contract explicite clairement la condition HSTS et les valeurs par environnement. - La review n'a pas lu correctement le YAML lines 36-51.
Gravité révisée : Non applicable (faux positif)
Point 3 — CORS credentials et exposedHeaders (Review : Bloquant)¶
Énoncé¶
Le contrat CORS ne cite pas explicitement
Access-Control-Allow-Credentials: trueni les en-têtes exposés.
Confrontation¶
Code contracts (cors_config) :
credentials:
type: boolean
value: true
invariant: INV-03
exposedHeaders:
type: "string[]"
values:
- "X-Correlation-Id"
- "Retry-After"
invariant: INV-03
Verdict confrontation : - INVALIDE (faux positif) — Les deux éléments sont explicitement présents dans le code contract (lines 117-122 et 113-118). - La review a fait une erreur de lecture.
Gravité révisée : Non applicable (faux positif)
Point 4 — Stratégie refus preflight (Review : Majeur)¶
Énoncé¶
Le plan ne détaille pas la stratégie de refus explicite des pré-vols non autorisés.
Confrontation¶
Code contracts (cors_middleware.use.behavior) :
Plan (Phase 3) :
"Aucun indicateur CORS si origine non autorisée"
Verdict confrontation : - PARTIELLEMENT VALIDE — Le comportement de refus est décrit (pas de headers CORS) mais le statut HTTP exact n'est pas précisé (200 ? 403 ? 204 ?). - Recommandation : Clarifier que le preflight non autorisé reçoit un 200 OK sans headers CORS (comportement standard navigateur).
Gravité révisée : Mineur (clarification documentaire)
Point 5 — DIV-01-v2 action test (Review : Bloquant)¶
Énoncé¶
Le plan ne décrit pas d'action test explicite pour étendre TC-ERR-02 aux refus CORS et 429.
Confrontation¶
Plan (Phase 6 — §6.4) :
"DIV-01-v2 | Assertions headers sur 429/refus CORS | Tests E2E Phase 6"
Plan (Phase 6 — §2.5) :
Créer
test/e2e/security-headers.e2e-spec.ts: TC-NOM-01, TC-NOM-02, TC-NOM-05, TC-ERR-02
Code contracts (test_assertions.security_headers) :
Verdict confrontation : - PARTIELLEMENT VALIDE — L'assertion "429" est présente dans les code contracts, mais le plan Phase 6 ne liste pas explicitement l'extension de TC-ERR-02 pour inclure refus CORS. - Recommandation : Ajouter explicitement dans Phase 6 : "Étendre TC-ERR-02 : assertions security headers sur 429 et refus CORS".
Gravité révisée : Majeur (pas bloquant car l'intention est présente, mais la traçabilité est faible)
Point 6 — DIV-02-v2 test intégration (Review : Majeur)¶
Énoncé¶
La qualification "résolution IP proxy en test d'intégration" est citée sans tâche dédiée.
Confrontation¶
Plan (§6.4) :
"DIV-02-v2 | Documentation test intégration IP proxy | Plan §4 + tests"
Plan (§4) :
"Résout IP client (X-Forwarded-For si proxy de confiance, sinon IP directe)"
Verdict confrontation : - VALIDE — Le plan mentionne la résolution mais ne crée pas de tâche/phase spécifique pour documenter/valider le mécanisme de proxy de confiance. - Recommandation : Ajouter dans Phase 6 une tâche "Créer test d'intégration TC-INT-01 : validation X-Forwarded-For avec trusted proxies".
Gravité maintenue : Majeur
Point 7 — Risque Redis non mitigé (Review : Majeur)¶
Énoncé¶
Aucun mécanisme d'atténuation décrit pour indisponibilité Redis.
Confrontation¶
Plan (§6.2 Performance) :
"Redis atomique (INCR + EXPIRE en une commande)"
Spec (INV-06) :
Limitation s'applique à tous endpoints — pas de mention de fallback.
Verdict confrontation : - VALIDE — Le risque d'indisponibilité Redis n'est pas adressé. Cependant, l'architecture existante (RateLimitService) a déjà un mécanisme de gestion (le service existe et fonctionne). - Recommandation : Ajouter dans §6 un point "Stratégie indisponibilité Redis : fail-open (permettre les requêtes) ou fail-closed (429 par défaut) — à valider avec l'équipe".
Gravité révisée : Mineur (hors scope spécification, mais bonne pratique)
Point 8 — Schéma log incomplet (Review : Bloquant)¶
Énoncé¶
Le plan ne détaille pas la complétude du schéma de log ni la rétention 90 jours.
Confrontation¶
Code contracts (audit_log_service.new_events) :
- name: CORS_REJECTED
fields:
- timestamp (UTC ISO-8601)
- correlationId
- environment
- origin
- method
- endpoint
- reason
invariant: INV-09
- name: RATE_LIMIT_EXCEEDED
fields:
- timestamp (UTC ISO-8601)
- correlationId
- environment
- ipHash (SHA256)
- endpoint
- windowStart
- count
- limit
invariant: INV-09
Verdict confrontation : - PARTIELLEMENT VALIDE — Les champs sont détaillés dans les code contracts (lignes 284-305) mais la rétention 90 jours n'est pas mentionnée. - Recommandation : La rétention est une configuration infrastructure (non code), mais devrait être documentée dans le plan ou les code contracts.
Gravité révisée : Mineur (rétention = config infra, pas code)
Point 9 — Confusion middleware/guards (Review : Mineur)¶
Énoncé¶
La chaîne inclut des guards qui ne sont pas des middlewares NestJS.
Confrontation¶
Plan (§4) :
Verdict confrontation : - VALIDE — Le schéma mélange middlewares (NestMiddleware) et guards (CanActivate), ce qui peut induire en erreur. - Recommandation : Clarifier que le diagramme montre le flux logique complet, pas uniquement les middlewares au sens NestJS.
Gravité confirmée : Mineur
Point 10 — Fail-fast détail (Review : Majeur)¶
Énoncé¶
Le plan ne précise pas le comportement fail-fast au bootstrap.
Confrontation¶
Plan (Phase 1) :
Spec (ERR-05) :
"Le service ne doit pas démarrer en mode permissif implicite. Comportement attendu unique : échec explicite de démarrage (fail-fast)."
Verdict confrontation : - PARTIELLEMENT VALIDE — Le plan indique "Throws si invalide" mais ne détaille pas les conditions exactes ni le message d'erreur. - Recommandation : Ajouter dans Phase 1 : "Conditions fail-fast : CORS_ORIGINS vide/invalide, RATE_LIMIT_GLOBAL_MAX < 1, etc. Message : 'Security configuration invalid:
Gravité maintenue : Majeur
Synthèse de la confrontation¶
| Point | Review | Confrontation | Gravité finale |
|---|---|---|---|
| 1 | Majeur | Partiellement valide | Majeur |
| 2 | Majeur | Faux positif | Non applicable |
| 3 | Bloquant | Faux positif | Non applicable |
| 4 | Majeur | Partiellement valide | Mineur |
| 5 | Bloquant | Partiellement valide | Majeur |
| 6 | Majeur | Valide | Majeur |
| 7 | Majeur | Valide (hors scope) | Mineur |
| 8 | Bloquant | Partiellement valide | Mineur |
| 9 | Mineur | Valide | Mineur |
| 10 | Majeur | Partiellement valide | Majeur |
Résultat consolidé : - Bloquant : 0 (2 faux positifs identifiés) - Majeur : 4 (Points 1, 5, 6, 10) - Mineur : 4 (Points 4, 7, 8, 9) - Non applicable : 2 (Points 2, 3)
Conclusion : La confrontation a réduit les 3 bloquants à 0 (2 faux positifs de lecture du code contracts). Il reste 4 majeurs qui concernent principalement des clarifications du plan. Le plan est globalement conforme mais nécessite des précisions sur les mécanismes d'application contextuelle et la traçabilité des réserves Gate 3.
Document produit par le workflow de gouvernance IA — Gate 5 v1 Phase 2 (Confrontation Claude mode factuel) Date : 2026-02-09