Aller au contenu

PD-283 — Rapport de confrontation (Étape 8 — Gate 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 d'origine
PD-283-specification.md Étape 1 (Spécification)
PD-283-tests.md Étape 2 (Tests & Validation)
PD-283-plan.md Étape 4 (Plan d'implémentation)
PD-283-acceptability.md Étape 7 (Acceptabilité)

2. Convergences

  • 13 invariants identiques : Les 13 invariants (INV-283-01 à INV-283-13) sont définis de manière cohérente dans la spec, repris dans la matrice de couverture des tests (§2), mappés aux mécanismes dans le plan (§3), et évalués dans l'acceptabilité. Aucune omission d'invariant entre documents.

  • Machine à états : La table de transitions (§5.5 spec) est strictement respectée dans le plan (C1 — ExportStateMachine), testée (TC-INV-12, TC-NOM-07, TC-NEG-07), et confirmée OK dans l'acceptabilité (INV-283-12).

  • Retry réseau : Les 4 documents convergent sur 3 tentatives max, backoff strict 1s/2s/4s (INV-283-06, CA-02, TC-INV-06, TC-ERR-04). Implémentation confirmée avec tableau [1000, 2000, 4000].

  • Sanitization anti zip-slip : Spec (INV-283-10, ERR-09), tests (TC-INV-10, TC-NEG-02/03/04), plan (C6 — FilenameSanitizer), acceptabilité (INV-283-10 OK) — convergence complète.

  • K_doc uniquement, jamais kmaster : INV-283-11 convergent dans les 4 documents. Mécanisme deriveKDocFromMaster() dans C4, testé par TC-INV-11, confirmé OK en acceptabilité.

  • Nommage archive : Regex ^PV-Dossier-Plainte_[0-9]{4}-[0-9]{2}-[0-9]{2}_[A-Za-z0-9]{8}\.pvproof$ identique dans spec (§3.3), plan (C10), tests (TC-INV-09, TC-NR-01).

  • Extension .pvproof exclusivement : INV-283-09 convergent, confirmé par TC-INV-09, plan C10, acceptabilité OK.

  • pvproof.json première entrée STORED : INV-283-08 convergent dans les 4 documents. Plan précise l'écriture en premier avant la boucle de téléchargement.

  • Notification 24h + bandeau fallback : INV-283-04, CA-12, TC-INV-04, plan C9, acceptabilité OK — convergence sur les deux modes (permission accordée / refusée).

  • 16 critères d'acceptation : Les CA-01 à CA-16 de la spec sont tous couverts par au moins un test et un mécanisme du plan. La matrice de couverture (tests §2) confirme la couverture complète.

  • Cas d'erreur ERR-01 à ERR-09 : Les 9 cas d'erreur de la spec sont mappés dans le plan (§6), couverts par les tests (TC-ERR-01 à TC-ERR-09), et évalués en acceptabilité.

  • Hors périmètre : Plan (§10) et spec (§2) s'accordent exactement sur les exclusions (Android, Web, background, chiffrement conteneur, CLI, MIME, PDF timeline).

3. Divergences

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

  • DIV-01 : INV-283-03 — SHA3-256 vs SHA-256 dans l'acceptabilité
  • Spec (§4 INV-283-03) : « Le hash SHA3-256 est calculé en streaming sur le conteneur final complet. »
  • Plan (§3 INV-283-03) : « StreamingHasher avec sha3_256.create() en lecture par chunks (64KB) » — confirme SHA3-256.
  • Tests (§5 INV-283-03) : « Hash SHA3-256 calculé sur conteneur final complet en flux. »
  • Acceptabilité (synthèse INV-283-03) : « SHA-256 sur archive finale (streaming-hasher) » — mentionne SHA-256 au lieu de SHA3-256.
  • Impact : Si l'implémentation utilise effectivement SHA-256 au lieu de SHA3-256, le hash n'est pas conforme à la spec ni au RFC PV-PACK-001. Divergence à vérifier dans le code source.

  • DIV-02 : INV-283-07 — Passthrough strict (byte-level) vs passthrough sémantique

  • Spec (§4 INV-283-07) : « manifest.json, chronology.json, enveloppes et README sont en passthrough strict. »
  • Spec (§3.1 glossaire) : « Passthrough strict : les artefacts backend sont injectés dans le conteneur sans altération de contenu. »
  • Plan (§3 INV-283-07) : « PvproofAssembler copie binaire sans transformation (bytes identiques) »
  • Acceptabilité (E-03) : « manifest/chronology re-sérialisés via JSON.stringify » — passthrough sémantique (clés/valeurs préservées), pas byte-level.
  • Tests (§5 INV-283-07) : « Comparaison binaire source vs archive » — attente de passthrough binaire.
  • Impact : Le test TC-INV-07 spécifie une comparaison SHA3-256 source vs entrée archive. Si le manifest est parsé puis re-sérialisé, le hash différera (ordre des clés JSON non garanti). L'implémentation contredit la spec ET le plan. L'acceptabilité classe cela en MINEUR, mais le test contractuel TC-INV-07 échouerait sur une comparaison binaire stricte.

  • DIV-03 : URL refresh automatique (F-03 / CA-03) — spécifié mais non implémenté

  • Spec (§5.3 F-03) : « Nouvel appel API pour rafraîchir URLs. Reprise téléchargement au prochain artefact non finalisé. »
  • Spec (CA-03) : « URL expirée déclenche refresh automatique. »
  • Plan (§2.3) : Flux refresh documenté (C3 détecte → C10 → C2 refresh → reprise).
  • Tests (TC-NOM-04) : Test de couverture prévu pour F-03/CA-03.
  • Acceptabilité (T-01) : « L'orchestrateur propage URL_EXPIRED comme erreur terminale au lieu d'un refresh automatique. Documenté comme limitation v1. »
  • Impact : CA-03 est un critère d'acceptation de la spec. L'absence de refresh automatique rend CA-03 non satisfait. Le test TC-NOM-04 ne peut pas passer dans l'état actuel. C'est un écart fonctionnel entre la spec et l'implémentation.

  • DIV-04 : purgeStale() au démarrage — plan le prévoit, implémentation l'omet

  • Plan (§9.3) : « Le TempFileManager.purgeStale() au démarrage couvre ce cas [crash mid-export]. »
  • Plan (§7.3) : « Au démarrage de l'app, TempFileManager.purgeStale() supprime tout résidu de la session précédente. »
  • Acceptabilité (S-01) : « purgeStale() non appelé au début de startExport() » — classé MAJEUR.
  • Impact : Après un crash, des fichiers clairs pourraient persister en violation de INV-283-01 et INV-283-05. Le plan prévoit ce mécanisme mais l'implémentation l'omet.

  • DIV-05 : integrityHash — validation format seule vs vérification fonctionnelle

  • Spec (§3.3) : integrityHash avec regex ^[a-f0-9]{64}$, « Si invalide → export marqué invalide, abort. »
  • Spec (ERR-06) : « Hash/format invalide artefact → Abort export ; signaler artefact corrompu/non conforme. »
  • Tests (TC-ERR-05) : « manifest.json invalide OU integrityHash non conforme regex → Export abort. »
  • Acceptabilité (S-03) : « integrityHash non vérifié fonctionnellement — le hash est validé en format (regex hex 64 chars) mais jamais comparé au fichier téléchargé. L'intégrité repose uniquement sur HTTPS. »
  • Impact : La spec est ambiguë — elle ne dit pas explicitement « comparer le hash au fichier téléchargé », mais la sémantique d'un integrityHash implique une vérification de contenu, pas seulement de format. Sans comparaison, la détection de corruption silencieuse (au-delà de HTTPS) est impossible.

  • DIV-06 : Coverage 77% vs objectif 80%

  • Acceptabilité Phase 1 : « Coverage (statements) 77.18% — Objectif 80% — écart marginal. »
  • Impact : Écart de 2.82 points sur l'objectif de couverture. Les fichiers à faible couverture sont justifiés (pvproof-assembler 14%, streaming-hasher 17% — dépendances I/O non mockables facilement). L'acceptabilité qualifie l'écart de « marginal ».

  • DIV-07 : Sonar Quality Gate non exécuté

  • Procédure (rules/procedures.md) : « Phase 1.5 (Sonar local) est BLOQUANTE. Si Sonar QG ERROR → STOP avant reviews LLM. »
  • Acceptabilité Phase 1.5 : « sonar-scanner → Skipped — token non disponible dans Vault. Status WARN. »
  • Impact : La procédure exige un Sonar scan bloquant. Le scan n'a pas été exécuté. Le plugin ESLint sonarjs a été utilisé en substitution locale, mais les règles (procedures.md) précisent que « La dérogation ESLint+tsc comme substitution n'est PLUS acceptée. »

4. Zones d'ombre

  • ZO-01 : Schémas JSON détaillés PD-85 (manifest.json, chronology.json, rejectedProofs). Reconnu comme limitation dans les 4 documents (spec §10 pt 1, tests §9 « règle non testable », plan §9.6 « dette »). La validation structurelle est limitée à « JSON valide + champs 1er niveau ». Aucun document ne précise quels sont les champs obligatoires de premier niveau attendus.

  • ZO-02 : Persistance du registre TempFileManager. Le plan (§9.3) mentionne : « il faut s'assurer que le registre des temporaires est persisté (AsyncStorage) pour survivre au crash ». Aucun autre document ne confirme que cette persistance est implémentée. Si le registre est en mémoire seule, purgeStale() au démarrage ne peut pas connaître les fichiers à purger.

  • ZO-03 : Stubs sans story destination. L'acceptabilité identifie 3 stubs (S-01, S-03, T-01) tous marqués « STUB: PD-XXX ». La procédure (learnings.md) exige que chaque stub ait une « story de destination exacte ». Les 3 stubs utilisent PD-XXX au lieu d'une vraie référence Jira. Ces stubs sans story tracable sont signalés MAJEUR en Gate 8 selon la procédure.

  • ZO-04 : Spike librairie ZIP streaming (plan §9.1). Le plan classe ce spike en « priorité maximale » et exige qu'il soit validé « AVANT l'implémentation des autres composants ». Le choix final (fflate) est mentionné dans l'acceptabilité (E-01 : « fflate Zip est streaming par nature ») mais aucun document ne trace la validation formelle du spike ni ses résultats.

  • ZO-05 : Comportement exact du 403 en contexte download vs 403 FREE. Le plan (C3) documente la disambiguation (403 FREE = pas de exportId ; 403 URL = contexte download). La spec ne formalise pas cette distinction. Les tests ne couvrent pas explicitement la disambiguation des deux types de 403.

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 : 3 divergences structurantes nécessitent résolution : 1. DIV-01 (SHA3-256 vs SHA-256) : possible erreur rédactionnelle dans l'acceptabilité, à vérifier dans le code. 2. DIV-03 (URL refresh non implémenté) : CA-03 non satisfait — soit implémenter, soit dégrader CA-03 avec justification et stub tracé. 3. DIV-07 (Sonar skipped) : procédure bloquante non respectée.

Les divergences DIV-02 (passthrough), DIV-04 (purgeStale), DIV-05 (integrityHash) sont correctement identifiées comme écarts MAJEURS dans l'acceptabilité avec stubs, mais les stubs manquent de story destination (ZO-03).