Aller au contenu

The PD-56 artefacts are in the backend repo. Let me produce the specification review.

PD-56 — Specification Review

Analyse des écarts


Écart 1 — Contradiction : transition d'état sur corruption structurelle (F-06 vs §5.4)

Type : Contradiction
Référence : §5.4 (diagramme d'état + table transitions) vs §5.5 F-06
Description : Le diagramme d'état et la table §5.4 définissent PENDING->CORRUPTED avec condition "preuve incohérente (mismatch) ou structure invalide". Or, F-06 (corruption structurelle) prescrit uniquement le retour ERR-56-03 + SECURITY_ALERT, sans mentionner de transition d'état vers CORRUPTED. En comparaison, F-04 (mismatch cryptographique) décrit explicitement "Persister la transition d'état vers CORRUPTED (écriture DB)".
Impact : Un implémenteur pourrait ne pas persister la transition sur corruption structurelle (en suivant F-06), ou la persister (en suivant le diagramme). Les tests TC-ERR-04 ne vérifient pas de transition d'état non plus, ce qui confirme l'ambiguïté.
Gravité : Bloquant


Écart 2 — Contradiction : émission SECURITY_ALERT sur appel à état CORRUPTED existant (§5.4 vs F-06)

Type : Contradiction
Référence : §5.4 (comportement d'appel sur état terminal) vs §5.5 F-06 vs TC-ERR-10
Description : §5.4 prescrit qu'en état CORRUPTED, getMerkleProof(eventId) retourne ERR-56-03 sans aucune transition d'état — mais ne mentionne pas l'émission de SECURITY_ALERT. F-06 prescrit "Toute émission ERR-56-03 DOIT produire SECURITY_ALERT severity=CRITICAL". TC-ERR-10 attend SECURITY_ALERT à chaque appel sur état CORRUPTED. La spec §5.4 est donc silencieuse sur un comportement que les tests exigent.
Impact : Si SECURITY_ALERT est émis à chaque appel sur état CORRUPTED, un appelant défaillant (ou malveillant) pourrait noyer le bus d'audit avec des alertes critiques par appels répétés. Aucun mécanisme de throttling n'est spécifié.
Gravité : Majeur


Écart 3 — Ambiguïté : "métadonnées batch absentes/inexploitables" (ERR-56-05)

Type : Ambiguïté
Référence : §5.5 F-05, §6 ERR-56-05
Description : Le terme "inexploitables" n'est pas défini. Quels critères rendent une métadonnée batch "inexploitable" ? Format invalide ? Valeur dans le passé ? Absence de champ window_end ? Sans critère objectif, un implémenteur ne peut pas distinguer ERR-56-05 d'un cas pending normal.
Impact : Comportement non déterministe entre implémentations.
Gravité : Majeur


Écart 4 — Ambiguïté : "mécanisme équivalent garantissant pas de perte d'alerte" (§5.7)

Type : Ambiguïté / Non testable
Référence : §5.7
Description : L'atomicité multi-composant exige "transaction DB + outbox, ou mécanisme équivalent". Le terme "équivalent" n'a pas de critère de validation. Aucun test ne vérifie cette atomicité (TC-NOM-11 vérifie l'émission d'alerte, pas l'atomicité avec la transition d'état).
Impact : Un implémenteur pourrait considérer un try/catch avec log comme "équivalent", ce qui violerait la garantie de non-perte.
Gravité : Majeur


Écart 5 — Incohérence Spec↔Tests : référence morte TC-NOM-06 → "AMB-04"

Type : Incohérence Spec↔Tests
Référence : TC-NOM-06 (tests §3)
Description : TC-NOM-06 référence "AMB-04" comme source spec. Cet identifiant n'existe nulle part dans la spécification. La référence correcte serait §5.4 (conditions PENDING->AVAILABLE, contrainte finalized_at IS NOT NULL) et INV-56-06.
Impact : Traçabilité rompue — le test n'est pas auditable vers sa source contractuelle.
Gravité : Mineur


Écart 6 — Incohérence Spec↔Tests : TC-INV-07 et TC-INV-08 sans scénario détaillé

Type : Incohérence Spec↔Tests
Référence : Tests §2 (matrice) et §5 (table invariants)
Description : TC-INV-07 (campagne exhaustive format/bornes) et TC-INV-08 (aucun secret en clair) sont référencés dans la matrice de couverture et la table d'invariants, mais n'ont aucun scénario Given/When/Then dans le document de tests (§3, §4, §7). TC-INV-07 est critique car il couvre INV-56-07 (format-single-source).
Impact : Ces tests ne sont pas implémentables en l'état par une équipe tierce.
Gravité : Majeur (TC-INV-07) / Mineur (TC-INV-08, reconnu partiel)


Écart 7 — Incohérence Spec↔Tests : TC-ERR-04 ne vérifie pas la transition d'état

Type : Incohérence Spec↔Tests
Référence : TC-ERR-04 vs §5.4 diagramme d'état
Description : Si le diagramme d'état est la source de vérité (Écart 1), la corruption structurelle devrait provoquer une transition vers CORRUPTED. TC-ERR-04 ne vérifie que ERR-56-03 + SECURITY_ALERT, pas de transition. En revanche, TC-ERR-08 (mismatch crypto) vérifie explicitement "Transition PENDING->CORRUPTED persistée en base". L'asymétrie entre ces deux tests reflète l'ambiguïté de la spec.
Impact : Selon la résolution de l'Écart 1, TC-ERR-04 est incomplet ou correct.
Gravité : Majeur (conditionnel à l'Écart 1)


Écart 8 — Ambiguïté : initialisation de proofAvailabilityState

Type : Ambiguïté
Référence : §5.4, §5.5, diagramme de séquence
Description : La spec contractualise la machine d'état PENDING/AVAILABLE/CORRUPTED mais ne décrit pas comment l'état initial PENDING est créé. Le diagramme de séquence présuppose que l'état existe déjà lors de la lecture MS. L'initialisation est probablement portée par PD-237, mais aucune hypothèse explicite ne le contractualise (contrairement à H-56-01..H-56-05 qui documentent les dépendances).
Impact : Si PD-237 ne crée pas cet état, le service PD-56 lirait un état NULL non géré.
Gravité : Mineur (dépendance inter-PD implicite, ajout d'hypothèse suffit)


Écart 9 — Hypothèse dangereuse : concurrence sur détection de corruption

Type : Hypothèse dangereuse
Référence : §5.8 (protection distribuée)
Description : §5.8 indique qu'une "transition conditionnelle atomique (row-level lock ou update optimiste) suffit" mais ne précise pas le comportement attendu en cas de conflit. Si deux appels concurrents détectent un mismatch sur le même eventId : (a) avec row-level lock, le second attend puis détecte CORRUPTED existant → ERR-56-03 (correct) ; (b) avec update optimiste, le second pourrait échouer (version conflict) — quel code retourner ? La spec est silencieuse sur ce cas.
Impact : Risque d'erreur non contractualisée (500 interne, retry silencieux, ou comportement indéfini).
Gravité : Mineur


Écart 10 — Cohérence diagramme de séquence : cas "leaf introuvable" sans lecture d'état

Type : Incohérence diagramme (§5bis)
Référence : Diagramme de séquence vs §5.4
Description : Dans le diagramme de séquence, le cas "leaf introuvable" mène directement au chemin pending sans vérifier proofAvailabilityState. Or, si un eventHash a précédemment été résolu puis l'état est passé à CORRUPTED (par un appel antérieur), et que le leaf est ensuite purgé (maintenance DB), le diagramme retournerait pending au lieu de ERR-56-03. Le check proofAvailabilityState = CORRUPTED est positionné comme sibbling de "leaf introuvable", pas comme parent.
Impact : Faible (scénario marginal nécessitant purge de données + état CORRUPTED préexistant), mais le diagramme ne le rend pas évident.
Gravité : Mineur


Écart 11 — Risque sécu/conformité : flood d'alertes SECURITY_ALERT sur état CORRUPTED

Type : Risque sécu/conformité
Référence : §5.5 F-06, INV-56-09
Description : Si chaque appel ERR-56-03 sur état déjà CORRUPTED émet un SECURITY_ALERT severity=CRITICAL (per F-06), un service appelant défaillant en boucle de retry pourrait générer des milliers d'alertes critiques, noyant les vraies alertes de sécurité. §5.8 confirme "Rate-limiting: Non applicable" ce qui est correct pour le service en soi, mais aucun mécanisme de déduplication d'alerte n'est contractualisé.
Impact : Dégradation de la capacité de détection sécurité (alert fatigue).
Gravité : Mineur (service interne, risque atténué par H-56-05)


Écart 12 — Incohérence Spec↔Tests : TC-ERR-11 référence "DIV-01" inexistant

Type : Incohérence Spec↔Tests
Référence : TC-ERR-11 (tests §4)
Description : TC-ERR-11 référence "DIV-01" comme source spec. Cet identifiant n'existe pas dans la spécification PD-56. La référence correcte serait §5.4 (transitions) et INV-56-06.
Impact : Traçabilité rompue.
Gravité : Mineur


Synthèse

Gravité Nombre
Bloquant 1
Majeur 5
Mineur 6

Écart bloquant : La contradiction entre le diagramme d'état et F-06 concernant la transition vers CORRUPTED sur corruption structurelle (Écart 1) doit être résolue avant implémentation. Toute la chaîne de tests (TC-ERR-04, TC-INV-06) en dépend.


Voulez-vous que j'écrive ce fichier dans le repo backend sous PD-56-specification-review.md ?