Aller au contenu

PD-280 — Rapport de confrontation (Gate 5 — Review plan)

Ce rapport est produit par l'orchestrateur Claude avant la gate PMO 5. Il confronte les documents produits pour identifier convergences, divergences et zones d'ombre.

1. Sources confrontees

Document Etape d'origine Version
Specification (PD-280-specification.md) Etape 1 v3 corrigee
Tests (PD-280-tests.md) Etape 2 v3 corriges
Plan d'implementation (PD-280-plan.md) Etape 4 v1
Code contracts (PD-280-code-contracts.yaml) Etape 4 v1

2. Convergences

2.1 — Modele de domaine unanime Les 4 documents convergent sur CheckResult = {OK, KO, INDETERMINATE, PENDING} et VerificationStatus = {PENDING, DONE}. L'enum est etendu sur place (pas de nouvel enum). Aucune ambiguite residuelle. - Spec §3-4 | Tests §2 matrice INV-280-01 | Plan §1 C1 | Contracts module proof-verification-domain

2.2 — 8 invariants (INV-280-01 a 09, sans 08) alignes Les 8 invariants sont cites avec la meme formulation et les memes identifiants dans les 4 documents. Chaque invariant est mappe a au moins un mecanisme (plan §3), au moins un test (tests §5), et au moins un module de code contracts.

2.3 — 12 criteres d'acceptation couverts Les 12 CAs (CA-01 a CA-12) sont references de maniere coherente entre spec §7, tests §2 (matrice), plan §4 (mapping CA -> mecanismes), et code contracts (invariants par module).

2.4 — Mode SLA lazy sans worker background Les 4 documents excluent explicitement le worker/cron de reevaluation SLA. La reevaluation est declenchee uniquement sur appel API. - Spec §2 hors perimetre + §5.2 | Tests TC-NEG-11 | Plan §9.3 + §10 | Contracts proof-verification-service forbidden

2.5 — Endpoint lecture seule, idempotent, sans lock applicatif Convergence complete sur INV-280-09 (concurrence idempotente) et INV-280-06 (DONE terminal avec rappel identique). - Spec §4-5.3 | Tests TC-NOM-10, TC-INV-06 | Plan §2.3 | Contracts proof-verification-service invariants

2.6 — Mapping interne/API : PENDING -> null Les 4 documents specifient que CheckResult.PENDING interne est expose comme null dans linkResults[*] API, et que la string "PENDING" est interdite en API. - Spec §5.7 | Tests TC-NEG-04 | Plan C2 mapper | Contracts proof-verification-domain forbidden

2.7 — Codes d'erreur HTTP et metier Les 6 cas d'erreur (ERR-280-01 a ERR-280-07) sont specifies avec les memes codes HTTP et codes metier dans spec §6, tests §4-7, plan §6, et contracts C3/C4.

2.8 — Perimetre et exclusions Les 8 elements hors perimetre (BullMQ, worker, creation de preuve, finalisation, invariants constitutionnels, versionnement API, clients legacy, down migration production) sont listes de maniere coherente dans spec §2, tests §9, plan §10.

2.9 — Epic parent aligne PD-217 — LEGAL & COMPLIANCE est reference dans les 4 documents (correction DIV-05 appliquee en v3).

2.10 — verificationRequestId comme identifiant technique UUID v4 genere cote serveur, present sur toute reponse 200, stable en rappel idempotent DONE. - Spec §3 + §5.1 | Tests TC-NOM-09 | Plan C1 interfaces | Contracts proof-verification-domain CA-11

3. Divergences

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

DIV-S5-01 — Scenario SCN-280-04 (indeterminate durable) sans test dedie

  • Source A (Spec §8 SCN-280-04) : Scenario explicite — "Given blockchain inaccessible, When verification echoue sans perspective de resolution courte, Then resultat maillon = INDETERMINATE".
  • Source B (Tests §3) : La numerotation saute de TC-NOM-03 a TC-NOM-05. Aucun TC-NOM-04 n'existe. La matrice de couverture §2 ne reference pas de test dedie pour le cas "determination immediate INDETERMINATE par inaccessibilite blockchain" (distinct de la reclassification SLA lazy couverte par TC-NOM-05).
  • Source C (Plan §5) : Le mapping TC-* -> mecanismes ne contient pas de ligne pour SCN-280-04.
  • Impact : Chemin metier non couvert par les tests. La distinction entre "INDETERMINATE par inaccessibilite immediate" et "INDETERMINATE par expiration SLA" represente deux chemins de code differents dans le service (evaluation directe vs reclassification lazy). L'absence de test dedie laisse un trou de couverture sur CA-03 (partiellement — le cas PENDING est couvert, pas le cas INDETERMINATE direct).

DIV-S5-02 — Strategie DDL resolue par le plan sans engagement de la spec

  • Source A (Spec §5.4) : Presente deux options — "Colonne check_result : soit varchar (inchangee), soit enum PostgreSQL 3 valeurs -> enum PostgreSQL 4 valeurs (ajout PENDING)".
  • Source B (Plan §1 C5) : Tranche pour ALTER TYPE ... ADD VALUE 'PENDING' (extension enum PostgreSQL). La decision est presentee comme definitive sans qualifier explicitement l'alternative varchar ecartee.
  • Source C (Code contracts proof-verification-migration) : Invariant "Enum PostgreSQL check_result contient 4 valeurs apres migration" — presuppose l'option enum.
  • Impact : Si l'enum PostgreSQL n'est pas le mecanisme reel en base (varchar), la migration est incorrecte. La spec ouvrait la porte aux deux options ; le plan a tranche sans marquer explicitement cette decision architecturale. L'hypothese HT-03 du plan ("le champ chain_blockchain a deja default: 'PENDING' en DB") suggere que PENDING pourrait deja exister comme string meme sans enum — renforce la necessite de verifier le type reel avant implementation.

DIV-S5-03 — Stockage du verificationRequestId non specifie

  • Source A (Spec §3, §5.1) : Definit verificationRequestId comme "UUID v4 technique, porte par la reponse, identifiant la verification materialisee cote serveur". Implique une materialisation persistante.
  • Source B (Plan HT-05) : Hypothese non resolue — "genere par le serveur via crypto.randomUUID() et stocke en association avec le proofId (table de cache ou colonne additionnelle)". Aucun schema de persistance defini.
  • Source C (Plan §1 C5 migration) : Mentionne "ajout eventuel de colonnes" — le "eventuel" contredit l'obligation de materialiser le verificationRequestId pour l'idempotence (INV-280-06 : "retourne la reponse DONE existante a l'identique, y compris verificationRequestId").
  • Source D (Code contracts proof-verification-migration) : Aucune mention de verificationRequestId dans les invariants ou les fichiers du module migration.
  • Impact : L'idempotence INV-280-06 exige que le meme verificationRequestId soit retourne sur rappel. Sans mecanisme de stockage defini, l'implementeur doit improviser. Si verificationRequestId est regenere a chaque appel, INV-280-06 est viole. C'est un manque structurant dans le plan.

DIV-S5-04 — Validation runtime de pendingReason hors enum non couverte par l'intercepteur

  • Source A (Spec §5.1) : pendingReason — "Rejet 500 (si present hors contrat ou valeur hors enum)".
  • Source B (Code contracts proof-verification-guards) : Les invariants de l'intercepteur couvrent INV-280-02 (DONE + null), INV-280-03 (DONE + pending*), ERR-280-03, ERR-280-07 (PENDING en linkResults). Aucun invariant ne mentionne la validation que pendingReason est dans l'enum autorisee.
  • Source C (Plan §1 C4) : L'intercepteur verifie "INV-280-02, INV-280-03, valeur PENDING interdite en API" — pas de mention de validation de la valeur de pendingReason.
  • Impact : Si un processus interne produit un pendingReason hors enum (ex: une nouvelle raison ajoutee en DB sans mise a jour du code), l'intercepteur ne le detecterait pas selon les contracts actuels. Le DTO TypeScript assure une protection a la compilation, mais pas au runtime si la valeur vient de la base de donnees.

4. Zones d'ombre

ZO-S5-01 — Disponibilite du timestamp pending_since par maillon (HT-06)

Le plan HT-06 pose comme hypothese que "les timestamps pending_since par maillon sont disponibles ou derivables depuis les donnees existantes". Si faux, une colonne pending_since doit etre ajoutee a la migration. La migration C5 ne mentionne pas cette colonne. Le mecanisme SLA lazy (TC-NOM-05, ERR-280-05) depend directement de ce timestamp. Aucun document ne confirme l'existence de cette donnee.

ZO-S5-02 — Entite LegalCompositeProof comme point d'entree (HT-01)

Le plan presuppose que LegalCompositeProof (schema vault_secure) expose un champ proofId UUID v4 utilisable comme cle d'entree. La spec ne mentionne pas cette entite par nom. Si l'entite n'existe pas ou utilise un identifiant different, le controller et le service doivent etre repenses.

ZO-S5-03 — Comportement hors bornes de pendingResolutionTtl non tranche

Spec §8 SCN-280-09 dit "rejet/normalisation hors bornes selon mecanisme de config". Tests TC-NEG-09 dit "Rejet de configuration ou normalisation selon mecanisme contractuel de config". Plan C1 et code contracts ne specifient pas si c'est un rejet (erreur au demarrage) ou une normalisation (clamp silencieux). Le mecanisme n'est pas decide.

ZO-S5-04 — Application de PENDING dans PD-251 non gardee

Plan §9.4 affirme que "PD-251 ne doit jamais produire PENDING dans ses resultats finaux". Code contracts et tests ne contiennent aucun mecanisme ou test verifiant cette contrainte. TC-NR-01 verifie que la suite PD-251 existante reste verte, mais ne verifie pas que PD-251 ne produit pas PENDING.

ZO-S5-05 — Schema anchor_batches et detection PENDING_FINALITY (HT-04)

Le plan presuppose que la table anchor_batches (schema vault_blockchain) contient un champ status avec la valeur PENDING_FINALITY. C'est une hypothese non verifiee. Si le champ ou la valeur n'existent pas, le mecanisme de detection du maillon blockchain en attente (CA-03, TC-NOM-03) ne peut pas etre implemente.

ZO-S5-06 — Down migration avec donnees PENDING actives

Reconnu comme non tranche par spec §10.2, plan §10, et code contracts (forbidden "sans plan explicite"). Aucune decision n'est attendue dans ce perimetre, mais le risque est documente. Pas bloquant pour Gate 5.

ZO-S5-07 — Tests documentaires et formels non automatisables dans le perimetre

TC-NR-03 (verification textuelle RFC), TC-NEG-11 (absence de worker), TC-NOM-07 et TC-ERR-06 (pipeline TLA+) dependent de CI ou de verification manuelle. Le plan les classe comme "Documentaire" ou "CI/Formel" mais ne specifie pas comment ils sont integres dans la suite de tests automatisee de l'etape 7 (acceptabilite). Le risque est un oubli en phase d'acceptabilite.

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 : L'alignement global entre les 4 documents est solide (modele, invariants, CAs, perimetre). Cependant, 3 divergences necessitent correction avant soumission a la Gate 5 :

  1. DIV-S5-01 (bloquant) : Ajouter un test TC-NOM-04 couvrant SCN-280-04 (INDETERMINATE durable par inaccessibilite blockchain) dans le document de tests.
  2. DIV-S5-03 (bloquant) : Specifier le mecanisme de stockage du verificationRequestId dans le plan (colonne, table, ou derivation deterministe) — requis pour satisfaire INV-280-06.
  3. DIV-S5-02 (mineur) : Qualifier explicitement dans le plan la decision "enum PostgreSQL" vs "varchar" comme decision architecturale documentee.
  4. DIV-S5-04 (mineur) : Ajouter un invariant de validation pendingReason dans les contracts du module proof-verification-guards ou documenter que la protection TypeScript est suffisante.