PD-294 - Alignement contractuel du format merkle_proof sur RFC 9162 (inclusion proof)¶
1. Objectif¶
Contractualiser un format canonique merkle_proof aligné sur la structure d’inclusion proof RFC 9162 (section 2.1.3), avec les exigences suivantes :
- lecture compatible des preuves legacy v1 (
proof_versionabsent ou1), - émission exclusive du format v2 (
proof_version=2), - conservation de l’algorithme de hachage ProbatioVault (
sha3-256), - absence de réécriture rétroactive des preuves déjà persistées.
2. Périmètre / Hors périmètre¶
Inclus¶
- Définition normative de
merkle_proofv2 dansProofEnvelope. - Règles de mapping v1 -> v2 (normalisation à la volée en lecture).
- Discriminant de version (
proof_version) et règles d’interprétation. - Règles de validation des formats, tailles et bornes numériques.
- Applicabilité de l’algorithme RFC 9162 §2.1.3.2 adapté à
SHA3-256. - Correction contractuelle de
hashAlgorithm: 'SHA-256'vershash_algorithm: 'sha3-256'. - Contractualisation de l’ordre
merklePathv1 (bottom-to-top).
Exclu¶
- Implémentation des fonctions applicatives (
getMerkleProof(),verifyMerkleProof()) : hors périmètre. - Consistency proofs RFC 9162 §2.1.4 : hors périmètre.
- Migration rétroactive des preuves v1 en base : hors périmètre.
- Changement d’algorithme cryptographique vers SHA-256 : hors périmètre.
- Modification structurelle des autres sous-objets
ProofEnvelope(tsa_token,hsm_signature,blockchain_anchor,event_metadata) : hors périmètre. - Chiffrement d’artefacts cryptographiques temporaires : hors périmètre PD-294.
3. Définitions¶
| Terme | Définition |
|---|---|
merkle_proof v1 | Format legacy historique (merklePath, merkleRoot, leafIndex, treeSize, eventHash, etc.). |
merkle_proof v2 | Format cible RFC 9162-inspired (proof_version, leaf_index, tree_size, inclusion_path, merkle_root, hash_algorithm, event_hash). |
| Inclusion path | Liste ordonnée des siblings de bas en haut (index 0 = niveau feuille, dernier = niveau proche racine). |
proof_version | Discriminant de format en entrée : absent ou 1 = v1 legacy, 2 = v2 explicite. |
| Dual-read / single-write | Lecture v1 et v2 autorisée ; écriture/émission uniquement en v2 (proof_version=2). |
| RFC 9162 §2.1.3.2 | Algorithme de vérification d’inclusion proof, ici appliqué avec SHA3-256. |
| État terminal | État sans transition sortante autorisée. |
4. Invariants (non négociables)¶
| ID | Règle | Justification |
|---|---|---|
| INV-294-01-format-v2 | Toute preuve émise DOIT contenir exactement proof_version, leaf_index, tree_size, inclusion_path, merkle_root, hash_algorithm, event_hash. | Contrat v2 univoque. |
| INV-294-02-hash-algorithm | hash_algorithm DOIT valoir strictement sha3-256. | Alignement écosystème ProbatioVault. |
| INV-294-03-dual-read-single-write | Le système DOIT lire v1 et v2, et DOIT émettre uniquement v2. | Compatibilité descendante sans ambiguïté de sortie. |
| INV-294-04-no-retrowrite | Les preuves v1 déjà persistées NE DOIVENT PAS être réécrites. | Préservation de la valeur probatoire historique. |
| INV-294-05-discriminant | En lecture : proof_version absent ou 1 => v1 ; proof_version=2 => v2 ; toute autre valeur => rejet. | Détection de format déterministe, compat legacy explicite. |
| INV-294-06-rfc-verify-applicable | Toute preuve v2 émise DOIT être vérifiable par RFC 9162 §2.1.3.2 adapté SHA3-256. | Interopérabilité algorithmique. |
| INV-294-07-no-treeid-exposed | treeId et hashAlgorithmVersion NE DOIVENT PAS apparaître dans merkle_proof v2 exposé. | Éviter fuite de détails internes non normatifs. |
| INV-294-08-format-state-transitions | La machine d’états de classification format (§5.4) DOIT être respectée ; toute transition non listée est interdite et DOIT lever ERR-294-11. | Prévention des ambiguïtés de parsing. |
| INV-294-09-format-single-source | Tous les formats de données DOIVENT être définis uniquement en §5.1 et référencés ailleurs. | Anti-divergence documentaire. |
| INV-294-10-v1-path-order | En entrée v1, merklePath DOIT être interprété bottom-to-top et mappé sans inversion vers inclusion_path. | Contrat d’ordonnancement explicite v1. |
5. Flux nominaux¶
5.1 Modèle de données (source de vérité unique)¶
| Donnée canonique | Format / encodage | Taille / longueur | Jeu de caractères | Sensibilité casse | Validation | Comportement si invalide |
|---|---|---|---|---|---|---|
proof_version | entier JSON | entrée: absent, 1, 2; sortie: 2 | chiffres | n/a | entrée: absent/1 => v1, 2 => v2 ; sortie: =2 | autre valeur: rejet 400 ERR-294-01 |
leaf_index | entier signé 32-bit | 0..(tree_size-1) | chiffres | n/a | leaf_index >= 0 et < tree_size | rejet 422 ERR-294-02 |
tree_size | entier signé 32-bit | 1..2147483647 | chiffres | n/a | tree_size >= 1 et <= 2147483647 | rejet 422 ERR-294-03 |
inclusion_path | tableau JSON de hash hex | 0..31 éléments | [a-f0-9] | case-sensitive | chaque élément ^[a-f0-9]{64}$; length=0 si et seulement si tree_size=1 | rejet 400 ERR-294-04 |
merkle_root | hex lowercase | 64 chars (32 bytes) | [a-f0-9] | case-sensitive | ^[a-f0-9]{64}$ | rejet 400 ERR-294-05 |
event_hash | hex lowercase | 64 chars (32 bytes) | [a-f0-9] | case-sensitive | ^[a-f0-9]{64}$ | rejet 400 ERR-294-06 |
hash_algorithm | enum string | 8 chars | ASCII lowercase | case-sensitive | valeur stricte sha3-256 | rejet 422 ERR-294-07 |
treeId (legacy interne) | UUID v4 texte | 36 chars | [0-9a-fA-F-] | case-insensitive (hex UUID) | UUID v4 | non exposé en v2 ; si exposé: rejet 500 ERR-294-08 |
Notes normatives :
- Les champs legacy v1 (
merklePath,merkleRoot,leafIndex,treeSize,eventHash,hashAlgorithm,hashAlgorithmVersion) ne sont acceptés qu’en entrée de normalisation. - L’ordre attendu de
merklePathv1 est bottom-to-top et DOIT être conservé tel quel dansinclusion_path(aucune inversion). - La sortie contractuelle est toujours en nomenclature v2 (
snake_case+proof_version=2).
5.2 Bornes numériques obligatoires¶
| Paramètre | Défaut | Min | Max | Unité | Contexte de référence | Percentile | Comportement hors bornes |
|---|---|---|---|---|---|---|---|
proof_version (sortie) | 2 | 2 | 2 | version | API backend | n/a | rejet émission (erreur interne) |
proof_version (entrée) | n/a | absent/1/2 | absent/1/2 | version | parsing contrat | n/a | rejet 400 ERR-294-01 |
tree_size | n/a (valeur source obligatoire) | 1 | 2147483647 | feuilles | schéma persistance Merkle (INTEGER) | n/a | rejet 422 ERR-294-03 |
leaf_index | n/a (valeur source obligatoire) | 0 | tree_size-1 | index | preuve d’inclusion | n/a | rejet 422 ERR-294-02 |
inclusion_path.length | n/a (dérivé de l’arbre) | 0 | 31 | éléments | arbre binaire, tree_size max int32 | n/a | rejet 400 ERR-294-04 |
longueur hash (event_hash, merkle_root, élément inclusion_path) | 64 | 64 | 64 | caractères hex | SHA3-256 | n/a | rejet 400 |
Justification contractuelle tree_size int32 vs RFC 9162 uint64 :
- RFC 9162 autorise
tree_sizesur 64 bits non signés. - Le périmètre PD-294 conserve la contrainte de persistance existante (
INTEGERPostgreSQL signé 32 bits). - La borne contractuelle est donc
1..2^31-1(2147483647) feuilles. - Toute valeur au-delà est hors contrat PD-294 et rejetée par
ERR-294-03. - Un passage à
BIGINTnécessite une évolution dédiée (hors périmètre PD-294).
5.3 SLA temporels¶
Aucune transition temporelle identifiée.
5.4 Machine d’états de classification format (avec transitions retour)¶
Règle de classification initiale :
| Condition d’entrée | État initial |
|---|---|
proof_version absent ou 1 | LEGACY_V1_DETECTED |
proof_version=2 | CANONICAL_V2_READY |
| autre valeur | REJECTED_INVALID (ERR-294-01) |
Transitions sortantes :
| État source | État cible | Statut | Code si interdit |
|---|---|---|---|
LEGACY_V1_DETECTED | CANONICAL_V2_READY | AUTORISÉE | n/a |
LEGACY_V1_DETECTED | REJECTED_INVALID | AUTORISÉE | n/a |
LEGACY_V1_DETECTED | LEGACY_V1_DETECTED | AUTORISÉE | n/a |
CANONICAL_V2_READY | CANONICAL_V2_READY | AUTORISÉE | n/a |
CANONICAL_V2_READY | REJECTED_INVALID | AUTORISÉE | n/a |
CANONICAL_V2_READY | LEGACY_V1_DETECTED | INTERDITE | ERR-294-11 |
REJECTED_INVALID | * | INTERDITE (état terminal) | ERR-294-11 |
Comportement au retour/downgrade :
- Données existantes : conservées, aucune suppression.
- Quotas/limites : sans objet.
- Re-verrouillage fonctionnalités : sans objet.
- Toute tentative de transition interdite DOIT retourner
409 ERR-294-11.
5.5 Mapping v1 -> v2 (normalisation contractuelle)¶
| Source v1 | Cible v2 | Règle |
|---|---|---|
merklePath | inclusion_path | renommage sans inversion ; ordre attendu bottom-to-top conservé |
merkleRoot | merkle_root | renommage |
leafIndex | leaf_index | renommage |
treeSize | tree_size | renommage |
eventHash | event_hash | renommage |
hashAlgorithm | hash_algorithm | forçage strict vers sha3-256 |
proof_version absent ou 1 | proof_version | sortie forcée à 2 |
treeId | — | supprimé du payload exposé |
hashAlgorithmVersion | — | supprimé du payload exposé |
5.6 Flux nominal A — Lecture d’une preuve v2 native¶
- Le système lit la preuve source.
- Le système détecte
proof_version=2. - Le système valide les formats §5.1.
- Le système retourne
merkle_proofinchangé (v2 canonique).
5.7 Flux nominal B — Lecture d’une preuve legacy v1¶
- Le système lit la preuve source avec
proof_versionabsent ouproof_version=1. - Le système classe la preuve en
LEGACY_V1_DETECTED. - Le système applique le mapping §5.5.
- Le système valide les contraintes v2 §5.1.
- Le système retourne
merkle_proofv2 (proof_version=2) sans écrire en base.
5.8 Flux nominal C — Vérification RFC 9162 §2.1.3.2 adaptée SHA3-256¶
Primitives :
HASH(x) = SHA3-256(x)NODE_HASH(left, right) = HASH(0x01 || left || right)LSB(x) = x & 1hexToBytes()pour décoder les hex 64 en 32 bytes
Algorithme normatif :
Entrées: leaf_index, tree_size, event_hash, inclusion_path[], merkle_root
1. if leaf_index >= tree_size:
FAIL(ERR-294-02)
2. fn = leaf_index
sn = tree_size - 1
3. r = hexToBytes(event_hash)
Convention PD-294: event_hash est le leaf-hash stocké.
4. for each p_hex in inclusion_path:
p = hexToBytes(p_hex)
a. if sn == 0:
FAIL(ERR-294-09)
b. if (LSB(fn) == 1) OR (fn == sn):
i. r = NODE_HASH(p, r)
ii. while (LSB(fn) == 0):
fn = fn >> 1
sn = sn >> 1
if fn == 0:
break
c. else:
i. r = NODE_HASH(r, p)
d. fn = fn >> 1
sn = sn >> 1
5. if (sn != 0) OR (r != hexToBytes(merkle_root)):
FAIL(ERR-294-09)
6. SUCCESS
Règles additionnelles :
inclusion_path.length = 0est valide uniquement sitree_size = 1.- Toute divergence (
sn==0dans boucle,sn!=0final, racine non égale) retourneERR-294-09.
5.9 Stratégie de migration DDL¶
Aucune migration DDL requise dans PD-294 : la borne tree_size reste contractuellement alignée sur le type INTEGER existant.
5.10 Atomicité multi-composant¶
| Scope | Synchrone/Async | Garantie |
|---|---|---|
| Lecture DB de la preuve | Synchrone | Cohérence de lecture transactionnelle |
| Normalisation v1 -> v2 | Synchrone (mémoire) | Déterministe, sans effet de bord persistant |
| Vérification cryptographique | Synchrone (calcul) | Résultat déterministe sur même entrée |
| Crash pré-réponse | n/a | Aucune mutation persistée |
| Crash post-réponse | n/a | Aucun rattrapage requis (flux sans écriture) |
5.11 Mécanismes de protection distribuée¶
Aucun mécanisme de protection distribuée applicable (module synchrone mono-instance).
5.12 Contraintes inter-modules¶
Aucune contrainte inter-module applicable.
5bis. Diagrammes (si applicable)¶
Diagramme d’état¶
stateDiagram-v2
[*] --> LEGACY_V1_DETECTED: proof_version absent|1
[*] --> CANONICAL_V2_READY: proof_version=2
[*] --> REJECTED_INVALID: autre proof_version (ERR-294-01)
LEGACY_V1_DETECTED --> CANONICAL_V2_READY: normalisation v1->v2 (lecture)
LEGACY_V1_DETECTED --> REJECTED_INVALID: format legacy invalide
LEGACY_V1_DETECTED --> LEGACY_V1_DETECTED: relecture idempotente
CANONICAL_V2_READY --> CANONICAL_V2_READY: relecture idempotente
CANONICAL_V2_READY --> REJECTED_INVALID: contrainte invalide
CANONICAL_V2_READY --> LEGACY_V1_DETECTED: INTERDITE (ERR-294-11)
REJECTED_INVALID --> LEGACY_V1_DETECTED: INTERDITE (ERR-294-11)
REJECTED_INVALID --> CANONICAL_V2_READY: INTERDITE (ERR-294-11) Diagramme de séquence¶
sequenceDiagram
participant V as Verifier
participant API as Proof API (NestJS)
participant DB as vault_merkle (PostgreSQL)
participant N as Normalizer
participant C as SHA3-256 Engine
V->>API: GET proof(event_id)
API->>DB: SELECT event_hash, merkle_root, leaf_index, tree_size, inclusion_proof, proof_version
DB-->>API: record (v1 proof_version absent|1 OU v2 proof_version=2)
API->>N: classify+normalize(record)
alt record v1
N-->>API: v2{proof_version=2, inclusion_path=merklePath, hash_algorithm='sha3-256'}
else record v2
N-->>API: v2 inchangé
end
API-->>V: ProofEnvelope.merkle_proof(v2)
V->>C: fn=leaf_index, sn=tree_size-1, r=event_hash
loop pour chaque p in inclusion_path
V->>C: if sn==0 => invalid
alt (LSB(fn)=1) ou (fn==sn)
V->>C: r=SHA3-256(0x01 || p || r)
else
V->>C: r=SHA3-256(0x01 || r || p)
end
loop while (LSB(fn)=0) et (fn!=0)
V->>C: fn >>= 1 ; sn >>= 1
end
V->>C: fn >>= 1 ; sn >>= 1
end
V->>C: check sn==0 and r==merkle_root
C-->>V: valid / invalid(ERR-294-09) 6. Cas d’erreur¶
| Code | Cas | Réponse contractuelle |
|---|---|---|
ERR-294-01 | proof_version présent et non supporté (not in {1,2}) | HTTP 400 |
ERR-294-02 | leaf_index hors borne ou leaf_index >= tree_size | HTTP 422 |
ERR-294-03 | tree_size < 1 ou tree_size > 2147483647 | HTTP 422 |
ERR-294-04 | inclusion_path invalide (type, longueur, élément non hex64, incohérence length=0/tree_size) | HTTP 400 |
ERR-294-05 | merkle_root invalide | HTTP 400 |
ERR-294-06 | event_hash invalide | HTTP 400 |
ERR-294-07 | hash_algorithm != 'sha3-256' | HTTP 422 |
ERR-294-08 | fuite de champ interne interdit (treeId, hashAlgorithmVersion) en payload v2 | HTTP 500 |
ERR-294-09 | échec vérification RFC 9162 adaptée (sn==0 en boucle, sn!=0 final, ou r != merkle_root) | HTTP 422 |
ERR-294-10 | preuve absente pour l’identifiant demandé | HTTP 404 |
ERR-294-11 | transition de format interdite dans la machine d’états (§5.4) | HTTP 409 |
7. Critères d’acceptation (testables)¶
| ID | Critère | Observable |
|---|---|---|
| CA-294-01 | Toute preuve émise contient exactement les 7 champs v2. | Contrôle JSON schema v2 PASS. |
| CA-294-02 | hash_algorithm vaut toujours sha3-256. | Aucun payload v2 avec autre valeur. |
| CA-294-03 | Une preuve v1 (proof_version absent ou 1) lue est restituée en v2 sans réécriture DB. | Réponse v2 + absence de mutation persistance. |
| CA-294-04 | proof_version absent/1 => v1, 2 => v2, autre valeur rejetée. | Tests de parsing 4 cas. |
| CA-294-05 | Les champs treeId et hashAlgorithmVersion n’apparaissent jamais en v2 exposé. | Contrôle payload systématique PASS. |
| CA-294-06 | Toutes les contraintes de format §5.1 sont appliquées. | Tests négatifs par champ -> codes ERR-294-* attendus. |
| CA-294-07 | leaf_index et tree_size respectent les bornes §5.2 (incluant max int32). | Cas limites min/max PASS. |
| CA-294-08 | inclusion_path.length respecte [0,31] et length=0 <=> tree_size=1. | Cas 0, 31, 32 + cohérence tree_size PASS. |
| CA-294-09 | L’algorithme RFC 9162 §2.1.3.2 adapté SHA3-256 (avec inner while-loop) valide un vecteur connu. | valid=true sur vecteur positif. |
| CA-294-10 | L’algorithme RFC 9162 adapté invalide une preuve altérée. | valid=false / ERR-294-09. |
| CA-294-11 | Aucune preuve v1 existante n’est réécrite par PD-294. | Diff base avant/après sans update legacy. |
| CA-294-12 | Vérification empirique H-294-02 : sur échantillon DB réel, SHA3-256 valide ; SHA-256 ne reproduit pas la racine attendue. | Rapport de test comparatif PASS. |
| CA-294-13 | Toute transition interdite de la machine d’états retourne ERR-294-11. | Tests de transitions interdites PASS. |
| CA-294-14 | merklePath v1 est interprété bottom-to-top sans inversion. | Cas ordre normal PASS, ordre inversé FAIL (ERR-294-09). |
8. Scénarios de test (Given / When / Then)¶
| ID | Given | When | Then |
|---|---|---|---|
| ST-294-01 | preuve avec proof_version=2 et champs v2 valides | lecture preuve | réponse identique v2, validation §5.1 OK |
| ST-294-02 | preuve legacy avec proof_version absent | lecture preuve | réponse normalisée v2 (proof_version=2) sans écriture DB |
| ST-294-03 | preuve legacy avec proof_version=1 | lecture preuve | classée v1 puis normalisée v2 sans écriture DB |
| ST-294-04 | preuve avec proof_version=3 | lecture preuve | rejet 400 ERR-294-01 |
| ST-294-05 | event_hash non conforme ^[a-f0-9]{64}$ | lecture preuve | rejet 400 ERR-294-06 |
| ST-294-06 | leaf_index=tree_size | vérification preuve | rejet 422 ERR-294-02 |
| ST-294-07 | tree_size=2147483648 | lecture/vérification | rejet 422 ERR-294-03 |
| ST-294-08 | inclusion_path de 32 éléments | lecture/vérification | rejet 400 ERR-294-04 |
| ST-294-09 | merkle_root invalide (non hex64) | lecture/vérification | rejet 400 ERR-294-05 |
| ST-294-10 | hash_algorithm='sha-256' | lecture/vérification | rejet 422 ERR-294-07 |
| ST-294-11 | preuve v2 cohérente (event_hash, inclusion_path, merkle_root) | algo RFC 9162 §2.1.3.2 adapté exécuté | valid=true |
| ST-294-12 | preuve v2 dont un élément inclusion_path est altéré | algo exécuté | rejet 422 ERR-294-09 |
| ST-294-13 | réponse contenant treeId en merkle_proof | validateur de contrat | non-conformité 500 ERR-294-08 |
| ST-294-14 | aucune preuve pour event_id demandé | lecture preuve | rejet 404 ERR-294-10 |
| ST-294-15 | tentative de transition CANONICAL_V2_READY -> LEGACY_V1_DETECTED | exécution machine d’états | rejet 409 ERR-294-11 |
| ST-294-16 | échantillon DB réel + recalcul double mode SHA3/SHA-256 | campagne de validation H-294-02 | SHA3-256 conforme, SHA-256 non conforme |
| ST-294-17 | preuve v1 correcte mais merklePath inversé (top-to-bottom) | normalisation + vérification | échec crypto 422 ERR-294-09 |
8.1 Matrice de couverture des erreurs¶
| Code erreur | Scénario(s) de couverture |
|---|---|
ERR-294-01 | ST-294-04 |
ERR-294-02 | ST-294-06 |
ERR-294-03 | ST-294-07 |
ERR-294-04 | ST-294-08 |
ERR-294-05 | ST-294-09 |
ERR-294-06 | ST-294-05 |
ERR-294-07 | ST-294-10 |
ERR-294-08 | ST-294-13 |
ERR-294-09 | ST-294-12, ST-294-17 |
ERR-294-10 | ST-294-14 |
ERR-294-11 | ST-294-15 |
9. Hypothèses explicites¶
| ID | Hypothèse | Validation testable | Impact si faux |
|---|---|---|---|
| H-294-01 | Le stockage source expose tree_size et leaf_index pour chaque preuve exploitable. | Vérifié par tests d’intégration lecture preuve | Vérification RFC impossible, rejet massif des preuves. |
| H-294-02 | Le calcul Merkle amont est réellement en SHA3-256 malgré labels legacy ambigus. | ST-294-16 + CA-294-12 | Incompatibilité racine/preuve si l’amont est SHA-256. |
| H-294-03 | Le domaine métier actuel n’excède pas 2^31-1 feuilles par arbre. | Vérification volumétrie prod + monitoring | Bornes §5.2 insuffisantes, évolution BIGINT à planifier. |
| H-294-04 | Le transport externe des erreurs supporte les codes ERR-294-*. | Tests contractuels API | Mapping erreur non aligné, observabilité affaiblie. |
| H-294-05 | Le besoin d’exposer explicitement l’origine legacy au client n’est pas requis. | Validation PO/API review | Si requis, contrat de sortie à amender. |
10. Points à clarifier¶
10.1 Contraintes techniques (stack réelle)¶
| Élément | Valeur contractuelle |
|---|---|
| Projet cible | ProbatioVault-backend |
| Langage | TypeScript |
| Framework backend | NestJS |
| ORM | TypeORM |
| Base de données | PostgreSQL |
| Schéma métier concerné | vault_merkle (références PD-237/PD-56) |
10.2 Questions ouvertes¶
| ID | Point à clarifier | Impact |
|---|---|---|
| Q-294-01 | Confirmation convention HTTP 409 pour ERR-294-11 (transition interdite). | Risque d’écart avec conventions backend si 422 attendu. |
| Q-294-02 | Plan d’évolution formel vers BIGINT si besoin futur tree_size > 2^31-1. | Risque de rejet fonctionnel sur très grands arbres. |
| Q-294-03 | Le placeholder d’injection {{LEARNINGS}} est non renseigné. | Risque de manquer des contraintes historiques spécifiques. |
| Q-294-04 | Référence épique textuelle métier non fournie dans le besoin (seul chemin technique disponible). | Métadonnées de traçabilité incomplètes. |
Références¶
- Epic :
ProbatioVault-backend/docs/epics/probatoire/PD-294-merkle-rfc9162 - JIRA :
PD-294 - Repos concernés :
ProbatioVault-backend - Documents associés :
- RFC 9162 (sections 2.1.3, 2.1.3.2, 4.12)
- PD-54 — Construction arbre Merkle
- PD-55 — Worker ancrage blockchain
- PD-56 — Generation Merkle proof
- PD-237 — Persistance Merkle
- PD-245 — Format preuve multi-chain
- PD-282 — ProofEnvelope HSM/eIDAS
Note d’exécution : sandbox en lecture seule, donc fichier non écrit sur disque dans ce run.
---SPEC-END---