Aller au contenu

PD-253 — Confrontation Gate 3 v2

Rôle : Second reviewer (confrontation indépendante) Date : 2026-03-12 Objet : Confirmation ou infirmation des écarts MAJEUR ECT-01/02/03 identifiés dans la review v2


1. Sources confrontées

Document Version analysée Observations
PD-253-specification.md v2 (2026-03-12) 14 invariants, machine à états 8 états, modèle §5.1, SLA §5.⅖.3
PD-253-tests.md v2 (2026-03-12) 14 TC nominaux + 12 TC erreurs + 2 TC invariants + 8 TC négatifs
PD-253-review-step3-v2.md Review Gate 3 v2 Score 8.5/10, verdict RESERVE, 3 MAJEUR + 9 MINEUR

2. Convergences v2 confirmées

Les 6 corrections de la v1 identifiées dans la review v2 sont confirmées par lecture directe des textes sources.

Correction Statut Preuve textuelle
DIV-01 : état FAILED_TIMEOUT absent Corrigée complètement Spec §5.4 : état FAILED_TIMEOUT présent avec note explicative distinguant timeout infra vs échec fonctionnel. TC-ERR-09 couvre l'observable.
DIV-02 : 422 sync/async ambigu Corrigée complètement Spec §6 : 422 absent. TC-ERR-06 explicite la détection asynchrone avec état FAILED + failure_reason. Tests §8 confirment la suppression du 422.
DIV-03 : transition DOWNLOADED non testée Corrigée partiellement Spec §5.4 et §5.5 flux 3 documentent la transition. Aucun TC dédié n'en teste le mécanisme de déclenchement (voir ECT-01).
DIV-04 : fallback strong → standard non contractualisé Corrigée complètement TC-NOM-06 couvre le fallback. INV-253-06 et H-253-06 cohérents.
DIV-05 : accès inter-utilisateur non contractualisé Corrigée complètement Spec §5.7 contractualise les trois opérations (GET/download/DELETE) avec 403 FORBIDDEN_EXPORT_ACCESS. TC-SEC-01 couvre les trois.
ZO-08 : flux annulation non documenté Corrigée complètement Spec §5.5 flux 4 : règles d'idempotence, checkpoint worker, transitions, audit fail-closed. TC-NOM-13/14 couvrent les deux branches.

3. Validation des écarts MAJEUR

ECT Statut Justification
ECT-01 CONFIRMÉ — BLOQUANT La spec §5.5 flux 3 pose la transition READY_FOR_DOWNLOAD → DOWNLOADED comme conditionnée à une "confirmation de téléchargement réussi", sans définir le mécanisme déclencheur (HTTP 200 S3 ? callback client ? endpoint dédié ?). La machine à états §5.4 la liste comme autorisée, mais le trigger est implicite. Parmi les 26 TC (nominaux, erreurs, invariants, négatifs), aucun ne teste ni n'observe cette transition de façon déterministe. TC-NOM-09 est générique ("transitions autorisées/interdites") et ne modélise pas le flux téléchargement. L'état DOWNLOADED est le seul état terminal fonctionnel qui valide la réversibilité complète selon NF Z42-013 — ne pas le couvrir par un test dédié est un gap fonctionnel réel. ECT-01 est confirmé bloquant.
ECT-02 CONFIRMÉ — BLOQUANT Le modèle de données contractuel §5.1 définit uniquement destruction_log[].destruction_act_hash (format hex SHA3-256). Les autres champs structurels de destruction-log.jsondocument_id, destroyed_at, motif légal, référence à l'acte PD-250 — ne sont définis nulle part dans la spec v2. INV-253-09 exige l'exclusion et la consignation des documents détruits dans ce fichier, CA-253-07 et TC-NOM-08 valident sa présence, mais TC-NOM-08 ne peut vérifier l'exhaustivité des champs sans schéma contractualisé. La conformité NF Z42-013 §13.1 requiert une traçabilité structurée de la destruction — un schéma partiel ne suffit pas. ECT-02 est confirmé bloquant.
ECT-03 CONFIRMÉ — BLOQUANT Le champ failure_reason est référencé en spec §6 (failure_reason: PROOF_ENVELOPE_INCOMPLETE) et en TC-ERR-06 comme "observable dans les métadonnées de l'export". Il n'apparaît pas dans le modèle de données §5.1. Son format (enum ? string libre ?), son emplacement (colonne export.failure_reason en DB ? champ dans la réponse GET /exports/{id} ?), et l'énumération exhaustive de ses valeurs contractuelles sont absents. TC-NEG-03 référence également un failure_reason observable sans le contractualiser. Sans modélisation dans §5.1, "observable" reste une promesse informelle : un implémenteur peut exposer la valeur dans un champ non-standard ou la logguer seulement, rendant le test TC-ERR-06 non-déterministe. ECT-03 est confirmé bloquant.

4. Zones d'ombre supplémentaires

Les points suivants ne figurent pas dans la review v2 et méritent attention avant Gate 5.

ZA-01 [MINEUR — à résoudre Gate 5] : Libération de quota après états terminaux non confirmée explicitement pour TOUS les terminaux.

La spec §3 définit "Export actif" comme REQUESTED ou ASSEMBLING ou READY_FOR_DOWNLOAD — ce qui exclut implicitement DOWNLOADED, EXPIRED, FAILED, FAILED_TIMEOUT, CANCELLED du quota. Cela est cohérent. Mais aucune clause contractuelle ne confirme que le passage à un état terminal libère le slot de quota en temps réel (vs batch). Si la libération est différée, un utilisateur dont l'export vient de passer en FAILED ne pourrait pas relancer immédiatement. Ce point doit être tranché dans le plan (Gate 5) pour éviter une implémentation ambiguë.

ZA-02 [MINEUR — observation] : 504 EXPORT_TIMEOUT comme code HTTP de réponse synchrone est incohérent avec l'architecture async.

La spec §6 liste 504 EXPORT_TIMEOUT parmi les codes d'erreur, mais l'export est asynchrone : le passage en FAILED_TIMEOUT est produit par le worker, pas par la couche HTTP synchrone. Un client qui crée un export ne reçoit jamais de 504 en réponse directe. Un client qui fait GET /exports/{id} sur un export en FAILED_TIMEOUT reçoit logiquement un 200 avec status: FAILED_TIMEOUT. La review v2 le signale comme ECT-12 MINEUR — ce second reviewer confirme que l'ambiguïté est réelle mais n'est pas bloquante pour Gate 3 (c'est une question d'API design à préciser au plan). Niveau : MINEUR, à traiter en Gate 5.

ZA-03 [OBSERVATION — non bloquant] : TC-NOM-01 (exhaustivité GLOBAL) ne précise pas le comportement attendu si un document est ajouté au coffre pendant l'assemblage.

Le test fixe un "dataset figé et versionné" avant l'exécution, ce qui est une bonne pratique. Mais la spec ne contractualise pas de snapshot sémantique au moment de la création de la demande d'export. Si un document est créé ou supprimé entre REQUESTED et ASSEMBLING, la spec reste silencieuse sur son inclusion. Ce n'est pas bloquant pour Gate 3 (la spec mentionne des critères clairs de sélection de périmètre), mais mérite une note dans le plan.

ZA-04 [OBSERVATION — non bloquant] : Aucun test ne couvre le cas scope=SELECTION avec une liste de document_id vide ou invalide.

TC-ERR-01 couvre les UUID malformés et les enums invalides. Mais une liste de document_id syntaxiquement valides mais ne correspondant à aucun document du coffre de l'utilisateur n'est pas testée. La spec §6 ne définit pas de code d'erreur dédié pour ce cas (400 INVALID_SCOPE_OR_FILTER est le plus proche, mais son libellé vise les filtres de format). Non bloquant pour Gate 3.


5. Recommandation

Tableau de synthèse

ECT Statut Justification résumée
ECT-01 CONFIRMÉ — BLOQUANT Transition READY_FOR_DOWNLOAD → DOWNLOADED : trigger non défini, aucun TC dédié. État terminal de réversibilité non couvert.
ECT-02 CONFIRMÉ — BLOQUANT Schéma destruction-log.json partiel (seul destruction_act_hash défini). Conformité NF Z42-013 §13.1 non garantissable par les tests.
ECT-03 CONFIRMÉ — BLOQUANT failure_reason absent du modèle §5.1. Format, emplacement API et enum non contractualisés. TC-ERR-06 reste non-déterministe.
ECT-04 à ECT-12 Confirmés MINEURS Cohérents avec l'analyse de la review v2. Aucun de ces écarts ne change la recommandation finale.
ZA-01 Nouveau MINEUR Libération quota après état terminal non contractualisée explicitement. À Gate 5.
ZA-02 Nouveau MINEUR 504 EXPORT_TIMEOUT sémantiquement incohérent avec l'async. Confirmé ECT-12, à Gate 5.
ZA-03/04 Observation Non bloquants. À documenter dans le plan.

Verdict final

RESERVE

Le verdict de la review v2 est confirmé sans réserve supplémentaire bloquante. Les trois écarts MAJEUR (ECT-01, ECT-02, ECT-03) sont réels, précisément localisés dans les textes sources, et constituent des lacunes de contractualisation qui rendraient les tests correspondants non-déterministes ou incomplets.

Les 6 corrections v1 sont validées (5 complètes, 1 partielle — DIV-03 levée partiellement mais source d'ECT-01). La maturité globale de la spec v2 est haute : le RESERVE est attribuable à des gaps circonscrits et corrigibles, non à un défaut structurel.

Conditions de passage GO (v3) — identiques à la review v2 :

  1. ECT-01 : Définir le mécanisme de confirmation de téléchargement déclenchant READY_FOR_DOWNLOAD → DOWNLOADED dans §5.5 flux 3 et §5.4. Ajouter un TC dédié.
  2. ECT-02 : Contractualiser le schéma complet de destruction-log.json dans §5.1 (a minima : document_id, destroyed_at, destruction_act_hash, référence acte PD-250).
  3. ECT-03 : Modéliser failure_reason dans §5.1 : type enum, emplacement (champ API réponse GET /exports/{id}), valeurs contractualisées exhaustives.

Aucun désaccord de fond avec la review v2. Convergence entre les deux reviewers sur le verdict RESERVE et les conditions de levée.