CONFRONTATION Gate 8 (CLOSURE) — PD-254¶
1. Sources confrontées¶
| Document | Version | Date |
|---|---|---|
| PD-254-specification.md | Validée Gate 3 RESERVE v2 + Gate 5 RESERVE v1 | 2026-03-13 |
| PD-254-tests.md | 45 TC (44 PASS, 1 ABSENT, 1 PARTIEL) | 2026-03-13 |
| PD-254-acceptability.md | Verdict initial REFUSÉ (2 BLOQUANTS) | 2026-03-13 |
| PD-254-review-step8-v1.md | Revue post-correction | 2026-03-13 |
2. Convergences¶
C-01 — Résolution des 2 écarts BLOQUANTS (E-01, E-02)
- E-01 (3 erreurs TypeScript) : confirmé résolu par
npx tsc --noEmitexit 0. Les 3 fichiers corrigés sont identifiés avec preuves factuelles. - E-02 (ManifestIntegrityCheck absent du VerificationEngine) : confirmé résolu.
ManifestService.revalidate()appelé parMigrationCampaignService.runPostcheck()à la ligne 282, rapport peuplé ligne 314. Choix architectural documenté (orchestrateur vs engine) — légitime et conforme à INV-254-12. - Alignement spec : INV-254-12 (§5.7 étape 2) exige revalidation hash + signature au début du postcheck. L'implémentation satisfait cette exigence.
C-02 — Résolution écart MAJEUR E-03 (ESLint)
- 0 erreur ESLint dans le module migration post-correction. Les 2 erreurs sécurité (
detect-object-injection,detect-unsafe-regex) et les 10 erreurs qualité sont corrigées. - Les 5 warnings résiduels sont hors périmètre PD-254. Conforme.
C-03 — Couverture fonctionnelle solide
- 44/45 tests contractuels PASS (acceptabilité initiale). TC-INV-07 (rollback manuel) ABSENT — hors scope automatisé, conforme à la spec §5.4.
- TC-ERR-07 (timeout BullMQ) PARTIEL — couvert par config, non E2E. Acceptable pour une story protocolaire.
- La matrice de couverture (tests §2) couvre les 11 invariants, les 12 cas d'erreur, les 8 flux nominaux, les 11 tests négatifs et les 5 tests de non-régression.
C-04 — Machine d'états conforme
- TC-INV-10A/10B : matrice exhaustive des transitions, états terminaux fermés. Aligné avec spec §5.2.
- Codes d'erreur métier (§3, §5.2) distincts des états formels — vérifié par TC-CODES-METIER-01.
C-05 — Document protocole présent
- TC-NOM-01 PASS : document Markdown avec les 3 types de migration (support, provider, région). Conforme CA-01.
3. Divergences¶
D-01 — RÉGRESSION : test READABILITY_RATE (224/225) — MAJEUR
- Fait :
validation.spec.ts:137— regex^[01](\.\d{1,4})?$accepte1.0001à1.9999. - Spec : §5.1 définit
readability_sample_pass_ratedans0.0000..1.0000avec regex^(0(\.\d{1,4})?|1(\.0{1,4})?)$. - Écart : le code utilise une regex simplifiée qui ne contraint pas la partie après
1.à0000. La regex de la spec est stricte et correcte. Le code diverge de la spec. - Impact : une valeur
1.5000serait acceptée comme pass_rate valide, ce qui violerait le domaine contractuel. L'attestation pourrait contenir unreadability_pass_ratesémantiquement invalide. - Verdict : MAJEUR. La condition de levée « 225/225 PASS après corrections » n'est pas satisfaite.
D-02 — E-04 : chemins code-contracts non vérifiés — MAJEUR
- Fait : les fichiers sont à
src/modules/migration/(confirmé par arborescence). LePD-254-code-contracts.yamlréférencesrc/migration/. - Spec : §5.13 ne prescrit pas l'arborescence, mais les code-contracts sont un artefact de traçabilité (Art. III CONSTITUTIONAL).
- Impact : écart de traçabilité. Les contracts ne pointent pas vers le code réel. Un audit trouverait une incohérence.
- Verdict : MAJEUR pour la traçabilité, non bloquant fonctionnellement.
D-03 — E-05 : JSON.stringify vs RFC 8785 JCS — MINEUR
- Fait :
attestation.service.ts:84utiliseJSON.stringify,manifest.service.ts:95utilisecanonicalize()(RFC 8785). - Spec : §5.6 étape 2 prescrit "JSON canonique, clés triées" pour le manifest. §5.8 ne prescrit pas explicitement la méthode de sérialisation de l'attestation.
- Impact : divergence de convention. Pas de violation fonctionnelle (sign et verify utilisent la même sérialisation). Risque théorique si un vérificateur tiers attend JCS pour l'attestation.
- INV-254-09 (reproductibilité) :
JSON.stringifyest déterministe en Node.js pour un même objet, mais pas garanti cross-runtime. Risque faible mais réel pour la reproductibilité inter-environnement. - Verdict : MINEUR. Recommandation d'alignement sur JCS pour cohérence.
D-04 — E-06 : localeCompare pour tri GRH — MINEUR
- Fait :
global-root-hash.check.ts:18utilisea.localeCompare(b). - Spec : §3 prescrit "lexicographique sur la chaîne hex lowercase (comparaison caractère par caractère, code ASCII croissant)".
- Impact :
localeComparedépend de la locale de l'environnement. Pour hex lowercase ASCII pur, le résultat est correct dans les locales courantes. Mais INV-254-09 (reproductibilité) exige un résultat déterministe cross-environnement. - Verdict : MINEUR.
a < b(comparaison JavaScript par défaut) ou.localeCompare(b, 'en', {sensitivity: 'base'})serait plus rigoureux.
D-05 — E-07 : WormGuard no-op — MINEUR
- Fait :
canActivate()retourne toujourstrue. LeWormRetentionCheckerest défini mais non injecté. - Spec : INV-254-06 exige "aucune suppression/altération d'objet verrouillé WORM". L'événement
WORM_VIOLATION_BLOCKEDest émis correctement viaemitViolation(). - Impact : le guard NestJS ne remplit pas son rôle de garde d'accès HTTP. La protection est assurée au niveau service (MigrationCampaignService), ce qui est fonctionnellement suffisant mais architecturalement incomplet.
- TC-INV-06 et TC-ERR-09 : PASS — l'événement est bien émis. Le test vérifie l'émission, pas le mécanisme de blocage HTTP.
- Verdict : MINEUR. Le guard est un squelette. La protection est effective via le service.
D-06 — E-08 : MigrationModule non enregistré dans AppModule — MINEUR
- Fait :
grep MigrationModule src/app.module.ts— aucun résultat. - Spec : hors périmètre explicite (la spec couvre le protocole, pas le bootstrapping NestJS).
- Impact : le module ne serait pas chargé par NestJS. Attendu (TODO #10 décomposition).
- Verdict : MINEUR. Documenté comme TODO. Non bloquant pour Gate 8 si tracé.
4. Zones d'ombre¶
Z-01 — Coverage non mesuré
- L'acceptabilité note "N/A — Non mesuré (pas de
--coveragesur run isolé)". Aucune donnée de couverture de code. - Impact : impossible de vérifier si les 225 tests couvrent effectivement les chemins critiques (branches
catch, edge cases regex, etc.).
Z-02 — TC-ERR-07 (timeout BullMQ) — PARTIEL
- "Couvert par config timeout, non testé end-to-end". La spec §5.3 définit
verification_timeoutavec des bornes. Le comportement en cas de dépassement n'est pas vérifié en conditions réelles. - Risque : une campagne pourrait rester bloquée en
POSTCHECK_RUNNINGsi le timeout n'est pas correctement propagé.
Z-03 — Clearing conditionnel (TC-CLR-01) PASS mais E-07 WormGuard no-op
- Le clearing fonctionne au niveau service, mais le guard qui devrait bloquer les requêtes HTTP est inactif. Si un endpoint expose une action WORM sans passer par le service, la protection est absente.
Z-04 — Regex attestation vs code
- La spec §5.14 définit
readability_pass_rateavec regex^(0(\.\d{1,4})?|1(\.0{1,4})?)$. Le testvalidation.spec.ts:137utilise une regex différente. Pas de preuve que le code de production utilise la regex de la spec.
Z-05 — Points Q-03/Q-04/Q-06 non figés
- Les tests §10 les identifient comme "règles non testables". Le verdict QA est "testable partiellement". Ces points impactent la reproductibilité contractuelle mais sont hors périmètre d'implémentation PD-254.
5. Recommandation¶
Scoring¶
| Axe | Note | Justification |
|---|---|---|
| Couverture fonctionnelle | 8.5 | 44/45 TC PASS, 1 ABSENT (manuel), machine d'états complète |
| Conformité invariants | 8.0 | 11/11 invariants couverts, INV-254-09 fragilisé par D-03/D-04 |
| Qualité code | 7.0 | BLOQUANTS résolus, mais 1 régression test, regex divergente |
| Traçabilité | 7.0 | E-04 non vérifié, code-contracts potentiellement désalignés |
| Sécurité | 8.5 | ESLint sécurité résolu, WORM fonctionnel via service, guard squelette |
| Complétude | 7.5 | Module non enregistré, WormGuard no-op, coverage non mesuré |
Moyenne : 7.75/10
Verdict¶
- Procéder — convergence confirmée
- Rework nécessaire — 2 réserves MAJEUR à lever
- Escalade
Actions correctives requises (avant verdict GO)¶
| Priorité | Action | Réf |
|---|---|---|
| P1 | Corriger regex READABILITY_RATE pour rejeter 1.0001..1.9999 — aligner sur la regex spec ^(0(\.\d{1,4})?\|1(\.0{1,4})?)$ | D-01, R-01 |
| P1 | Mettre à jour PD-254-code-contracts.yaml : chemins src/migration/ → src/modules/migration/ | D-02, R-02 |
Réserves MINEUR (non bloquantes Gate 8, à tracer comme dette)¶
| ID | Action | Réf |
|---|---|---|
| R-03 | Aligner attestation sur RFC 8785 JCS | D-03 |
| R-04 | Remplacer localeCompare par comparaison byte-order stricte | D-04 |
| R-05 | Injecter WormRetentionChecker dans le guard ou documenter le choix architectural | D-05 |
| R-06 | Enregistrer MigrationModule dans AppModule ou créer ticket dédié | D-06 |
Condition de passage GO¶
- Regex
READABILITY_RATEcorrigée → 225/225 tests PASS PD-254-code-contracts.yamlmis à jour avec chemins correctsnpx tsc --noEmitexit 0 (maintenu)npm run lint0 erreur module migration (maintenu)