Aller au contenu

PD-56 — Scénarios de tests contractuels (v3)

1. Références

  • Spécification : PD-56-specification.md (v3).
  • Epic : PD-187.

2. Matrice de couverture

ID Invariant ID Critère ID Test Couverture Commentaire
INV-56-01-root-source-of-truth CA-56-01 TC-NOM-01 Oui merkleRoot retourné strictement égal à la valeur persistée.
INV-56-01-root-source-of-truth CA-56-02 TC-NOM-04 Oui Recalcul off-chain cohérent avec racine persistée.
INV-56-02-determinisme CA-56-01 TC-NOM-03 Oui Même snapshot transactionnel + même eventId => même résultat.
INV-56-03-minimal-disclosure CA-56-01 TC-NOM-08 Oui Vérification stricte des champs exposés.
INV-56-04-algo-explicit CA-56-01 TC-NOM-01 Oui hashAlgorithm et hashAlgorithmVersion obligatoires en available.
INV-56-05-auto-verification CA-56-07 TC-NOM-05 Oui Vérification exécutée avant tout retour available.
INV-56-05-auto-verification CA-56-11 TC-ERR-08 Oui Mismatch racine => transition persistée + ERR-56-04.
INV-56-06-transitions CA-56-08 TC-INV-06 Oui Transitions autorisées validées et tracées.
INV-56-06-transitions CA-56-08 TC-ERR-04 Oui Corruption structurelle => transition vers CORRUPTED vérifiée.
INV-56-06-transitions CA-56-08 TC-ERR-09 Oui AVAILABLE->PENDING refusée.
INV-56-06-transitions CA-56-12 TC-ERR-10 Oui CORRUPTED terminal, aucun sortant.
INV-56-06-transitions CA-56-11 TC-ERR-11 Oui AVAILABLE->CORRUPTED sur mismatch.
INV-56-07-format-single-source CA-56-09 TC-INV-07 Oui Campagne exhaustive format/bornes §5.1/§5.2, inclut treeSize=1/merklePath=[].
INV-56-08-no-secret-cleartext N/A TC-INV-08 Oui (partielle) Vérifiable côté flux PD-56, périmètre global hors scope.
INV-56-09-security-alert-on-first-corruption-detection CA-56-14 TC-NOM-11 Oui Alerte émise à la première détection uniquement.
INV-56-09-security-alert-on-first-corruption-detection CA-56-14 TC-ERR-04 Oui Corruption structurelle initiale -> alerte critique.
INV-56-09-security-alert-on-first-corruption-detection CA-56-14 TC-ERR-08 Oui Corruption cryptographique initiale -> alerte critique.
INV-56-09-security-alert-on-first-corruption-detection CA-56-15 TC-ERR-10 Oui État déjà CORRUPTED -> aucune alerte additionnelle.
N/A CA-56-03 TC-NOM-04 Oui Vérification par script externe sans API/BDD.
N/A CA-56-04 TC-NOM-09 Oui Mesure P95 taille JSON < 10 KB.
N/A CA-56-05 TC-NOM-10 Oui (conditionnelle) Opposabilité liée à benchmark officiel figé.
N/A CA-56-06 TC-NOM-02 Oui pending + ETA UTC conforme.
N/A CA-56-10 TC-NOM-06 Oui Finality gate finalized_at obligatoire pour available.
N/A CA-56-09 TC-NOM-12 Oui Cas limite valide : treeSize=1 et merklePath=[].
N/A CA-56-13 TC-ERR-03 Oui ETA non calculable bornée => ERR-56-05.
N/A CA-56-09 TC-ERR-01 Oui eventId invalide => ERR-56-01.
N/A CA-56-09 TC-ERR-05 Oui Hash/format invalide => ERR-56-03.
N/A CA-56-09 TC-ERR-06 Oui Bornes numériques invalides => ERR-56-03.
N/A CA-56-09 TC-ERR-07 Oui Algo/version invalides => ERR-56-03.

3. Scénarios de test – Flux nominaux

TEST-ID: TC-NOM-01
Référence spec: INV-56-01, INV-56-04, CA-56-01

GIVEN
  - Snapshot S-56-AVAIL figé
  - eventId E1 valide et connu
  - Preuve persistée valide, arbre finalisé (finalized_at IS NOT NULL)
WHEN
  - getMerkleProof(E1) est appelé
THEN
  - status='available'
  - Champs présents et conformes: eventHash, merkleRoot, merklePath, treeId, treeSize, leafIndex, hashAlgorithm='SHA-256', hashAlgorithmVersion='1.0'
  - merkleRoot retourné = merkleRoot persisté
AND
  - Aucun champ hors contrat n’est exposé
TEST-ID: TC-NOM-02
Référence spec: F-02, CA-56-06, ERR-56-02

GIVEN
  - Snapshot S-56-PENDING figé
  - eventId E2 valide et connu
  - finalized_at IS NULL
  - window_end disponible et calculable
WHEN
  - getMerkleProof(E2) est appelé
THEN
  - status='pending'
  - estimatedAvailableAt est présent et conforme RFC3339 UTC (suffixe Z)
AND
  - Aucune donnée de preuve available n’est retournée
TEST-ID: TC-NOM-03
Référence spec: INV-56-02

GIVEN
  - Snapshot transactionnel S-56-AVAIL immuable
  - eventId E1 constant
WHEN
  - Deux appels successifs puis deux appels concurrents sont exécutés
THEN
  - Les résultats sont strictement identiques (égalité structurelle champ-à-champ)
AND
  - Aucun écart de statut, de valeurs, ni de code
TEST-ID: TC-NOM-04
Référence spec: F-03, CA-56-02, CA-56-03

GIVEN
  - Une réponse available valide exportée en JSON
  - Outil externe indépendant (JS ou Python), sans accès API/BDD
WHEN
  - Le tiers recalcule computedRoot = fold(hashPair(sorted(a,b))) en SHA-256
THEN
  - computedRoot == merkleRoot
AND
  - L’exécution du script est réussie sans dépendance backend
TEST-ID: TC-NOM-05
Référence spec: INV-56-05, CA-56-07

GIVEN
  - Snapshot S-56-AVAIL avec observabilité activée (trace corrélée)
WHEN
  - getMerkleProof(E1) est appelé
THEN
  - La vérification cryptographique est exécutée avant l’émission de la réponse available
AND
  - La trace contient la décision de vérification (succès/échec)
TEST-ID: TC-NOM-06
Référence spec: §5.4 (conditions PENDING->AVAILABLE), F-01, CA-56-10

GIVEN
  - eventId E3 avec preuve trouvée et auto-vérification OK
  - finalized_at IS NULL
  - window_end calculable
WHEN
  - getMerkleProof(E3) est appelé
THEN
  - Le service ne retourne pas available
  - Le service retourne pending avec ETA UTC
AND
  - Aucune transition PENDING->AVAILABLE n’est validée sans finality
TEST-ID: TC-INV-06
Référence spec: INV-56-06, CA-56-08

GIVEN
  - Jeux de données forçant les états PENDING, AVAILABLE, CORRUPTED
WHEN
  - Les appels sont rejoués dans des conditions menant aux transitions autorisées
THEN
  - Transitions acceptées: PENDING->PENDING, PENDING->AVAILABLE, PENDING->CORRUPTED, AVAILABLE->AVAILABLE, AVAILABLE->CORRUPTED
AND
  - Aucune transition sortante depuis CORRUPTED
TEST-ID: TC-INV-07
Référence spec: INV-56-07, §5.1, §5.2, CA-56-09

GIVEN
  - Une campagne de conformité FORMAT-56 regroupant:
    * Cas valides frontières (UUID v4 valide, hashes lowercase hex, bornes min/max, treeSize=1 avec merklePath=[])
    * Cas invalides par champ (regex, charset, casse, taille)
    * Cas invalides de cohérence (leafIndex hors plage, merklePath.length hors borne dynamique, merklePath=[] avec treeSize>1)
WHEN
  - Chaque jeu de données est injecté via getMerkleProof(eventId) ou via validations internes équivalentes
THEN
  - Chaque entrée invalide retourne le code contractuel attendu (ERR-56-01 / ERR-56-03 / ERR-56-05 selon la règle)
  - Chaque entrée valide frontière est acceptée
AND
  - Un rapport trace pour chaque cas: {caseId, attendu, observé, verdict}
TEST-ID: TC-INV-08
Référence spec: INV-56-08

GIVEN
  - Traces de persistance PD-56 et payloads de sortie sur scénarios nominaux/erreurs
WHEN
  - Les écritures DB et les réponses sont inspectées
THEN
  - Aucune donnée secrète en clair n’est persistée ni exposée
AND
  - Seuls hashes et métadonnées publiques contractuelles sont manipulés
TEST-ID: TC-NOM-07
Référence spec: §5.3 (expiration ETA)

GIVEN
  - Événement en pending avec ETA W1 expirée
  - Preuve toujours absente
  - Fenêtre suivante connue W2
WHEN
  - getMerkleProof(eventId) est appelé après W1
THEN
  - Le statut reste pending
  - estimatedAvailableAt est recalculé sur W2 en UTC
AND
  - Aucune promotion implicite vers available
TEST-ID: TC-NOM-08
Référence spec: INV-56-03

GIVEN
  - Une réponse available
WHEN
  - Le payload est inspecté
THEN
  - Seuls les champs contractuels de preuve et métadonnées sont présents
AND
  - Aucun payload métier brut, aucune donnée sensible, aucun secret en clair
TEST-ID: TC-NOM-09
Référence spec: CA-56-04

GIVEN
  - Campagne de référence PERF-56-SIZE (N défini, dataset figé)
WHEN
  - Chaque réponse available est sérialisée JSON UTF-8
THEN
  - Le P95 de taille est strictement < 10 KB
AND
  - Le rapport percentile est archivé comme preuve
TEST-ID: TC-NOM-10
Référence spec: CA-56-05

GIVEN
  - Campagne de référence PERF-56-LAT (N défini, dataset figé)
  - Environnement benchmark officiel préalablement figé
WHEN
  - La latence de génération est mesurée
THEN
  - P95 <= 10 ms
AND
  - Rapport horodaté avec distribution complète (P50/P95/P99)
TEST-ID: TC-NOM-11
Référence spec: INV-56-09, CA-56-14, CA-56-15

GIVEN
  - Un scénario de première corruption structurelle (S1) et un scénario de première corruption cryptographique (S2)
  - Puis des appels répétés sur les mêmes eventId déjà passés en CORRUPTED
WHEN
  - Le service traite S1, S2, puis les relectures
THEN
  - Exactement un SECURITY_ALERT CRITICAL est émis par eventId lors de la transition initiale vers CORRUPTED
AND
  - Aucun SECURITY_ALERT supplémentaire n’est émis lors des appels répétés en état CORRUPTED
TEST-ID: TC-NOM-12
Référence spec: §5.1 (règle treeSize=1), CA-56-09

GIVEN
  - eventId E4 avec preuve valide
  - treeSize=1, leafIndex=0, merklePath=[]
  - computedRoot == merkleRoot, finalized_at IS NOT NULL
WHEN
  - getMerkleProof(E4) est appelé
THEN
  - Le service retourne status='available'
AND
  - Aucun ERR-56-03 n’est déclenché sur merklePath de longueur 0

4. Scénarios de test – Cas d’erreur

TEST-ID: TC-ERR-01
Référence spec: ERR-56-01, §5.1 (eventId)

GIVEN
  - eventId invalide (regex UUID v4 non respectée)
WHEN
  - getMerkleProof(eventId) est appelé
THEN
  - Rejet explicite ERR-56-01
AND
  - Aucune preuve retournée
TEST-ID: TC-ERR-02
Référence spec: ERR-56-01

GIVEN
  - eventId valide syntaxiquement mais inexistant
WHEN
  - Appel du service
THEN
  - Rejet explicite ERR-56-01
AND
  - Aucun artefact de preuve n’est exposé
TEST-ID: TC-ERR-03
Référence spec: ERR-56-05, F-05, §5.1 (estimatedAvailableAt)

GIVEN
  - Cas pending où un batch candidat existe
  - finalized_at IS NULL
  - window_end IS NULL (ETA impossible)
WHEN
  - Appel du service
THEN
  - Rejet explicite ERR-56-05
AND
  - Aucun pending sans ETA UTC conforme n’est retourné
TEST-ID: TC-ERR-04
Référence spec: F-06, §5.4, INV-56-06, INV-56-09, CA-56-08, CA-56-14, CA-56-15

GIVEN
  - État courant non CORRUPTED (PENDING ou AVAILABLE)
  - Donnée Merkle structurellement invalide, par exemple:
    * merklePath absent ou null
    * merklePath=[] alors treeSize>1
    * merklePath[i] non conforme format hex
WHEN
  - getMerkleProof(eventId) est appelé
THEN
  - Transition persistée vers CORRUPTED
  - Rejet explicite ERR-56-03
  - SECURITY_ALERT severity=CRITICAL émis (première détection)
AND
  - Un appel immédiat suivant sur le même eventId retourne ERR-56-03 sans nouvelle transition ni nouvelle alerte
TEST-ID: TC-ERR-05
Référence spec: ERR-56-03, §5.1 (eventHash/merkleRoot/merklePath[i])

GIVEN
  - Au moins un hash non conforme (taille, charset, case)
WHEN
  - Appel du service
THEN
  - Rejet explicite ERR-56-03
AND
  - Le motif de format invalide est traçable
TEST-ID: TC-ERR-06
Référence spec: ERR-56-03, §5.2

GIVEN
  - treeSize hors [1..10000] ou leafIndex hors [0..treeSize-1] ou merklePath.length hors borne
WHEN
  - Appel du service
THEN
  - Rejet explicite ERR-56-03
AND
  - Aucune preuve exploitable n’est retournée
TEST-ID: TC-ERR-07
Référence spec: ERR-56-03, INV-56-04

GIVEN
  - Réponse candidate available avec hashAlgorithm ou hashAlgorithmVersion non conformes
WHEN
  - Validation contractuelle du résultat
THEN
  - Rejet explicite ERR-56-03
AND
  - Le statut available est refusé
TEST-ID: TC-ERR-08
Référence spec: ERR-56-04, INV-56-05, CA-56-11, CA-56-14

GIVEN
  - État courant PENDING
  - eventHash + merklePath produisant computedRoot != merkleRoot
WHEN
  - Appel du service
THEN
  - Transition PENDING->CORRUPTED persistée en base
  - Rejet explicite ERR-56-04
AND
  - SECURITY_ALERT severity=CRITICAL émis (première détection)
TEST-ID: TC-ERR-09
Référence spec: §5.4, INV-56-06

GIVEN
  - État courant AVAILABLE
WHEN
  - Une transition vers PENDING est évaluée
THEN
  - Transition refusée contractuellement
AND
  - État conservé, rejet tracé
TEST-ID: TC-ERR-10
Référence spec: §5.4, INV-56-06, INV-56-09, CA-56-12, CA-56-15

GIVEN
  - État courant CORRUPTED déjà persisté
  - Une alerte a déjà été émise lors de la première détection
WHEN
  - getMerkleProof(eventId) est appelé (répétitions incluses)
THEN
  - Retour explicite ERR-56-03
  - Aucune transition d’état n’est effectuée
AND
  - Aucun SECURITY_ALERT additionnel n’est émis
TEST-ID: TC-ERR-11
Référence spec: §5.4, F-04, ERR-56-04, CA-56-11, CA-56-12

GIVEN
  - État courant AVAILABLE
  - Une auto-vérification ultérieure détecte computedRoot != merkleRoot
WHEN
  - getMerkleProof(eventId) est appelé
THEN
  - Transition AVAILABLE->CORRUPTED persistée en base
  - Rejet explicite ERR-56-04
AND
  - Appel suivant sur le même eventId retourne ERR-56-03 (état terminal)

5. Tests d’invariants (non négociables)

Invariant Test(s) dédiés Observable Commentaire
INV-56-01-root-source-of-truth TC-NOM-01, TC-NOM-04 Égalité stricte racine retournée vs persistée Vérifie absence de substitution/recalcul de sortie.
INV-56-02-determinisme TC-NOM-03, TC-NR-04 Résultats identiques à snapshot transactionnel constant Reproductibilité audit.
INV-56-03-minimal-disclosure TC-NOM-08, TC-NEG-10 Liste de champs strictement contractuelle Confidentialité préservée.
INV-56-04-algo-explicit TC-NOM-01, TC-ERR-07 Valeurs exactes SHA-256 / 1.0 Vérification indépendante possible.
INV-56-05-auto-verification TC-NOM-05, TC-ERR-08, TC-ERR-11 Vérification exécutée avant available Détection de corruption active.
INV-56-06-transitions TC-INV-06, TC-ERR-04, TC-ERR-09, TC-ERR-10, TC-ERR-11 Respect machine d’état §5.4 Inclut interdictions et terminalité CORRUPTED.
INV-56-07-format-single-source TC-INV-07, TC-NOM-12 Couverture exhaustive format/bornes §5.1/§5.2 Inclut le cas limite valide treeSize=1.
INV-56-08-no-secret-cleartext TC-INV-08 Aucune persistance/émission de secret en clair Couverture partielle sans preuve globale inter-modules.
INV-56-09-security-alert-on-first-corruption-detection TC-NOM-11, TC-ERR-04, TC-ERR-08, TC-ERR-10 Émission unique sur première détection + absence de flood Traçabilité sécurité opposable.

6. Tests de non-régression

Test ID Objet Observable Commentaire
TC-NR-01 Stabilité contrat available Même schéma de sortie et mêmes règles de validation entre baseline et candidate Non-régression CA-56-01/INV-56-03/INV-56-04.
TC-NR-02 Stabilité contrat pending status='pending' + ETA UTC conforme inchangés Non-régression CA-56-06.
TC-NR-03 Stabilité mapping codes Même entrée invalide => même code ERR-56-0x attendu Non-régression CA-56-09/CA-56-13.
TC-NR-04 Stabilité déterminisme Même snapshot transactionnel => même résultat sur versions successives Non-régression INV-56-02.
TC-NR-05 Stabilité performance P95 taille/latence ne dépassent pas les budgets contractuels Non-régression CA-56-04/CA-56-05.
TC-NR-06 Effets de bord contrôlés Seules écritures autorisées: transition vers CORRUPTED et audit SECURITY_ALERT de première détection Non-régression §5.7/INV-56-09.
TC-NR-07 Anti-flood audit Sur état déjà CORRUPTED, répétitions n’ajoutent pas d’alertes Non-régression CA-56-15.

7. Tests négatifs et adversariaux

Test ID Entrée invalide / abus Résultat attendu Observable
TC-NEG-01 eventId injection (' OR 1=1 --) ERR-56-01 Rejet explicite, aucun effet secondaire
TC-NEG-02 UUID non-v4 mais format UUID ERR-56-01 Rejet regex v4
TC-NEG-03 eventHash uppercase hex ERR-56-03 Rejet case-sensitive
TC-NEG-04 merklePath[i] avec caractère non-hex ERR-56-03 Rejet format élément
TC-NEG-05 merklePath.length = 21 ERR-56-03 Rejet borne max
TC-NEG-06 merklePath.length > ceil(log2(treeSize)) ERR-56-03 Rejet borne dynamique
TC-NEG-07 treeSize = 0 ou 10001 ERR-56-03 Rejet bornes numériques
TC-NEG-08 leafIndex = treeSize ou -1 ERR-56-03 Rejet contrainte d’index
TC-NEG-09 Métadonnée ETA source non UTC (ex: +02:00) Le service doit produire une ETA UTC (Z) dans la réponse pending; si conversion impossible, ERR-56-05 Vérification stricte sortie UTC
TC-NEG-10 Payload sortant contient eventPayload ou donnée métier brute Non-conformité INV-56-03 Contrôle de schéma sortant échoue
TC-NEG-11 hashAlgorithm='sha-256' (mauvaise casse) ERR-56-03 Rejet littéral exact
TC-NEG-12 merklePath permuté (ordre non contractuel) ERR-56-04 puis CORRUPTED Mismatch computedRoot + transition persistée
TC-NEG-13 treeSize=1 avec merklePath non vide ERR-56-03 Rejet cohérence arbre unitaire
TC-NEG-14 Flood volontaire: rafale d’appels sur eventId déjà CORRUPTED ERR-56-03 à chaque appel, 0 alerte additionnelle Vérification anti-flood CA-56-15

8. Observabilité requise pour les tests

  • État système : snapshots corrélés des résolutions eventId->eventHash, leaf/tree Merkle, finalité batch, état disponibilité.
  • Réponse service : payload MerkleProofResult ou code contractuel (ERR-56-01..05) avec horodatage UTC.
  • Journal d’audit : requestId, eventId, décision validation format, décision auto-vérification, transition d’état, code, timestamp UTC.
  • Événement sécurité : SECURITY_ALERT avec severity=CRITICAL, eventId, errorCode (ERR-56-03/ERR-56-04), requestId, émis uniquement lors de la transition initiale vers CORRUPTED.
  • Contrôle anti-flood : preuve corrélée que les appels ultérieurs sur état CORRUPTED n’ajoutent pas d’événement SECURITY_ALERT.
  • Export probatoire : bundle versionné (jeux de tests, réponses, logs corrélés, rapport off-chain SHA-256, rapport perf P95).

9. Règles non testables

Règle Raison Impact
Opposabilité CA-56-05 (P95 10 ms) Environnement benchmark officiel peut rester non figé. Majeur
Couverture universelle eventId -> eventHash tous types d’événements Source canonique exacte non explicitée pour tous types. Majeur
Preuve absolue INV-56-08 “aucun secret en clair persisté” Vérifiable partiellement sur PD-56; preuve globale nécessite périmètre système complet. Majeur

10. Verdict QA

  • Testable intégralement sur cœur contractuel (formats, statuts, transitions, codes erreurs, auto-vérification, anti-flood audit sécurité).
  • Testable partiellement sur les points dépendants d’un cadre externe (benchmark officiel, couverture inter-modules complète).

Verdict retenu : Testable partiellement (avec réserves externes non bloquantes pour le contrat PD-56 v3).