Aller au contenu

PD-85 — Rapport de confrontation (Gate 8 — Closure)

Ce rapport est produit par l'orchestrateur Claude avant la gate PMO 8. Il confronte les documents produits pour identifier convergences, divergences et zones d'ombre.

1. Sources confrontées

Document Étape
PD-85-specification.md Étape 1 (Spécification)
PD-85-tests.md Étape 2 (Tests contractuels)
PD-85-plan.md Étape 4 (Plan d'implémentation)
PD-85-acceptability.md Étape 7 (Acceptabilité)

2. Convergences

  • Zero-Knowledge (INV-85-01) : Les 4 documents s'accordent unanimement — le backend ne déchiffre JAMAIS les documents. Le plan détaille le mécanisme (S3PresignService sans GetObject), l'acceptabilité confirme le PASS du test TC-INV-8501.

  • UUID v4 exportId (INV-85-02) : Spec, plan et tests convergent sur crypto.randomUUID(). Acceptabilité confirme PASS.

  • SHA3-256 JCS (INV-85-03) : Spec définit SHA3-256 sur manifest canonicalisé (RFC 8785, champ integrityHash exclu). Plan détaille la réutilisation de json-canonicalize existante et la distinction SHA3-256 ≠ SHA-256. Tests (TC-NOM-05, TC-INV-8503) et acceptabilité confirment PASS.

  • Immutabilité ProofEnvelope (INV-85-06) : Lecture seule contractualisée dans les 4 documents. Tests TC-INV-8506 PASS.

  • Taille bornée 1 GB (INV-85-07) : Cohérence complète spec → plan → tests → acceptabilité. Code 413 avec taille estimée + limite.

  • Fail-fast 404 sur ownership : Spec §6, plan §9 et tests TC-ERR-03 convergent — la première preuve non possédée/inexistante interrompt le traitement. Ordre critique respecté : 400 → 403 → 404 → 413 → validation invariants.

  • Machine d'états terminale (INV-85-08) : 6 états terminaux sans transition sortante, cohérence entre spec §5.3, plan C2, tests TC-INV-8508. Acceptabilité PASS.

  • Traitement synchrone : Spec §5.7, plan §2 et §10 confirment : pas de queue/worker, atomicité transactionnelle synchrone.

  • Aucune migration DDL : Spec §5.8 et plan §10 s'accordent — pas de changement de schéma contractualisé.

  • Rate limiting par utilisateur : Spec §5.2 (10/h/user), plan C7 (Joi), tests implicites. Cohérent.

  • B2C-mineurs enrichissement conditionnel : Spec §5.6 (flux F3), plan C9 (ExportMinorEvidenceService), tests TC-NOM-03, acceptabilité PASS. Convergence sur l'enrichissement conditionnel (Mandate, Dual Validation, ReKey Lifecycle).

  • Doublons proofIds = 400 : Spec §6 contractualise le rejet 400 (déduplication interdite). Plan C1 (@ArrayUnique()). Tests TC-NEG-01 PASS en acceptabilité.

  • Signature ECDSA raw (INV-11) : Plan §9 rappelle le piège double-hash PD-282 (crypto.verify(null, ...) obligatoire). Cohérent avec les règles apprises du codebase.

3. Divergences

⚠️ Les conflits ne doivent JAMAIS être lissés. Chaque divergence est rendue visible.

  • DIV-01 : Audit fail-closed non respecté dans l'implémentation
  • Plan §6, §9 : "Fail-closed audit : si AuditLogService.logAsync() échoue, l'export DOIT échouer (500). L'opération métier et l'audit sont atomiques."
  • Acceptabilité E-01 (BLOQUANT) : ".catch(...) absorbe l'échec d'audit puis renvoie ExportException. Opération possible sans trace WORM."
  • Impact : Violation INV-85-05. Un export réussi sans trace audit WORM est une non-conformité NF Z42-013 / ISO 14641. Écart BLOQUANT confirmé par les 3 reviews LLM.

  • DIV-02 : TTL URL signée — bornage contractuel vs implémentation

  • Spec §5.2 : TTL défaut 15 min, max 30 min, env EXPORT_SIGNED_URL_TTL_MIN.
  • Plan C7 : Joi.number().min(1).max(30) — validation config Joi au démarrage.
  • Acceptabilité E-02 (MAJEUR) : "signedUrlTtlMin utilisé sans Math.min(config, 1800) dans le service. Mauvaise config = URLs trop longues."
  • Impact : La validation Joi au démarrage protège normalement contre une config > 30, mais l'acceptabilité indique une absence de clamp runtime dans le service. Si Joi est contourné (variable d'environnement injectée après démarrage, ou config runtime), INV-85-04 est violé.

  • DIV-03 : Tests doc signale des règles "non testables" déjà résolues dans la spec

  • Tests §9 : 6 règles déclarées "non testables" dont 4 marquées "Majeur" (signedUrlTtl défaut, politique audit 4xx, cas mixte 404, documentType enum, proofEnvelopeRef format).
  • Spec : A résolu explicitement 5 de ces 6 points — signalés par des mentions "RÉSOLU" dans §10 (points 3, 5, 6, 7, 8, 9).
  • Impact : Le verdict QA du document tests ("testable partiellement") est périmé. La couverture contractuelle est meilleure que ce que le document tests déclare. Seul le contexte de performance P95 reste réellement non testable.

  • DIV-04 : Référence epic incohérente

  • Spec : "Epic : PD-185 (B2C-MINEURS)"
  • Tests §1 : "Epic : EPIC-XX (incohérence détectée avec référence PD-185 en annexe de la spec)"
  • Impact : Mineur — cosmétique. La référence PD-185 dans la spec est correcte.

  • DIV-05 : Énumération de ressources — spec vs implémentation

  • Spec §6 : "proofId introuvable ou non possédé" — traitement uniforme, même code 404.
  • Acceptabilité E-05 (MAJEUR) : "Messages d'erreur distincts ('Proof not found' vs 'Proof not accessible') permettent de profiler l'existence d'IDs."
  • Impact : Fuite d'information permettant à un attaquant de distinguer un ID inexistant d'un ID existant mais non possédé. La spec contractualise un traitement uniforme que l'implémentation ne respecte pas.

  • DIV-06 : TC-NEG-01 — ambiguïté dans le doc tests vs clarté dans la spec

  • Tests TC-NEG-01 : "Soit déduplication explicite soit rejet 400 (comportement contractuel à figer)"
  • Spec §6 : "proofIds contient des doublons → Erreur explicite listant les doublons (déduplication interdite — fail-fast)"
  • Plan C1 : "@ArrayUnique()"
  • Impact : Aucun — la spec et le plan sont clairs. Le doc tests est simplement antérieur à la finalisation de la spec.

  • DIV-07 : Coverage sous seuil contractuel

  • Plan C10 : "Couverture complète des TC-*"
  • Acceptabilité §3 : Stmts 82.72%, Branch 74.15%, Funcs 67.64%, Lines 84.33% — sous le seuil 85%
  • Acceptabilité E-07 : Controller à 0% coverage
  • Impact : Le plan promettait une couverture complète. L'implémentation est en dessous du seuil sur toutes les métriques. Fonctions à 67.64% est particulièrement bas.

4. Zones d'ombre

  • ZO-01 : SonarQube non exécuté (serveur injoignable). Phase 1.5 de la procédure d'acceptabilité est BLOQUANTE selon les règles (procedures.md). L'acceptabilité note E-11 (MINEUR) mais la procédure dit BLOQUANT. Aucun des 4 documents ne tranche cette contradiction procédurale.

  • ZO-02 : Tests d'intégration S3 absents (TC-NOM-06, TC-NOM-07, TC-INV-8504). Acceptabilité note E-04 et E-08. Le plan prévoit ces tests (§5, §10) mais l'implémentation ne les inclut pas. Aucune couverture de CA-10 (expiration URL signée) et INV-85-04 en conditions réelles (même mockées).

  • ZO-03 : encrypted_size — stratégie d'estimation taille. Plan HT-03 : "Si absent, requête S3 HeadObject par document (latence)." Acceptabilité Stubs : "estimateTotalSize utilise 1 MB par document." La spec (INV-85-07) exige un rejet strict > 1 GB. Aucun document ne confirme si l'estimation à 1 MB/doc est acceptable pour la conformité INV-85-07 (risque de faux négatif : 500 preuves × 1 MB = 500 MB < 1 GB, même si les documents réels font > 1 GB chacun).

  • ZO-04 : Test E2E controller absent. Acceptabilité E-03 (MAJEUR) et E-07 (MINEUR) : aucun test E2E pour le controller (0% coverage), pas de test assertant 403 + body vide + audit. Le plan prévoit des tests E2E (§10) mais l'implémentation n'en a pas pour le controller.

  • ZO-05 : SecretExposureValidator — robustesse. Acceptabilité E-09 : "substring match, contournable par encodage/obfuscation." Plan §3 : "Risque Moyen — patterns à maintenir exhaustifs." La spec INV-09 exige "aucune preuve exportée n'expose de secret." Aucun document ne définit le périmètre exact des patterns à scanner ni la stratégie face à l'encodage.

  • ZO-06 : N+1 queries sur ownership. Acceptabilité E-10 : "checkOwnership N+1 queries (2 DB × 500 proofIds)." Plan §9 TODO : "Optimiser avec requête set-based (IN clause)." Impact performance non quantifié — potentiellement 1000 requêtes DB pour un export max.

  • ZO-07 : Rôle LEGAL_GUARDIAN hardcodé à USER. Acceptabilité Stubs : "Role hardcodé à USER dans controller." Le flux F3 (spec §5.6) et TC-NOM-03 (tests) exigent exportedBy.role = LEGAL_GUARDIAN. Le test TC-NOM-03 passe (PASS en acceptabilité) mais le stub implique que la détection dynamique n'est pas implémentée. Contradiction potentielle entre le PASS du test et le stub : le test pourrait forcer le rôle en fixture sans tester la détection réelle.

5. 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 : 1 divergence BLOQUANTE (DIV-01 — audit fail-closed), 3 divergences MAJEURES (DIV-02, DIV-05, DIV-07), et 3 zones d'ombre impactantes (ZO-01 SonarQube, ZO-02 tests S3, ZO-03 estimation taille). Les conditions de levée des réserves de l'acceptabilité (E-01 à E-05) doivent être satisfaites avant soumission au verdict PMO.