Aller au contenu

PD-254 — Specification Review (Gate 3 — CONFORMITY_CHECK)

Auditeur : Claude (orchestrateur) Date : 2026-03-13 Documents analysés : PD-254-specification.md (v2), PD-254-tests.md (v2) Itération : v2


Bilan corrections v1

Les 15 constats de la review v1 ont été traités :

ID v1 Gravité Statut v2 Correction appliquée
C-01 Bloquant Corrigé §3 définit explicitement « Codes d'erreur métier » distincts des états. §5.2 documente leur comportement (aucune transition).
C-02 Bloquant Corrigé §3 spécifie « lexicographique sur la chaîne hex lowercase des merkle_root ».
C-03 Bloquant Corrigé §3 définit 3 critères de lisibilité (I/O, MIME, décodage 1024 octets).
C-04 Majeur Corrigé §5.9 step 2 précise « compare source avec lui-même (source/source) ».
C-05 Majeur Corrigé precheck_ttl max réduit à 168h. INV-254-12 + revalidation source_object_count ajoutés.
C-06 Bloquant Corrigé INV-254-12, manifest_hash (SHA3-256) et manifest_signature (HSM) ajoutés. §5.7 step 2 revalide au postcheck.
C-07 Majeur Corrigé INV-254-11 retiré du périmètre avec note explicative. Numérotation saute 10→12.
C-08 Majeur Corrigé §3 définit « Artefacts logiques » : verdict, écarts, hash objets. Exclusions explicites.
C-09 Majeur Corrigé TC-CLR-01 et CA-18 ajoutés avec scénario multi-cycles complet.
C-10 Mineur Corrigé ERR-09 nomme explicitement WORM_VIOLATION_BLOCKED.
C-11 Mineur Corrigé §3 définit « Initiateur » (service account ou utilisateur authentifié).
C-12 Mineur Corrigé Transitions retour réorganisées sous les états sources corrects.
C-13 Majeur Corrigé protocol_version ajouté dans §5.1, schemas JSON §5.14, manifest, attestation.
C-14 Majeur Atténué Spec plus explicite sur le périmètre (protocole de vérification). Résiduel mineur R-08.
C-15 Majeur Corrigé §5.14 fournit JSON Schemas complets pour manifest et attestation.

Constats v2

R-01 — Code métier MANIFEST_STALE non défini

Type : Contradiction Référence : §3 (définitions codes métier), §5.2 (règles générales), §5.7 step 3, ERR-12, TC-ERR-12 Description : §3 et §5.2 énumèrent exactement 5 codes d'erreur métier : INVALID_INPUT, INVALID_MANIFEST, CONCURRENT_EXECUTION_DENIED, ATTESTATION_FAILED, PRECHECK_EXPIRED. Or, §5.7 step 3 et ERR-12 utilisent un 6e code MANIFEST_STALE (divergence source_object_count) qui n'apparaît ni dans §3, ni dans §5.2 (règles générales). TC-INV-10A affirme « 10 états formels + 5 codes métier » — ce décompte est incorrect si MANIFEST_STALE fait partie du contrat. Impact : INV-254-10 (toute transition explicite) est violé : le comportement de MANIFEST_STALE n'est pas formellement ancré. TC-INV-10A ne testera pas ce 6e code. Gravité : Bloquant


R-02 — Transition ERR-12 impossible : POSTCHECK_RUNNING → DRAFT

Type : Contradiction Référence : ERR-12 vs §5.2 (transitions POSTCHECK_RUNNING) Description : ERR-12 prescrit « retour à DRAFT obligatoire pour relance avec nouveau manifest » lorsque source_object_count diverge pendant le postcheck. À ce stade, la campagne est en état POSTCHECK_RUNNING. Or, §5.2 n'autorise depuis POSTCHECK_RUNNING que 3 transitions : → VERIFIED, → ROLLED_BACK, → RECONCILIATION_FAILED. La transition → DRAFT n'existe pas dans la machine d'états. TC-ERR-12 hérite de cette contradiction en attendant « Retour à DRAFT ». Impact : Implémentation impossible sans contredire soit ERR-12 soit §5.2. Une équipe tierce ne peut pas trancher. Gravité : Bloquant


R-03 — Canonicalisation JSON du manifest non spécifiée

Type : Ambiguïté Référence : §5.6 step 2 (calcul manifest_hash) Description : §5.6 step 2 prescrit « SHA3-256 du contenu sérialisé du manifest (JSON canonique, clés triées) ». Aucun standard de canonicalisation n'est référencé (RFC 8785 JCS, protocole custom, etc.). Les différences entre sérialiseurs JSON (formatage des nombres, échappement Unicode, espacement, ordre des clés imbriquées) produisent des sorties byte-différentes, donc des hash différents. Impact : INV-254-12 (intégrité manifest) et INV-254-09 (reproductibilité) sont compromis si le manifest est généré par un sérialiseur et vérifié par un autre. Le hash divergerait sans altération réelle, produisant des faux positifs KO. Gravité : Majeur


R-04 — Aucun test dédié pour la transition PRECHECK_EXPIRED

Type : Incohérence Spec↔Tests Référence : §5.2 (PRECHECK_PASSED → DRAFT), §5.4 (SLA precheck), TC-INV-10A Description : §5.2 autorise la transition PRECHECK_PASSED → DRAFT lorsque le TTL du precheck est dépassé, avec émission du code PRECHECK_EXPIRED. Aucun scénario de test ne couvre explicitement ce chemin : ni la détection de l'expiration, ni le retour à DRAFT, ni l'émission du code. TC-INV-10A affirme tester « chaque transition autorisée et interdite » mais sans scénario isolé pour PRECHECK_EXPIRED. Impact : La transition de retour la plus critique (invalidation temporelle du precheck) n'est pas vérifiable par les tests fournis. Un bug sur le contrôle TTL passerait inaperçu. Gravité : Majeur


R-05 — Mécanisme de détection de PRECHECK_EXPIRED non spécifié

Type : Ambiguïté Référence : §5.2 (PRECHECK_PASSED), §5.4 (SLA precheck) Description : §5.2 stipule que le code PRECHECK_EXPIRED est « émis avant retour » à DRAFT quand le TTL est dépassé. La spécification ne précise pas le déclencheur : vérification à la tentative de transition vers CUTOVER_AUTHORIZED (lazy) ? Cron/scheduler (proactif) ? Événement temporel (TTL Redis/BullMQ) ? Le choix affecte directement la latence de détection et le comportement observable. Impact : TC-INV-10A ne peut pas reproduire le scénario sans connaître le déclencheur. Une implémentation lazy (vérification au prochain accès) laisserait la campagne en PRECHECK_PASSED indéfiniment si aucune tentative de cutover n'est faite. Gravité : Majeur


R-06 — readability_sample_count hors bornes : spec vs test

Type : Incohérence Spec↔Tests Référence : §5.3 (readability_sample_count, colonne « Hors bornes ») vs TC-NEG-05 Description : §5.3 prescrit « Clamp au max + trace » pour readability_sample_count hors bornes. TC-NEG-05 attend « Clamp max trace ou rejet selon règle de borne ». Le test introduit un comportement alternatif (rejet) absent de la spécification. Impact : L'implémenteur ne sait pas si la valeur hors borne doit être clampée (spec) ou peut être rejetée (test). Divergence de comportement selon l'interprétation choisie. Gravité : Mineur


R-07 — Transitions retour depuis CUTOVER_AUTHORIZED sans test dédié

Type : Incohérence Spec↔Tests Référence : §5.2 (CUTOVER_AUTHORIZED → PRECHECK_PASSED, CUTOVER_AUTHORIZED → ROLLED_BACK) Description : §5.2 autorise deux transitions retour depuis CUTOVER_AUTHORIZED : retour vers PRECHECK_PASSED (avant exécution, conserve manifest) et vers ROLLED_BACK (annulation opérationnelle). Aucun scénario de test ne couvre ces deux chemins explicitement. TC-INV-10A les englobe théoriquement (« chaque transition autorisée ») mais sans scénario isolé ni conditions déclenchantes. Impact : Le comportement de conservation du manifest lors du retour → PRECHECK_PASSED (« aucun écrasement ») n'est pas vérifié. Une implémentation qui régénère le manifest au retour violerait silencieusement le contrat. Gravité : Mineur


R-08 — TC-NOM-03 présuppose un dataset cible post-migration

Type : Hypothèse dangereuse Référence : TC-NOM-03 vs §2 (hors périmètre) Description : TC-NOM-03 teste le flux precheck → postcheck « sur lot sans altération » et attend la transition POSTCHECK_RUNNING → VERIFIED. Ce chemin implique qu'un dataset cible identique à la source existe. Or, la migration effective est hors périmètre de PD-254 (§2). Le test ne précise pas comment le dataset cible est constitué (fixture pré-positionnée, copie manuelle, stub). Impact : Le scénario nominal n'est pas autoportant pour une exécution par équipe tierce sans hypothèse sur la mise en place du dataset cible. Risque de non-reproductibilité du test. Gravité : Mineur


Synthèse

Gravité Nombre IDs
Bloquant 2 R-01, R-02
Majeur 3 R-03, R-04, R-05
Mineur 3 R-06, R-07, R-08

Total : 8 constats (2 bloquants, 3 majeurs, 3 mineurs)

Progression v1 → v2 : 15 constats (3 bloquants) → 8 constats (2 bloquants). Les 2 bloquants résiduels portent sur le même sujet (code MANIFEST_STALE non défini + transition impossible associée).


Aucune correction proposée. Aucune reformulation. Aucune implémentation.