Aller au contenu

PD-294 — Scénarios de tests contractuels

1. Références

  • Spécification : PD-294-specification.md
  • Epic : ProbatioVault-backend/docs/epics/probatoire/PD-294-merkle-rfc9162

2. Matrice de couverture

ID Invariant ID Critère ID Test Couverture Commentaire
INV-294-01-format-v2 CA-294-01 TC-NOM-01 Oui Sortie strictement limitée aux 7 champs v2.
INV-294-01-format-v2 CA-294-06 TC-ERR-04 Oui Validation stricte de inclusion_path.
INV-294-01-format-v2 CA-294-07 TC-NOM-04 Oui Bornes min/max numériques acceptées.
INV-294-01-format-v2 CA-294-08 TC-NOM-05 Oui Longueur inclusion_path 0 et 31 acceptée.
INV-294-02-hash-algorithm CA-294-02 TC-NOM-02 Oui Forçage hash_algorithm='sha3-256' en normalisation v1->v2.
INV-294-02-hash-algorithm CA-294-06 TC-ERR-07 Oui Toute autre valeur est rejetée.
INV-294-03-dual-read-single-write CA-294-03 TC-NOM-02 Oui Lecture v1/v2, émission v2 uniquement.
INV-294-03-dual-read-single-write CA-294-01 TC-NR-02 Oui Non-régression du contrat de sortie v2.
INV-294-04-no-retrowrite CA-294-11 TC-NR-01 Oui Aucune réécriture des preuves v1 persistées.
INV-294-04-no-retrowrite CA-294-03 TC-NOM-02 Oui Normalisation en mémoire, sans mutation persistée.
INV-294-05-discriminant CA-294-04 TC-NOM-03 Oui absent=>v1, 2=>v2.
INV-294-05-discriminant CA-294-04 TC-ERR-01 Oui Toute autre valeur rejetée (ERR-294-01).
INV-294-05-discriminant CA-294-07 TC-ERR-02 Oui leaf_index et relation avec tree_size contrôlés.
INV-294-05-discriminant CA-294-06 TC-ERR-03 Oui tree_size>=1 strict.
INV-294-06-rfc-verify-applicable CA-294-09 TC-NOM-06 Oui Vecteur positif RFC adapté SHA3-256 valide.
INV-294-06-rfc-verify-applicable CA-294-10 TC-ERR-09 Oui Preuve altérée invalide (ERR-294-09).
INV-294-06-rfc-verify-applicable CA-294-12 TC-NOM-10 Oui Vérification empirique H-294-02 (SHA3-256 conforme, SHA-256 non conforme).
INV-294-07-no-treeid-exposed CA-294-05 TC-ERR-08 Oui Détection fuite treeId/hashAlgorithmVersion.
INV-294-08-format-state-transitions CA-294-03 TC-NOM-07 Oui Transitions autorisées et idempotence vérifiées.
INV-294-08-format-state-transitions CA-294-13 TC-ERR-11 Oui Transitions interdites refusées avec ERR-294-11 HTTP 409.
INV-294-09-format-single-source CA-294-06 TC-NOM-08 Oui (documentaire) Contrôle documentaire “single source” §5.1.
INV-294-10-v1-path-order CA-294-14 TC-NOM-09 Oui merklePath v1 est conservé bottom-to-top sans inversion.
INV-294-10-v1-path-order CA-294-14 TC-NEG-05 Oui merklePath inversé (top-to-bottom) échoue (ERR-294-09).
INV-294-01-format-v2 CA-294-06 TC-ERR-05 Oui merkle_root invalide rejeté.
INV-294-01-format-v2 CA-294-06 TC-ERR-06 Oui event_hash invalide rejeté.
INV-294-01-format-v2 CA-294-08 TC-ERR-04 Oui inclusion_path.length=32 rejetée.

3. Scénarios de test – Flux nominaux

TEST-ID: TC-NOM-01
Référence spec: INV-294-01, INV-294-07, CA-294-01, CA-294-05

GIVEN
  - Fixture v2 valide versionnée (horloge figée UTC, données immuables)
  - `merkle_proof` contient uniquement les 7 champs v2
WHEN
  - Lecture API de la preuve
THEN
  - HTTP 200
  - Le payload retourné contient exactement: `proof_version`, `leaf_index`, `tree_size`, `inclusion_path`, `merkle_root`, `hash_algorithm`, `event_hash`
AND
  - Aucun champ `treeId` ni `hashAlgorithmVersion` n'est exposé
  - Aucune écriture DB n'est observée pendant la lecture
TEST-ID: TC-NOM-02
Référence spec: INV-294-02, INV-294-03, INV-294-04, CA-294-02, CA-294-03, CA-294-11

GIVEN
  - Une preuve legacy v1 persistée (sans `proof_version`)
  - Snapshot DB avant lecture (checksum ligne + `updated_at`)
WHEN
  - Lecture API de cette preuve
THEN
  - HTTP 200
  - Réponse en v2 avec `proof_version=2`, renommages conformes §5.5, `hash_algorithm='sha3-256'`
AND
  - Snapshot DB après lecture identique (pas d'UPDATE/INSERT/DELETE sur la preuve v1)
TEST-ID: TC-NOM-03
Référence spec: INV-294-05, CA-294-04

GIVEN
  - Fixture A: preuve sans `proof_version`
  - Fixture B: preuve avec `proof_version=2`
WHEN
  - Lecture API des deux fixtures
THEN
  - A est traitée legacy puis restituée en v2
  - B est reconnue v2 et restituée inchangée
AND
  - Le comportement est strictement déterministe et répétable
TEST-ID: TC-NOM-04
Référence spec: §5.2, CA-294-07

GIVEN
  - Fixture LIM-MIN: `tree_size=1`, `leaf_index=0`
  - Fixture LIM-MAX: `tree_size=2147483647`, `leaf_index=2147483646`
WHEN
  - Validation/lecture API des deux preuves
THEN
  - Les deux cas sont acceptés
  - Aucun overflow, cast implicite, ni coercition de type
AND
  - Les valeurs renvoyées restent inchangées
TEST-ID: TC-NOM-05
Référence spec: §5.2, CA-294-08

GIVEN
  - Fixture PATH-0 avec `inclusion_path.length=0`
  - Fixture PATH-31 avec `inclusion_path.length=31`, tous éléments `^[a-f0-9]{64}$`
WHEN
  - Validation/lecture API
THEN
  - Les deux preuves sont acceptées
  - L'ordre des éléments de `inclusion_path` est conservé
AND
  - Les longueurs retournées sont exactement 0 et 31
TEST-ID: TC-NOM-06
Référence spec: INV-294-06, §5.8, CA-294-09

GIVEN
  - Vecteur de test figé `VEC-RFC9162-SHA3-256-01` (event_hash, leaf_index, tree_size, inclusion_path, merkle_root)
WHEN
  - Exécution de la vérification RFC 9162 §2.1.3.2 adaptée SHA3-256
THEN
  - Résultat `valid=true`
  - `r` final est égal à `merkle_root`
AND
  - Aucun code d'erreur n'est produit
TEST-ID: TC-NOM-07
Référence spec: INV-294-08, §5.4, CA-294-03

GIVEN
  - Une preuve v1 valide et une preuve v2 valide
  - Journalisation des transitions de classification activée
WHEN
  - Relecture séquentielle: v1, v1, v2, v2
THEN
  - Transitions observées uniquement parmi les autorisées:
    `LEGACY_V1_DETECTED -> CANONICAL_V2_READY`,
    `LEGACY_V1_DETECTED -> LEGACY_V1_DETECTED`,
    `CANONICAL_V2_READY -> CANONICAL_V2_READY`
AND
  - Aucune transition interdite n'est observée
TEST-ID: TC-NOM-08
Référence spec: INV-294-09

GIVEN
  - Corpus documentaire contractuel PD-294 gelé (même révision)
WHEN
  - Exécution d'un contrôle documentaire de cohérence
THEN
  - Les définitions de format sont présentes uniquement en §5.1
  - Les autres sections référencent §5.1 sans redéfinition contradictoire
AND
  - Rapport de contrôle archivé comme preuve
TEST-ID: TC-NOM-09
Référence spec: INV-294-10-v1-path-order, §5.1, §5.5, CA-294-14

GIVEN
  - Une preuve legacy v1 valide avec `merklePath` ordonné bottom-to-top
  - Vecteur témoin pour lequel la racine attendue est connue
WHEN
  - Normalisation v1 -> v2 puis vérification cryptographique
THEN
  - `inclusion_path` reprend `merklePath` sans inversion
  - Résultat de vérification `valid=true`
AND
  - Aucun remaniement d'ordre n'est observé dans le payload normalisé
TEST-ID: TC-NOM-10
Référence spec: H-294-02, CA-294-12

GIVEN
  - Échantillon DB réel versionné (jeu de preuves représentatif)
  - Outil de recalcul paramétrable (`sha3-256` et `sha-256`)
WHEN
  - Recalcul de la racine depuis `event_hash` + `inclusion_path` pour chaque preuve, en double mode
THEN
  - En mode `sha3-256`, la racine recalculée égale `merkle_root` sur l’échantillon
  - En mode `sha-256`, la racine recalculée ne reproduit pas `merkle_root`
AND
  - Rapport comparatif archivé (preuve par preuve, hash algo, résultat)

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

TEST-ID: TC-ERR-01
Référence spec: ERR-294-01, INV-294-05, CA-294-04

GIVEN
  - Preuve avec `proof_version=3`
WHEN
  - Lecture API
THEN
  - HTTP 400 avec `ERR-294-01`
  - Rejet déterministe
AND
  - Aucune mutation persistée
TEST-ID: TC-ERR-02
Référence spec: ERR-294-02, §5.1, §5.2, CA-294-06, CA-294-07

GIVEN
  - Cas A: `leaf_index=-1`
  - Cas B: `leaf_index=tree_size`
WHEN
  - Validation/lecture API
THEN
  - HTTP 422 avec `ERR-294-02` pour les deux cas
AND
  - Aucune écriture DB
TEST-ID: TC-ERR-03
Référence spec: ERR-294-03, §5.1, §5.2, CA-294-06, CA-294-07

GIVEN
  - Preuve avec `tree_size=0`
WHEN
  - Validation/lecture API
THEN
  - HTTP 422 avec `ERR-294-03`
AND
  - Aucune exécution de vérification crypto
TEST-ID: TC-ERR-04
Référence spec: ERR-294-04, §5.1, §5.2, CA-294-06, CA-294-08

GIVEN
  - Jeu de cas invalide déterministe:
    1) `inclusion_path` non tableau
    2) `inclusion_path.length=32`
    3) élément non `^[a-f0-9]{64}$`
WHEN
  - Validation/lecture API
THEN
  - HTTP 400 avec `ERR-294-04` pour chaque cas
AND
  - Aucun calcul RFC n'est lancé
TEST-ID: TC-ERR-05
Référence spec: ERR-294-05, §5.1, CA-294-06

GIVEN
  - `merkle_root` invalide (longueur != 64 ou caractère hors `[a-f0-9]`)
WHEN
  - Validation/lecture API
THEN
  - HTTP 400 avec `ERR-294-05`
AND
  - Pas d'effet secondaire persisté
TEST-ID: TC-ERR-06
Référence spec: ERR-294-06, §5.1, CA-294-06

GIVEN
  - `event_hash` invalide (longueur != 64 ou caractère hors `[a-f0-9]`)
WHEN
  - Validation/lecture API
THEN
  - HTTP 400 avec `ERR-294-06`
AND
  - Pas d'effet secondaire persisté
TEST-ID: TC-ERR-07
Référence spec: ERR-294-07, INV-294-02, CA-294-02, CA-294-06

GIVEN
  - Preuve avec `hash_algorithm='SHA-256'` (ou toute autre valeur)
WHEN
  - Validation/lecture API
THEN
  - HTTP 422 avec `ERR-294-07`
AND
  - La preuve n'est pas émise
TEST-ID: TC-ERR-08
Référence spec: ERR-294-08, INV-294-07, CA-294-05

GIVEN
  - Réponse API contenant `treeId` ou `hashAlgorithmVersion` dans `merkle_proof`
WHEN
  - Exécution du validateur de contrat
THEN
  - Non-conformité détectée avec `ERR-294-08` (HTTP 500 contractuel)
AND
  - Le test échoue tant que la fuite n'est pas corrigée
TEST-ID: TC-ERR-09
Référence spec: ERR-294-09, INV-294-06, CA-294-10

GIVEN
  - Vecteur valide puis version altérée (1 bit modifié dans `inclusion_path` ou longueur menant à `sn != 0`)
WHEN
  - Exécution de la vérification RFC adaptée SHA3-256
THEN
  - HTTP 422 avec `ERR-294-09` / `valid=false`
AND
  - Aucune mutation persistée
TEST-ID: TC-ERR-10
Référence spec: ERR-294-10

GIVEN
  - Identifiant de preuve inexistant
WHEN
  - Lecture API
THEN
  - HTTP 404 avec `ERR-294-10`
AND
  - Aucune mutation persistée
TEST-ID: TC-ERR-11
Référence spec: ERR-294-11, INV-294-08, §5.4, CA-294-13

GIVEN
  - Cas A: preuve classée `CANONICAL_V2_READY`
  - Cas B: preuve classée `REJECTED_INVALID`
WHEN
  - Tentative de transition interdite (`CANONICAL_V2_READY -> LEGACY_V1_DETECTED` ou `REJECTED_INVALID -> *`)
THEN
  - HTTP 409 avec `ERR-294-11`
  - Transition refusée explicitement et aucun downgrade de format exposé
AND
  - État courant inchangé et journal de refus présent

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

Invariant Test(s) dédiés Observable Commentaire
INV-294-01-format-v2 TC-NOM-01, TC-NR-02 Clés JSON exactes + schéma v2 PASS Contrat de sortie univoque.
INV-294-02-hash-algorithm TC-NOM-02, TC-ERR-07 hash_algorithm toujours sha3-256 Rejet strict des autres valeurs.
INV-294-03-dual-read-single-write TC-NOM-02, TC-NOM-03 v1 et v2 lisibles, sortie exclusivement v2 Dual-read/single-write vérifié.
INV-294-04-no-retrowrite TC-NOM-02, TC-NR-01 Checksum/updated_at legacy inchangés Aucune réécriture rétroactive.
INV-294-05-discriminant TC-NOM-03, TC-ERR-01 Routage déterministe selon proof_version Valeurs non supportées rejetées.
INV-294-06-rfc-verify-applicable TC-NOM-06, TC-ERR-09, TC-NOM-10 valid=true sur vecteur positif, ERR-294-09 sur altération, comparatif SHA3/SHA-256 conforme Applicabilité RFC adaptée SHA3-256 validée.
INV-294-07-no-treeid-exposed TC-NOM-01, TC-ERR-08 Absence de champs internes en sortie Protection du contrat exposé.
INV-294-08-format-state-transitions TC-NOM-07, TC-ERR-11 Traces de transitions autorisées/interdites + refus ERR-294-11 HTTP 409 Machine d’états respectée.
INV-294-09-format-single-source TC-NOM-08 Rapport documentaire de cohérence Test de gouvernance documentaire.
INV-294-10-v1-path-order TC-NOM-09, TC-NEG-05 Ordre bottom-to-top conservé sans inversion ; ordre inversé rejeté Contrat d’ordonnancement v1 explicite.

6. Tests de non-régression

Test ID Objet Observable Commentaire
TC-NR-01 Non-réécriture des preuves v1 existantes Diff DB avant/après lecture (0 update sur lignes v1) Couvre CA-294-11.
TC-NR-02 Stabilité du contrat de sortie v2 Snapshot JSON de réponse strictement identique (7 champs) Évite dérive de schéma.
TC-NR-03 Non-régression hors périmètre ProofEnvelope tsa_token, hsm_signature, blockchain_anchor, event_metadata inchangés Respect du hors périmètre.
TC-NR-04 Absence de migration DDL induite Schéma DB identique avant/après PD-294 Conforme §5.9.

7. Tests négatifs et adversariaux

Test ID Entrée invalide / abus Résultat attendu Observable
TC-NEG-01 Hash en uppercase/mixte ([A-F]) Rejet format (ERR-294-04/05/06 selon champ) HTTP + code erreur exact.
TC-NEG-02 inclusion_path contenant null, objet, nombre Rejet ERR-294-04 HTTP 400, aucune mutation DB.
TC-NEG-03 Rejeu massif concurrent de lectures v1 (N appels) Réponses v2 identiques, 0 écriture persistée Diff DB + hash des payloads.
TC-NEG-04 Tentative de downgrade forcé v2->v1 Transition interdite refusée (ERR-294-11) Trace de refus + absence de payload legacy.
TC-NEG-05 Preuve v1 correcte mais merklePath inversé (top-to-bottom) Échec vérification ERR-294-09 après normalisation Résultat valid=false déterministe + HTTP 422.
TC-NEG-06 Altération bit-à-bit de merkle_root après normalisation Échec vérification ERR-294-09 Résultat valid=false déterministe.

8. Observabilité requise pour les tests

  • État système : snapshot DB avant/après (checksum, updated_at, compte d’updates), traces de classification d’état.
  • Réponse API : code HTTP, error_code, payload JSON complet, ordre stable des champs vérifiés côté validateur.
  • Journal d’audit : lecture, normalisation, rejet de validation, transition de classification, tentative interdite.
  • Événement signé / horodaté : résultat de vérification RFC (valid/invalid) horodaté UTC corrélable à l’ID de preuve.
  • Export probatoire : fixtures versionnées, résultats bruts de tests, diffs DB, extraits journaux et rapport comparatif archivés.

9. Règles non testables

Règle Raison Impact
Représentativité exhaustive de l’échantillon H-294-02 Impossible de couvrir l’intégralité des arbres historiques en une seule campagne contractuelle Majeur
Namespace d’erreurs final Q-294-02 ERR-294-* doit être confirmé avec conventions backend effectives Majeur

10. Verdict QA

  • ✅ Testable (avec réserves non bloquantes listées)

Note d’exécution : environnement en lecture seule, contenu généré mais non écrit sur disque dans ce run.