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.