Aller au contenu

PD-280 — Rapport de confrontation (Gate 8 — 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 confrontees

Document Etape Version
PD-280-specification.md Etape 1 v3 corrigee
PD-280-tests.md Etape 2 v3 corriges
PD-280-plan.md Etape 4 v1
PD-280-acceptability.md Etape 7 v1

2. Convergences

2.1 Domaine metier et modele de donnees

  • CheckResult a 4 valeurs : Les 4 documents s'accordent sur {OK, KO, INDETERMINATE, PENDING} comme domaine exact de CheckResult (Spec §4 INV-280-01, Tests TC-NOM-08, Plan C1, Acceptability §4.3 TC-NOM-08 PASS).
  • verificationStatus : Les 4 documents definissent un enum {PENDING, DONE} au niveau job (Spec §3/§4 INV-280-02, Tests TC-NOM-01/TC-NOM-02, Plan C1, Acceptability §4.3 PASS).
  • verificationRequestId : UUID v4 technique genere a la creation du job, lu par l'endpoint. Coherent entre Spec §3/§5.1 AMB-V2-01, Tests TC-NOM-09, Plan DDL-02, Acceptability §4.3 TC-NOM-09 PASS.
  • Mapping interne/API : CheckResult.PENDING interne → null en API dans linkResults. Jamais la string "PENDING" exposee cote API publique (Spec §5.7, Tests TC-NEG-04, Plan C2/C4, Acceptability §4.3 TC-NEG-04 PASS).

2.2 Invariants

  • 9 invariants (INV-280-01 a INV-280-09, sans INV-280-08 retire) : Presentes dans la Spec §4, couvertes par les Tests §5, mappees par le Plan §3, et tracees par l'Acceptability §6. Convergence totale sur la definition de chaque invariant.
  • Machine a etats monotone : Transitions PENDING → {OK,KO,INDETERMINATE} pour les maillons, PENDING → DONE pour le job. Retour interdit. Coherent dans les 4 documents (Spec §5.3, Tests TC-INV-05/TC-INV-06/TC-NEG-06/TC-NEG-07, Plan §3, Acceptability PASS).

2.3 Reevaluation SLA

  • Mode lazy uniquement : Aucun worker/cron dans ce perimetre. Les 4 documents convergent explicitement (Spec §2/§5.2, Tests TC-NEG-11, Plan §9.3, Acceptability TC-NEG-11 ABSENT car documentaire).
  • Bornes SLA : pendingResolutionTtl [1h, 30j], nextCheckAfterSeconds clamp [1, 86400]. Convergent (Spec §5.2, Tests TC-NEG-05/TC-NEG-09, Plan C1, Acceptability PASS).

2.4 Idempotence et lecture seule

  • Endpoint en lecture seule : Aucune mutation par l'appel de verification. Coherent (Spec §4 INV-280-09, Tests TC-NOM-10, Plan §2.2/§2.3, Acceptability TC-NOM-10 PASS).
  • DONE terminal et idempotent : Rappel sur proofId deja DONE retourne la reponse DONE existante a l'identique (Spec §4 INV-280-06/ECT-V2-01, Tests TC-INV-06/TC-NEG-07, Plan §2.3, Acceptability PASS).

2.5 Cas d'erreur et format

  • 7 cas d'erreur (ERR-280-01 a ERR-280-07) : Definis dans la Spec §6, couverts par les Tests §4/§7, mappes par le Plan §6. Coherence totale sur les codes HTTP et codes metier.
  • 4 cles contractuelles linkResults : DOCUMENT_HASH, MERKLE_PROOF, TSA_TIMESTAMP, BLOCKCHAIN_ANCHOR. Coherent (Spec §5.1, Tests TC-NR-02, Plan C2, Acceptability PASS).
  • 12 criteres d'acceptation (CA-01 a CA-12) : Definis dans la Spec §7, mappes par les Tests §2, couverts par le Plan §4, traces dans l'Acceptability §6.

2.6 Perimetre et hors perimetre

  • Les 4 documents convergent sur les exclusions : pas de worker background, pas de queue/BullMQ, pas de modification endpoint creation preuve, pas de modification finalisation, invariants constitutionnels transversaux appliques par defaut (Spec §2, Tests §9, Plan §10, Acceptability §4.3).
  • Epic parent : PD-217 — LEGAL & COMPLIANCE aligne dans les 4 documents (Spec §References, Tests §1, Plan implicite, Acceptability §1).

2.7 Couverture de test

  • 25/30 TC implementes et passants : Acceptability §4.3 confirme 25 TC PASS sur 30 definis. Les 5 ABSENT sont CI/Formel (TC-NOM-07, TC-ERR-06, TC-NR-04), documentaire (TC-NR-03) et architectural (TC-NEG-11). Le Plan §12 prevoyait ces niveaux de test hors scope unitaire backend. Convergence sur l'explication des absences.
  • 49 tests unitaires PD-280, 95% couverture : Acceptability §3/§4.1 confirme.

3. Divergences

Les conflits ne sont JAMAIS lisses. Chaque divergence est rendue visible.

DIV-01 — Semantique "reclassifie" vs "projection" pour le SLA lazy

  • Specification (§5.2, ERR-280-05, SCN-280-05) : Utilise le verbe "reclassifie" et "Le maillon devient INDETERMINATE pendant le traitement de cet appel." Langage impliquant une mutation d'etat.
  • Plan (§2.2) : Dit explicitement "Le mode lazy se traduit par une PROJECTION a la lecture, pas une mutation" et "l'etat en base reste PENDING jusqu'a ce qu'un processus externe le mute."
  • Tests (TC-NOM-05) : "Le maillon devient INDETERMINATE pendant le traitement de cet appel" — meme langage que la Spec.
  • Acceptability (§4.3 TC-NOM-05) : PASS sans distinction projection/mutation.
  • Analyse : La Spec contient une tension interne entre le vocabulaire de mutation ("reclassifie", "devient") et l'invariant INV-280-09 ("endpoint en lecture seule"). Le Plan resout cette tension en choisissant la projection, ce qui est coherent avec INV-280-09. Mais la Spec n'utilise jamais le terme "projection".
  • Impact : Si un consommateur de la Spec interprete "reclassifie" comme une mutation persistee, il pourrait s'attendre a ce que l'etat DB passe a INDETERMINATE apres l'appel. L'implementation actuelle (projection) ne fait pas cela.

DIV-02 — Validation explicite de verificationStatus dans l'intercepteur (E-01)

  • Specification (§5.1) : verificationStatus a le format ^(PENDING|DONE)$ avec "Rejet 500 (violation contrat serveur)" si invalide. Exigence explicite de validation.
  • Plan (C4) : Mentionne que l'intercepteur verifie "INV-280-02, INV-280-03, valeur PENDING interdite en API, validation pendingReason". Ne mentionne pas explicitement la validation verificationStatus ∈ {PENDING, DONE}.
  • Acceptability (E-01, MAJEUR) : Confirme que l'intercepteur ne valide pas verificationStatus explicitement. "Une valeur inconnue pourrait traverser les checks sans etre rejetee."
  • Impact : Ecart MAJEUR entre la Spec (qui exige la validation) et l'implementation (qui ne la fait pas). Le Plan ne couvrait pas explicitement ce point.

DIV-03 — requestId dans les logs d'erreur de l'intercepteur (E-02)

  • Plan (§6) : "Chaque erreur 500 VERIFICATION_CONTRACT_BROKEN produit un log error avec requestId et proofId pour correlation."
  • Acceptability (E-02, MINEUR) : "Logs d'erreur de l'intercepteur ne contiennent pas requestId (uniquement proofId)."
  • Specification (ERR-280-03) : Exige "trace technique obligatoire" pour 500.
  • Impact : Le Plan specifiait requestId dans les logs, l'implementation ne l'a pas fait. Ecart MINEUR de tracabilite.

DIV-04 — TC-NOM-04 absent du document de tests

  • Tests (§3) : Le document definit les scenarios TC-NOM-01 a TC-NOM-10 sauf TC-NOM-04. Le scenario est absent de la liste des flux nominaux et de la matrice de couverture §2.
  • Plan (§5) : Reference explicitement "TC-NOM-04 | SCN-280-04, CA-03 | Service : evaluation maillon blockchain inaccessible | INDETERMINATE (determination immediate)".
  • Acceptability (§4.3) : Liste "TC-NOM-04 | PASS | proof-verification-mapper.service.spec.ts | INDETERMINATE durable explicite".
  • Specification (SCN-280-04) : Definit le scenario "indeterminate durable" correspondant.
  • Impact : Le scenario existe dans la Spec, est implemente et passe (Acceptability), mais n'est pas formellement defini dans le document de tests contractuels. Lacune documentaire qui rompt la tracabilite Tests → Spec.

DIV-05 — Migration DDL : ALTER TYPE vs string existant (E-05)

  • Plan (C5, DDL-01) : "L'enum PostgreSQL check_result passe de 3 a 4 valeurs via ALTER TYPE ... ADD VALUE 'PENDING'" — decision explicite.
  • Plan (HT-03) : "Le champ chain_blockchain dans IntegrityCheckAttempt a deja default: 'PENDING' en DB — ce qui confirme que PostgreSQL accepte deja la string 'PENDING' meme si l'enum TypeScript ne le contient pas" — hypothese.
  • Acceptability (E-05, MINEUR) : "Migration DB ne fait pas ALTER TYPE check_result ADD VALUE 'PENDING'. Le plan mentionne HT-03." L'implementation s'est appuyee sur HT-03 plutot que sur DDL-01.
  • Impact : Le Plan prenait une decision architecturale (ALTER TYPE) mais l'implementation a suivi l'hypothese HT-03 (la DB accepte deja PENDING comme string). Si HT-03 est faux dans certains environnements, l'enum PostgreSQL rejettera la valeur.

DIV-06 — DTO pendingReason : enum vs string (E-06)

  • Specification (§5.1) : pendingReason est defini comme "Enum texte" avec regex stricte et "Rejet 500 si present hors contrat ou valeur hors enum".
  • Plan (C1) : Cree un enum PendingReason { ANCHOR_BATCH_NOT_FINALIZED, TX_NOT_ENOUGH_CONFIRMATIONS }.
  • Acceptability (E-06, MINEUR) : "DTO pendingReason type string au lieu de PendingReason enum. Validation runtime assuree par intercepteur."
  • Impact : Le typage TypeScript ne protege pas statiquement contre une valeur hors enum dans le DTO. La protection est runtime uniquement (intercepteur). Ecart de rigueur par rapport a la Spec et au Plan.

4. Zones d'ombre

ZO-01 — HT-03 non confirme en environnement reel

L'Acceptability §7 indique : "HT-03 — DB accepte deja string 'PENDING' : A confirmer en environnement DEV." Cette hypothese est le fondement de la decision d'implementation (pas d'ALTER TYPE), mais n'est pas verifiee. Aucun des 4 documents ne fournit de preuve de la structure reelle de l'enum PostgreSQL check_result sur les environnements cibles.

ZO-02 — Coherence observee du processus externe apres projection SLA

La Spec et le Plan definissent la reevaluation SLA comme une projection (pas de mutation DB). Mais aucun document ne precise ce qui se passe quand le processus externe (hors perimetre) lit l'etat en base : - L'etat en base reste PENDING (confirmation Plan §2.2). - Le prochain appel API projettera a nouveau INDETERMINATE. - Mais le processus externe pourrait-il considerer le maillon comme encore PENDING et tenter de le resoudre ?

Aucun document ne contractualise le comportement attendu du processus externe face a un maillon PENDING dont le TTL est depasse. Ce point est explicitement hors perimetre mais constitue une zone d'ombre pour la coherence globale du systeme.

ZO-03 — 6 echecs CI pre-existants (Redis/PD-60)

L'Acceptability §3 note "6883/6951 global (6 echecs pre-existants Redis/PD-60)". Aucun document ne confirme que ces 6 echecs sont totalement independants du module integrity. Si un test Redis interagit avec CheckResult ou la verification de preuve, un masquage serait possible.

ZO-04 — Sonar n'a pas analyse le code PD-280

L'Acceptability §8 note : "Le code PD-280 n'a pas ete analyse par le dernier scan Sonar (scan sur version precedente)." Le Quality Gate Sonar backend est vert (0 issues), mais sur le code avant PD-280. Le scan reel du code PD-280 n'a pas encore eu lieu. Aucun document ne fournit d'analyse Sonar du code impacte.

ZO-05 — mapLinkValue fallback silencieux (E-03)

L'Acceptability (E-03, MINEUR) signale que mapLinkValue() retourne null en fallback pour une valeur inconnue au lieu de throw. La Spec ne definit pas explicitement le comportement du mapper pour une valeur hors domaine (elle definit le comportement de l'intercepteur). Le Plan ne specifie pas non plus ce cas dans le mapper. Le masquage de corruption est attenue par l'intercepteur en aval, mais le comportement fail-open du mapper constitue une zone d'ombre architecturale.

ZO-06 — Down migration avec donnees PENDING actives

La Spec §10.2 liste la "Strategie de down migration acceptee en production (en cas de presence de donnees PENDING)" comme non tranchee. Le Plan §9.2 propose un mecanisme (guard sur absence de lignes PENDING + recreation enum) mais ce mecanisme n'est pas implemente (pas d'ALTER TYPE, donc pas de down migration correspondante). Si HT-03 est vrai (string, pas enum PostgreSQL), le probleme de down migration ne se pose pas de la meme facon. Point non clarifie.

5. Recommandation

  • Proceder — convergence confirmee, aucun conflit bloquant
  • Rework necessaire — divergences a resoudre avant de continuer
  • Escalade — decision humaine requise sur un point structurant

Justification : La convergence est forte sur le modele metier, les invariants et les cas d'erreur (§2). Cependant :

  1. DIV-02 (E-01, MAJEUR) : La validation verificationStatus ∈ {PENDING, DONE} dans l'intercepteur est exigee par la Spec §5.1 et absente de l'implementation. C'est un ecart contractuel sur un mecanisme de defense-in-depth. Correction estimee : ~5 lignes + 1 test.
  2. DIV-01 : La tension semantique "reclassifie" vs "projection" merite une clarification dans la Spec pour eviter des interpretations divergentes en aval.
  3. DIV-04 : TC-NOM-04 doit etre ajoute au document de tests pour la tracabilite.
  4. DIV-05 : HT-03 doit etre confirme en environnement DEV (ZO-01) ou la migration ALTER TYPE doit etre ajoutee.

Les autres divergences (DIV-03, DIV-06) et zones d'ombre (ZO-02 a ZO-06) sont MINEUR et ne bloquent pas la gate, mais doivent etre documentees dans le verdict.