Aller au contenu

PD-177 — Review de spécification (Gate 3 — Phase 1)

Reviewer : Claude (auditeur indépendant) Date : 2026-02-23 Documents analysés : PD-177-specification.md, PD-177-tests.md

Verdict préliminaire : 4 bloquants, 8 majeurs, 5 mineurs (17 écarts)


ECART-01 — Horodatage non formalisé

Type : Ambiguïté
Référence : INV-177-13 (horodatage d'emission)
Description : Le format d'horodatage n'est pas spécifié. La spec mentionne "horodatage d'emission" dans INV-177-13 sans définir le format (ISO 8601 UTC ms ? Unix timestamp ? timezone locale ?). Le learning PD-55 signale que le format ISO 8601 UTC ms doit être défini dès la spécification.
Impact : Ambiguïté contractuelle — un tiers auditeur ne peut reconstruire la chaîne de preuve si le format d'horodatage n'est pas interopérable.
Gravité : Majeur

ECART-02 — Seuil de confirmations réseau indéterminé

Type : Ambiguïté
Référence : INV-177-16, CA-177-05, TC-177-05, HYP-177-06
Description : La spec délègue la politique de confirmations réseau à HYP-177-06 ("déjà définie dans le cadre transactionnel existant"). Or le code existant de PD-55 contient au moins 3 valeurs contradictoires (12 confirmations hardcodées, 30 confirmations dans un autre endroit, configuration par réseau avec 5 confirmations). Le TC-177-05 teste "dans la fenêtre configurée" sans valeur contractuelle.
Impact : Le test TC-177-05 est non déterministe — la "fenêtre configurée" peut valoir 12 ou 30 ou 5 selon l'interprétation. Un ancrage pourrait être marqué "confirmé" avec un nombre insuffisant de confirmations.
Gravité : Bloquant

ECART-03 — Comportement tezos en entrée

Type : Ambiguïté
Référence : INV-177-04
Description : INV-177-04 définit l'enum `ethereum_l2 | tezos` pour le champ `blockchain` mais PD-177 ne produit que des preuves `ethereum_l2`. La spec ne précise pas ce qui se passe si une preuve avec `blockchain=tezos` est reçue en entrée par un service PD-177 — rejet explicite, passthrough, ou erreur ?
Impact : Comportement non défini en cas de donnée Tezos circulant dans les services PD-177.
Gravité : Mineur

ECART-04 — Registre append-only ambigu

Type : Ambiguïté
Référence : Définitions (section 3), INV-177-14, TC-177-06
Description : Le "registre append-only" est défini comme concept dans la section 3 et utilisé comme observable dans INV-177-14 et TC-177-06. Mais la spec ne précise pas : est-ce une table PostgreSQL ? Un fichier ? Un event log ? Le learning PD-39 signale que "Database-level WORM protection is required, API guards are insufficient" — la nature exacte du registre impacte la testabilité de l'immutabilité.
Impact : L'immutabilité testée dans TC-177-06 ("tentative de modification destructive refusée") dépend de l'implémentation sous-jacente. Si c'est une table PostgreSQL, un UPDATE SQL pourrait contourner les gardes applicatives.
Gravité : Majeur

ECART-05 — Champ adresse émettrice absent de l'entité

Type : Incohérence Spec↔Tests
Référence : INV-177-13 vs TC-177-06
Description : INV-177-13 exige "adresse emettrice" dans l'enregistrement append-only. TC-177-06 vérifie sa présence. Mais si le modèle de données existant (PD-55) ne contient pas ce champ, la spec ne mentionne pas l'extension du modèle nécessaire.
Impact : Le test TC-177-06 pourrait échouer systématiquement si l'entité de persistance ne possède pas le champ `adresse émettrice`.
Gravité : Majeur

ECART-06 — Hypothèse HYP-177-06 potentiellement fausse

Type : Hypothèse dangereuse
Référence : HYP-177-06, INV-177-16, code existant PD-55
Description : HYP-177-06 affirme "La politique de confirmations réseau applicable est déjà définie dans le cadre transactionnel existant." Or le code PD-55 contient des valeurs hardcodées contradictoires. L'hypothèse masque une incohérence technique réelle.
Impact : Si l'hypothèse est fausse, INV-177-16 et CA-177-05 sont inapplicables car le seuil de finalisation n'est pas déterminé contractuellement.
Gravité : Bloquant

ECART-07 — Hardcode réseau dans waitForConfirmation

Type : Contradiction
Référence : Section 2 (périmètre : Polygon + Arbitrum), code existant PD-55
Description : Le périmètre PD-177 mentionne Polygon ET Arbitrum comme réseaux cibles. Le code existant de `waitForConfirmation()` dans PD-55 est hardcodé sur un seul réseau (Polygon). La spec ne mentionne pas cette limitation existante.
Impact : Arbitrum est dans le périmètre contractuel mais potentiellement non confirmable. TC-177-05 pourrait passer sur Polygon mais échouer sur Arbitrum.
Gravité : Bloquant

ECART-08 — Fail-open vs fail-closed pour détection de secrets

Type : Risque sécu/conformité
Référence : INV-177-09, TC-SEC-02, TC-ERR-08
Description : INV-177-09 exige qu'une fuite de secret détectée "produise un echec explicite" (fail-closed). Le learning PD-39 confirme que "Fail-closed is mandatory for security-critical features." Mais la spec ne définit pas le mécanisme de détection. Si le mécanisme est un filtre de logs post-hoc (fail-open : la fuite a déjà eu lieu quand on la détecte), l'invariant est violé.
Impact : Différence critique entre "empêcher la fuite" (fail-closed) et "détecter la fuite après coup" (fail-open). INV-177-09 implique fail-closed mais le test TC-SEC-02 suppose une "tentative injectée" détectée — le moment de la détection (avant/après fuite) n'est pas spécifié.
Gravité : Bloquant

ECART-09 — Formulations divergentes exercice de reprise

Type : Ambiguïté
Référence : INV-177-18, CA-177-13, TC-177-15, ST-177-10
Description : Quatre formulations différentes pour la même exigence :
- INV-177-18 : "testee en exercice"
- CA-177-13 : "un exercice de test aboutit a un resultat consigne"
- TC-177-15 : "un resultat consigne, horodate et auditable est produit"
- ST-177-10 : "un resultat horodate, signe operationnellement, et auditable est consigne"
ST-177-10 ajoute "signé opérationnellement" qui n'apparaît nulle part dans les invariants ou CA.
Impact : Le standard de preuve varie selon le document lu — un implémenteur pourrait produire un résultat non signé (conforme à CA-177-13) mais rejeté par les tests (TC-177-15 exige horodatage + audit).
Gravité : Majeur

ECART-10 — Modèle de menace non défini pour compromission serveur

Type : Non testable
Référence : INV-177-10, TC-SEC-03
Description : INV-177-10 exige qu'une "compromission d'un serveur applicatif ne doit pas permettre la signature arbitraire." TC-SEC-03 teste ce scénario. Mais le modèle de menace n'est pas défini : compromission = accès shell ? Accès mémoire ? Accès au processus Node.js ? Le niveau de protection attendu dépend du modèle d'attaque.
Impact : Le test TC-SEC-03 est non déterministe sans modèle de menace bornant la surface d'attaque.
Gravité : Majeur

ECART-11 — Mapping codes erreur ERR-177-XX vs BlockchainErrorCode

Type : Ambiguïté
Référence : Section 6 (Cas d'erreur), HYP-177-04
Description : La spec définit 8 codes ERR-177-01 à ERR-177-08. HYP-177-04 affirme que "les codes d'erreur blockchain existants couvrent les cas d'erreur PD-177." Mais aucun mapping entre ERR-177-XX et les `BlockchainErrorCode` existants de PD-55 n'est fourni. Les tests (TC-ERR-01 à TC-ERR-08) vérifient les codes ERR-177-XX, pas les codes existants.
Impact : Double système de codes d'erreur sans correspondance explicite — les tests pourraient passer avec ERR-177-XX mais le code réel retourne des BlockchainErrorCode différents.
Gravité : Majeur

ECART-12 — Exclusivité d'usage non opérationnalisée

Type : Non testable
Référence : INV-177-03, TC-177-09
Description : INV-177-03 exige l'exclusivité d'usage ancrage. TC-177-09 teste des "requêtes d'usage non-ancrage (DEX/DeFi, ERC-20, transfert metier tiers)". Mais le wallet n'expose pas d'endpoint DEX/DeFi — l'exclusivité est structurelle (le wallet ne peut faire que de l'ancrage). Le test vérifie l'absence d'une fonctionnalité qui n'existe pas.
Impact : Risque de test tautologique — le wallet n'a pas de mécanisme DeFi, donc le test passe toujours. La vraie menace (un administrateur utilisant le wallet manuellement hors du logiciel) n'est pas couverte.
Gravité : Mineur

ECART-13 — Sanitization de secrets poreuse

Type : Risque sécu/conformité
Référence : INV-177-08, TC-SEC-01
Description : INV-177-08 interdit la clé privée "en clair vers l'application, les logs, les bases de données ou les traces d'erreur." TC-SEC-01 vérifie l'absence dans "logs, traces d'erreur, et enregistrements de persistance." Mais ni la spec ni les tests ne mentionnent : stack traces d'exception (qui peuvent contenir des arguments de méthode), dumps mémoire (core dumps), ou variables d'environnement exposées.
Impact : Un crash Node.js avec `--abort-on-uncaught-exception` pourrait produire un core dump contenant la clé en mémoire. La spec ne borne pas la surface de fuite aux vecteurs les plus communs.
Gravité : Majeur

ECART-14 — Atomicité signature/diffusion non spécifiée

Type : Hypothèse dangereuse
Référence : FN-177-02 (étapes 3-4), INV-177-14
Description : FN-177-02 sépare signature (étape 3) et diffusion (étape 4). La spec ne précise pas ce qui se passe si la signature réussit mais la diffusion échoue : la transaction signée est-elle conservée pour retry ? Détruite ? L'entrée append-only est-elle créée avant ou après diffusion ?
Impact : Si l'entrée append-only est créée après signature mais avant confirmation de diffusion, une interruption peut laisser une entrée orpheline sans tx_hash. Si elle est créée après diffusion, une interruption entre diffusion et écriture append-only crée une transaction on-chain sans trace interne.
Gravité : Majeur

ECART-15 — Rotation dépend de CL non clarifié

Type : Incohérence Spec↔Tests
Référence : INV-177-19, TC-177-14, CL-177-01
Description : INV-177-19 exige que "toute rotation de clé planifiée préserve l'auditabilité." TC-177-14 teste la "rotation planifiée sans perte d'auditabilité." Mais CL-177-01 (politique de rotation) est listé comme "point à clarifier" non résolu. TC-177-14 teste un mécanisme dont les prérequis (déclencheurs, périodicité) ne sont pas définis.
Impact : Le test TC-177-14 peut être implémenté mais ses conditions de déclenchement restent indéterminées — il pourrait ne jamais être exécuté en production.
Gravité : Mineur

ECART-16 — Périmètre UUID ambigu

Type : Ambiguïté
Référence : INV-177-11, CA-177-14, TC-177-16
Description : INV-177-11 exige `crypto.randomUUID()` pour "les identifiants aléatoires techniques introduits par PD-177." Le qualificatif "introduits par PD-177" est ambigu : s'applique-t-il aux UUIDs générés dans le nouveau code PD-177 uniquement, ou aussi aux UUIDs générés dans le code existant modifié par PD-177 ?
Impact : Si PD-177 modifie un service existant qui utilise `Math.random()`, doit-il le migrer vers `crypto.randomUUID()` ? Le périmètre d'application n'est pas borné.
Gravité : Mineur

ECART-17 — Architecture self-transfer non documentée

Type : Hypothèse dangereuse
Référence : FN-177-02 (émission transaction), INV-177-03
Description : La transaction d'ancrage publie un Merkle root on-chain. La spec ne précise pas le mécanisme technique : est-ce un appel à un smart contract (PD-53) ? Un self-transfer avec data en calldata ? Un event log ? Le learning PD-55 mentionne un `MerkleAnchorContract.sol` — la spec PD-177 devrait référencer ce contrat si c'est le mécanisme utilisé.
Impact : Le format de la transaction d'ancrage n'est pas spécifié contractuellement — le test TC-177-04 vérifie un `tx_hash` non vide mais pas la nature de la transaction.
Gravité : Mineur

Synthèse par type

Type Nombre
Ambiguïté 6 (ECART-01, 02, 04, 09, 11, 16)
Contradiction 1 (ECART-07)
Non testable 2 (ECART-10, 12)
Incohérence Spec↔Tests 2 (ECART-05, 15)
Hypothèse dangereuse 3 (ECART-06, 14, 17)
Risque sécu/conformité 3 (ECART-08, 13, bloquant + majeur)

Les 3 actions de déblocage prioritaires

  1. Formaliser la politique de confirmations — lever la contradiction entre les 3 valeurs existantes (12/30/5-par-réseau)
  2. Reconnaître le défaut Arbitrum dans waitForConfirmation() ou retirer Arbitrum du périmètre PD-177
  3. Trancher fail-open vs fail-closed pour la détection de fuite de secret (INV-177-09 vs code existant)