PD-19 — Rapport de confrontation v2 (Étape 3)¶
1. Sources confrontées¶
- PD-19-specification.md v2 (étape 1 — spécification corrigée après Gate 3 v1)
- PD-19-tests.md v1 (étape 2 — scénarios de test, NON MIS À JOUR)
- PD-19-specification-review.md v2 (Gate 3 Phase 1 v2 — review ChatGPT)
2. Convergences¶
C-01 — Socle de security headers désormais défini : La spec v2 (INV-01) contractualise explicitement le socle complet : X-Content-Type-Options, X-Frame-Options, CSP, Referrer-Policy, Permissions-Policy, HSTS conditionnel, Cache-Control conditionnel. Les tests (TC-NOM-05) vérifient la présence du socle. La review ne conteste pas la liste elle-même mais signale une ambiguïté sur les clauses conditionnelles (Majeur, non Bloquant). Convergence sur l'existence d'un socle contractualisé.
C-02 — Paramètres CORS contractualisés : INV-03 définit méthodes (6), en-têtes autorisés (6), en-têtes exposés (2), credentials=true. INV-04 liste les origines par environnement. INV-05 fixe Max-Age par env. Les tests couvrent via TC-NOM-01/02/03/04. La review ne conteste pas les valeurs CORS elles-mêmes. Convergence.
C-03 — Seuils de limitation définis : INV-06 fixe 100 req/60s/IP, clé=IP via proxy de confiance. INV-07 contractualise le signal 429+Retry-After+JSON. Tests TC-NOM-07/08 couvrent le flux. La review ne conteste pas les valeurs mais soulève l'absence de définition de la chaîne de proxy (Majeur). Convergence sur les valeurs, divergence sur la chaîne de confiance.
C-04 — eIDAS exclu du périmètre : La spec v2 (§2 Exclu + H-07) exclut explicitement eIDAS. Les tests v1 le marquent encore comme Bloquant (§9) — mais c'est un artefact de non-mise-à-jour. La review ne mentionne plus eIDAS comme problème. Convergence sur l'exclusion.
C-05 — Couverture structurelle 12/12 INV, 14/14 CA : La matrice de tests couvre tous les invariants et critères. La spec définit une table ST↔TC. La review ne conteste pas la couverture structurelle. Convergence.
C-06 — ERR-05 maintenant fail-fast unique : La spec v2 corrige ERR-05 en imposant « fail-fast (comportement unique) ». La review conteste cependant l'absence d'observable contractuel (Majeur). Les tests TC-ERR-05 acceptent encore les deux comportements (v1). Convergence partielle.
C-07 — Indépendance métier confirmée : INV-08 + CA-13 + TC-NOM-12. Aucune contestation. Convergence unanime.
C-08 — Mode dev borné : INV-10 définit les deux origines locales autorisées et les headers maintenus. TC-NOM-11 les vérifie. La review ne conteste plus les bornes du mode dev. Convergence.
3. Divergences¶
DIV-01 — Erreur factuelle de la review : ERR-01 « contradiction »¶
- Source A (review v2, point 1, Bloquant) : Affirme que ERR-01 indique « un refus CORS pour toute requête portant Origin », en contradiction avec F1/CA-03 qui autorisent les origines listées.
- Source B (specification.md §6 ERR-01) : Le texte dit « Origine absente/invalide dans un contexte nécessitant CORS — S'applique à toute requête portant un en-tête Origin — Réponse conforme à la politique de refus ». Le titre indique clairement « Origine absente/invalide ». La politique de refus s'applique aux origines non conformes, pas à toute requête avec Origin.
- Constat : La review fait une lecture erronée de ERR-01. Le titre est « Origine absente/invalide ». La phrase « S'applique à toute requête portant Origin » définit le périmètre d'évaluation (quand évaluer le CORS), pas la décision (toujours refuser). Il n'y a pas de contradiction avec F1/CA-03 : l'évaluation CORS s'applique à toute requête avec Origin, et la décision dépend de la politique (autoriser ou refuser selon l'origine). Ce point Bloquant de la review est un faux positif.
DIV-02 — Tests v1 §9 obsolète : règles « non testables » résolues¶
- Source A (tests.md §9) : Maintient 8 règles non testables, dont socle headers, CORS, origines, seuils, portée limitation, eIDAS — toutes marquées Majeur/Bloquant.
- Source B (specification.md v2) : INV-01 contractualise le socle, INV-03/04/05 les CORS, INV-06/07 les seuils/signal, §2 exclut eIDAS.
- Source C (review v2) : Identifie correctement cette incohérence (Bloquant) — le dossier de preuve est « auto-contradictoire ».
- Constat : C'est un artefact de non-mise-à-jour du document de tests. La spec v2 a résolu 6 des 8 règles non testables. Restent : « Exceptions contrôlées » (maintenu comme point à clarifier §10.1) et « Exigences d'alerting » (§10.2). Le document de tests DOIT être mis à jour. Divergence réelle et légitime, mais de nature documentaire, pas structurelle.
DIV-03 — Nomenclature ST-xx vs TC-NOM-xx¶
- Source A (specification.md §8) : Table ST-01→TC-01 ... ST-12→TC-12.
- Source B (tests.md) : Nomenclature TC-NOM-01 à TC-NOM-12.
- Source C (review v2) : Identifie le décalage (Majeur) — couverture non démontrable formellement.
- Constat : La spec référence TC-01..TC-12 mais les tests utilisent TC-NOM-01..TC-NOM-12. La correspondance est bijective dans les faits (TC-01 = TC-NOM-01, etc.), mais la nomenclature n'est pas alignée formellement. Divergence réelle, gravité Mineure (résolution triviale par alignement de nommage).
DIV-04 — INV-01 : socle « constant » vs clauses conditionnelles¶
- Source A (review v2, Majeur) : INV-01 mélange « constant par environnement » avec HSTS conditionnel (selon HTTPS) et Cache-Control conditionnel (selon sensibilité).
- Source B (specification.md §4 INV-01) : Le texte distingue bien un socle de 5 headers toujours présents + HSTS conditionnel + Cache-Control conditionnel.
- Constat : La review a raison — le terme « constant par environnement » est ambigu quand on le juxtapose aux clauses conditionnelles. L'implémenteur doit comprendre que le socle de 5 headers est constant, et que HSTS et Cache-Control ont des règles supplémentaires. L'ambiguïté est réelle mais Mineure car la lecture attentive de INV-01 permet de distinguer les deux niveaux.
DIV-05 — ERR-03 : refus preflight sans observable complet¶
- Source A (review v2, Majeur) : Le refus déterministe des preflight incohérents n'a pas de contrat observable complet (statut, en-têtes attendus).
- Source B (specification.md §6 ERR-03) : « Décision CORS négative déterministe. Pas d'accès cross-origin autorisé. »
- Source C (tests.md TC-NOM-04) : Vérifie « la décision CORS est négative à chaque essai » et « les sorties de refus sont déterministes ».
- Constat : Le contrat de refus CORS est implicitement défini par l'absence des en-têtes CORS positifs (Access-Control-Allow-Origin absent ou non correspondant). Le statut HTTP d'un preflight refusé n'est pas spécifié (la RFC CORS ne mandate pas un statut spécifique — le serveur peut retourner 200 sans en-têtes CORS, ou 403). La review soulève un point légitime mais la spécification suit la pratique standard CORS. Gravité Mineure.
DIV-06 — ERR-05 : fail-fast sans observable contractuel¶
- Source A (review v2, Majeur) : « Fail-fast » exigé sans signal vérifiable.
- Source B (specification.md §6 ERR-05) : « Le service ne doit pas démarrer en mode permissif implicite. Comportement attendu unique : échec explicite de démarrage (fail-fast). »
- Source C (tests.md TC-ERR-05) : « Le service échoue explicitement au démarrage ou passe en mode bloquant documenté » — texte v1 non aligné avec ERR-05 v2 (fail-fast unique).
- Constat : Le test TC-ERR-05 n'a pas été mis à jour et accepte encore le double comportement de la v1. La spec v2 est claire (fail-fast unique), mais l'observable (exit code ? signal ? log d'erreur ?) n'est pas spécifié. Divergence réelle : le test doit être aligné sur la spec v2, et un observable de fail-fast devrait être précisé.
DIV-07 — Chaîne de proxy de confiance non définie¶
- Source A (review v2, Majeur) : Clé de comptage IP « via chaîne de proxy de confiance » sans définition contractuelle.
- Source B (specification.md §4 INV-06) : « IP client résolue via chaîne de proxy de confiance, sinon adresse source directe ».
- Constat : La spec ne définit pas ce que signifie « proxy de confiance » (trusted proxies). C'est un paramètre d'infrastructure qui varie par environnement. La review a raison que cela crée une surface de contournement (X-Forwarded-For spoofing). Cependant, la configuration des trusted proxies est un paramètre opérationnel, pas un paramètre de spécification fonctionnelle. Gravité Majeure pour la testabilité (sans trusted proxies définis, on ne peut pas tester le comptage IP en environnement avec proxy).
DIV-08 — Credentials=true en dev HTTP¶
- Source A (review v2, Majeur) : Access-Control-Allow-Credentials: true imposé globalement, y compris en dev avec origines HTTP.
- Source B (specification.md §4 INV-03) : Credentials: true sans exception par environnement.
- Constat : La review soulève un risque réel. En dev, les origines sont HTTP (localhost:3000, localhost:8080). Avec credentials=true, les cookies sont envoyés en clair. Cependant, c'est un risque accepté en développement local (localhost uniquement, pas de réseau exposé). Gravité Mineure dans le contexte d'un environnement dev local contrôlé.
DIV-09 — RGPD : journalisation IP sans minimisation¶
- Source A (review v2, Majeur) : INV-09 journalise IP client sur 90 jours sans minimisation/pseudonymisation.
- Source B (specification.md §4 INV-09) : Journaux JSON avec IP client, endpoint, statut, 90 jours.
- Constat : Point légitime. L'IP est une donnée personnelle (CJUE). La journalisation sur 90j sans mention de pseudonymisation (hashing, troncature) est un risque RGPD. Cependant, les logs de sécurité bénéficient d'une base légale « intérêt légitime » pour la détection d'abus. La spécification devrait au minimum mentionner la base légale ou le traitement de minimisation. Gravité Majeure sur le plan conformité.
4. Zones d'ombre¶
ZO-01 — Comportement sans en-tête Origin : Les requêtes sans Origin (scripts serveur, apps mobiles natives, curl) ne sont pas explicitement traitées. ERR-01 couvre « origine absente » mais uniquement « dans un contexte nécessitant CORS ». Pour les requêtes sans Origin, la politique CORS ne s'applique pas (comportement navigateur standard). La spec ne le dit pas explicitement.
ZO-02 — Exceptions B2B/partenaires : Point à clarifier §10.1. Ni la spec ni les tests ne définissent si des exceptions existent. Les tests ne peuvent pas couvrir un cas non spécifié.
ZO-03 — Alerting vs logging seul : Point à clarifier §10.2. Aucun document ne tranche.
ZO-04 — Tests v1 Verdict QA « testable partiellement » : Le verdict QA est basé sur les lacunes v1 maintenant résolues. Le verdict devrait être « testable intégralement » après mise à jour. Non mis à jour.
5. Synthèse des écarts¶
| ID | Source | Nature | Gravité réelle |
|---|---|---|---|
| DIV-01 | Review vs Spec | Faux positif review (lecture erronée ERR-01) | Écarté |
| DIV-02 | Tests vs Spec | Tests §9 non mis à jour | Majeur (documentaire) |
| DIV-03 | Spec vs Tests | Nomenclature ST-xx vs TC-NOM-xx | Mineur |
| DIV-04 | Review vs Spec | Ambiguïté « constant » vs conditionnel dans INV-01 | Mineur |
| DIV-05 | Review vs Spec | ERR-03 refus preflight sans observable explicite | Mineur |
| DIV-06 | Tests vs Spec | TC-ERR-05 non aligné avec ERR-05 v2 fail-fast | Majeur |
| DIV-07 | Review vs Spec | Chaîne de proxy de confiance non définie | Majeur |
| DIV-08 | Review vs Spec | Credentials=true en dev HTTP | Mineur |
| DIV-09 | Review vs Spec | RGPD journalisation IP sans minimisation | Majeur |
Bloquants légitimes de la review : 0 (les 3 Bloquants sont liés soit à un faux positif (ERR-01), soit à la non-mise-à-jour des tests).
Écarts Majeurs réels : 3 (DIV-02 tests non mis à jour, DIV-07 proxy de confiance, DIV-09 RGPD). Écarts Majeurs faciles : 1 (DIV-06 alignement TC-ERR-05). Écarts Mineurs : 4 (DIV-03, DIV-04, DIV-05, DIV-08).
6. Recommandation¶
- Procéder — convergence confirmée, aucun conflit bloquant
- Rework nécessaire — divergences à résoudre avant de continuer
- Escalade — décision humaine requise sur un point structurant
Justification : La spécification v2 a significativement progressé par rapport à la v1 (les 4 critiques et 7 majeurs de Gate 3 v1 sont résolus). Le document central (spec) est solide. Le problème principal est que le document de tests n'a pas été mis à jour pour refléter les corrections (§9 obsolète, TC-ERR-05 non aligné, nomenclature). Les 3 Bloquants de la review sont soit faux positifs (1), soit liés à cette non-mise-à-jour (2). La spécification a 3 vrais écarts Majeurs résiduels.
Document produit par le workflow de gouvernance IA — Gate 3 Phase 2 v2 (Confrontation Claude) Date : 2026-02-09