Aller au contenu

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

Documents audités

  • PD-286-specification.md
  • PD-286-tests.md (limité à : ambiguïtés, contradictions, règles non testables, hypothèses dangereuses, risques sécu/conformité — sans verdict de couverture)

Synthèse

Bloquants : 5 — Majeurs : 7 — Mineurs : 6.

Le verrou principal est une désynchronisation systémique entre spec et tests sur la numérotation des critères d'acceptation (CA) et des invariants (INV), associée à plusieurs contradictions de fond (comportement de la borne 768 MB / 10 GB, codes d'erreur, machine à états vs invariant DEK). Sans levée préalable, l'auditabilité contractuelle de la story (Art. III) et la séparation review/tests (Art. II) ne tiennent pas.


Écarts identifiés

Bloquants

Type        : Contradiction (Spec ↔ Tests)
Référence   : PD-286-tests.md §2 (matrice de couverture) vs PD-286-specification.md §7 (CA)
Description : La matrice de couverture des tests utilise une numérotation des CA décalée
              par rapport à la spec :
                - Tests « INV-286-07 | CA-286-04 | TC-NOM-04 » → spec CA-286-04 = « .pvproof
                  unique » alors que TC-NOM-04 traite le recalcul de hash, qui correspond à
                  CA-286-05 dans la spec.
                - Tests « INV-286-08 | CA-286-03 | TC-NOM-03 » → spec CA-286-03 = « preuve
                  unique 900 MB » alors que TC-NOM-03 traite l'unicité du .pvproof (CA-286-04).
                - Tests « INV-286-09 | CA-286-06 | TC-NOM-05 » → spec CA-286-06 = « échec
                  volume = échec global » alors que TC-NOM-05 traite l'audit (CA-286-07).
                - Tests « INV-286-11 | CA-286-07 | TC-INV-11 » → spec CA-286-07 = audit alors
                  que TC-INV-11 traite la machine à états (CA-286-08).
              Plusieurs autres lignes de la matrice sont également décalées.
Impact      : Traçabilité INV/CA/TEST cassée pour l'ensemble du périmètre Gate 8 (Art. III).
              Casse la matrice RTM, casse la vérification de couverture en Phase 2.
Gravité     : Bloquant
Type        : Incohérence Spec ↔ Tests
Référence   : PD-286-tests.md §2 (matrice), §5 (tests d'invariants), TC-INV-12 vs PD-286-specification.md §4
Description : Les tests référencent un invariant `INV-286-12` (« États terminaux sans
              transition sortante ») qui n'existe pas dans la spec. La spec s'arrête à
              `INV-286-11` qui couvre déjà les états terminaux. La matrice tests confond
              INV-286-10 (machine à états) et INV-286-11 (terminaux) avec ce qui semble
              être un INV-286-11 / INV-286-12 décalés d'un cran.
Impact      : Invariant fantôme dans les tests. Tout test associé est sans accroche
              contractuelle. Vice de tracabilité bloquant pour Gate 8.
Gravité     : Bloquant
Type        : Contradiction (Spec ↔ Tests)
Référence   : PD-286-specification.md §4 INV-286-10 / §7 CA-286-08 vs PD-286-tests.md §5 INV-286-10
Description : Spec §4 : « INV-286-10 = Machine à états d'export contractuelle (transitions
              listées) ». Tests §5 (lignes invariants) : « INV-286-10 | TC-INV-10 | Absence
              de DEK/clé/fragment en clair au repos ». Le contenu de INV-286-10 dans les
              tests décrit une exigence de chiffrement au repos qui n'apparaît nulle part
              dans la spec PD-286.
Impact      : Soit la spec a perdu un invariant critique de chiffrement, soit les tests
              testent un invariant absent. Dans les deux cas, périmètre indéterminé.
Gravité     : Bloquant
Type        : Contradiction (Spec ↔ Tests)
Référence   : PD-286-specification.md §4 INV-286-01, §7 CA-286-03, §6 ERR-286-02, §8 GWT-286-04
              vs PD-286-tests.md §4 TC-ERR-02
Description : Spec : une preuve atomique de 900 MB (> 768 MB et < 10 GB) est ACCEPTÉE en
              « volume dédié exceptionnel » (INV-286-01, CA-286-03, GWT-286-04). Le rejet
              `413 PROOF_TOO_LARGE` est réservé aux preuves > 10 GB (ERR-286-02).
              Tests TC-ERR-02 : « GIVEN une preuve atomique unique de 900 MB → THEN
              Réponse 422 PROOF_TOO_LARGE_FOR_VOLUME ». Le test impose un rejet là où la
              spec impose une acceptation.
              S'ajoute une triple contradiction : code HTTP (413 spec vs 422 tests), nom
              du code (`PROOF_TOO_LARGE` spec vs `PROOF_TOO_LARGE_FOR_VOLUME` tests, le
              second n'existe nulle part dans la spec), seuil déclencheur (10 GB spec vs
              768 MB tests).
Impact      : Comportement contractuel principal de la story divergent entre spec et
              tests. CA-286-03 et GWT-286-04 deviennent non vérifiables sans contredire
              TC-ERR-02. Régression fonctionnelle quasi certaine si on suit l'un ou l'autre.
Gravité     : Bloquant
Type        : Incohérence Spec ↔ Tests (couverture manquante)
Référence   : PD-286-specification.md §7 CA-286-10, §6 ERR-286-02, §8 GWT-286-05 vs PD-286-tests.md §2
Description : CA-286-10 (« Preuve atomique > 10 GB rejetée explicitement → 413
              PROOF_TOO_LARGE ») et son scénario GWT-286-05 ne sont mappés à aucun test
              dans la matrice §2 et n'apparaissent pas non plus dans les tests d'invariants
              §5. Aucun TC ne couvre la borne 10 GB sur preuve atomique.
              TC-ERR-02 (mal cadré sur 900 MB) ne supplée pas ce gap. Le rejet > 10 GB est
              un comportement de sécurité (anti-abus) non couvert.
Impact      : Gap de couverture sur un cas-limite de protection (borne 10 GB). CA-286-10
              non testable en l'état → critère d'acceptation non vérifiable en Gate 8.
Gravité     : Bloquant

Majeurs

Type        : Incohérence Spec ↔ Tests
Référence   : PD-286-tests.md §9 (règles non testables) Q-286-01 vs PD-286-specification.md §10.2
Description : Les tests référencent une question ouverte `Q-286-01 : Canonicalisation JSON
              exacte (algorithme formel non spécifié)`. La spec §10.2 ne contient aucun
              Q-286-01 ; elle commence à Q-286-02. Par ailleurs, la spec §3 et §5.4
              affirment RFC 8785 (JCS) comme algorithme de canonicalisation, donc
              l'ambiguïté Q-286-01 que les tests pointent n'existe pas formellement dans
              la spec — soit la spec a tranché et les tests sont obsolètes, soit les tests
              ont raison et RFC 8785 ne suffit pas comme spécification (variantes
              d'implémentation de JCS).
Impact      : Numérotation des Q-286-XX désynchronisée. Le verdict tests « ⚠️ Testable
              partiellement » repose en partie sur une question qui n'existe pas
              formellement dans la spec.
Gravité     : Majeur
Type        : Contradiction (Spec ↔ Tests)
Référence   : PD-286-specification.md §5.1 « totalVolumes : pas de borne max fixe contractuelle » vs
              PD-286-tests.md §7 TC-NEG-04, TC-NEG-05
Description : Spec §5.1 explicitement « totalVolumes min=1, pas de borne max fixe
              contractuelle » et « volumeIndex max dynamique = totalVolumes-1 ».
              Tests : TC-NEG-04 « totalVolumes=0 ou >14 → 500 INVALID_TOTAL_VOLUMES » et
              TC-NEG-05 « volumeIndex <0 ou >13 → 500 INVALID_VOLUME_INDEX_RANGE ».
              La borne 14 (et donc 13 pour volumeIndex) n'apparaît nulle part dans la
              spec (10 GB / 768 MB ≈ 14, mais ce calcul n'est pas tracé contractuellement
              et ne tient pas si une preuve dédiée occupe un volume).
Impact      : Borne max introduite par les tests, absente du contrat. Soit la spec doit
              fixer la borne (et alors le calcul 10 GB/768 MB est faux quand un volume
              dédié exceptionnel est présent), soit les tests doivent être revus.
Gravité     : Majeur
Type        : Contradiction terminologique
Référence   : PD-286-specification.md §5bis (diagramme de séquence) vs §3, §4, §5
Description : Le diagramme de séquence introduit `complaintId` (`POST /exports
              {complaintId}`) et `ComplaintFileResponseDto {volumes[], metadata}` comme
              nom du DTO de réponse. Aucun de ces deux identifiants n'est défini dans la
              spec : la spec parle de « dossier », « preuves », « exportId » et
              `ExportVolumeDto`. La notion de « plainte » (complaint) est étrangère au
              vocabulaire de la spec.
Impact      : Contrat d'API ambigu. Soit l'entité métier est « complaint » (et alors le
              vocabulaire spec doit suivre), soit elle est « dossier/export » (et alors
              le diagramme est faux). Tests et code dépendant.
Gravité     : Majeur
Type        : Ambiguïté
Référence   : PD-286-specification.md §5.4 (étape 3) et §5bis (diagramme de séquence)
Description : Le diagramme de séquence indique que c'est le BACKEND qui calcule
              `integrityHash = sha3_256(jcs_rfc8785(manifest_partial))`, mais le texte
              §5.4 step 3 dit seulement « chaque volume contient manifest +
              integrityHash » sans préciser qui calcule, ni l'algorithme. INV-286-07
              parle uniquement de la vérification côté app. Le contrat de production du
              hash côté backend est donc seulement inférable du diagramme.
Impact      : Si le diagramme et le texte divergent (axe 5bis), la vérification
              d'intégrité peut être réalisée sur des hash incompatibles entre backend et
              app. Risque réel sur la vérification de preuves.
Gravité     : Majeur
Type        : Hypothèse dangereuse
Référence   : PD-286-specification.md §9 H-286-01, §10.1
Description : H-286-01 « IntegrityHashComputer implémente RFC 8785 de manière stable
              entre backend et app ». Stack cible §10.1 : backend NestJS (Node.js) /
              app React Native + Expo SDK 54 (TypeScript). RFC 8785 (JCS) n'a pas
              d'implémentation de référence partagée Node ↔ RN ; les libs disponibles
              sur npm ne sont pas équivalentes byte-à-byte (ex : ordre des clés Unicode,
              nombres flottants). Sans test de conformité cross-runtime, H-286-01 est
              une hypothèse non vérifiée et bloquante.
Impact      : Faux négatifs d'intégrité (mismatch de hash) systématiques sur tout
              caractère non-ASCII dans un manifest. Toute preuve avec métadonnées
              accentuées peut faire échouer l'export.
Gravité     : Majeur
Type        : Hypothèse dangereuse
Référence   : PD-286-specification.md §4 INV-286-08, §3 (définitions), §5.5
Description : INV-286-08 dit que le « conteneur .pvproof reste inchangé ; seul
              pvproof.json interne inclut volumes_count + assembled_from[] si export
              avec volumes[] ». Aucun lien vers la spec du conteneur .pvproof n'est
              fourni, et aucun test ne vérifie qu'un consommateur legacy de .pvproof
              accepte un fichier avec ces deux champs supplémentaires (TC-NR-02 affirme
              la non-régression sans observable concret).
Impact      : Si un consommateur de .pvproof valide la liste exhaustive des champs de
              pvproof.json, l'ajout de volumes_count/assembled_from[] casse la
              compatibilité ascendante.
Gravité     : Majeur
Type        : Risque sécu/conformité
Référence   : PD-286-specification.md §4 INV-286-09 (« audit WORM fail-closed »)
Description : « Fail-closed » est invoqué sans définition opérationnelle : que se
              passe-t-il si le journal WORM est indisponible au moment de la finalisation
              `COMPLETED` ? Le flux est-il bloqué (et donc l'utilisateur perd l'export
              déjà téléchargé), ou l'export reste-t-il dans un état intermédiaire avec
              dette d'audit ? La spec ne tranche pas. ERR-286-XX ne couvre pas ce cas.
Impact      : Comportement non déterministe en cas de panne audit. Risque de perte
              d'auditabilité contre INV-286-09 lui-même, ou de DoS sur l'export en cas
              d'incident d'infra audit.
Gravité     : Majeur

Mineurs

Type        : Ambiguïté
Référence   : PD-286-specification.md §5.1 (modèle de données contractuel)
Description : Le tableau définit les types des champs (exportId, volumeIndex, manifest,
              integrityHash, signedUrl, etc.) mais ne fournit pas une définition
              explicite et unique du DTO `ExportVolumeDto` (référencé en §4 INV-286-07
              et dans le diagramme). La structure complète (champs obligatoires/
              optionnels, enveloppe, version) reste implicite.
Impact      : Risque de divergence backend/app sur le DTO. Fragilise la traçabilité du
              contrat API.
Gravité     : Mineur
Type        : Ambiguïté
Référence   : PD-286-specification.md §5.4 (flux nominal B, étape 4)
Description : « L'app traite les volumes séquentiellement » : aucune obligation de tri
              par volumeIndex n'est explicitement formulée. Si l'API renvoie volumes[]
              dans un ordre arbitraire, l'app pourrait soit lever un trou apparent, soit
              les traiter dans l'ordre reçu, ce qui complique l'observabilité.
Impact      : Tests non déterministes si l'ordre dans volumes[] varie. TC-INV-03 (union
              sans omission) reste vérifiable, mais TC-NOM-04 (séquentiel) devient
              ambigu.
Gravité     : Mineur
Type        : Incohérence cohérence diagrammes (axe 5bis)
Référence   : PD-286-specification.md §5bis (diagramme d'état) vs §4 INV-286-10 (transitions interdites)
Description : Le diagramme représente certaines transitions INTERDITES (COMPLETED →
              REQUESTED, COMPLETED → DOWNLOADING, FAILED → REQUESTED, EXPIRED →
              REQUESTED) mais omet d'autres interdictions explicitement listées dans le
              texte : `PLANNED_MULTI → PLANNED_SINGLE`, `COMPLETED → ASSEMBLING`,
              `COMPLETED → PLANNED_*`. Ces interdictions ne sont donc visibles que dans
              le texte.
Impact      : Diagramme partiel — auditeur visuel pourrait conclure que ces transitions
              sont « simplement absentes » sans réaliser qu'elles sont explicitement
              interdites.
Gravité     : Mineur
Type        : Ambiguïté
Référence   : PD-286-specification.md §4 INV-286-03 (« ensemble des preuves validées »)
Description : Le terme « validées » n'est pas défini : statut de preuve dans le système ?
              Pipeline de validation (hors périmètre §2) ? Filtre métier sur le dossier ?
              L'union mentionnée par INV-286-03 dépend de ce périmètre.
Impact      : Critère INV-286-03 difficilement testable sans qualifier l'ensemble de
              référence.
Gravité     : Mineur
Type        : Hypothèse dangereuse
Référence   : PD-286-specification.md §5.2 (SLA temporels) vs §4 INV-286-11
Description : Pas de référence à la source d'horloge faisant foi (signature backend,
              système app, signed URL signing time). Un décalage d'horloge entre app et
              backend peut faire transiter prématurément vers EXPIRED côté app sans
              que le backend ne le considère expiré (ou inversement).
Impact      : Comportement non déterministe entre clients selon dérive d'horloge. Faux
              EXPIRED possibles. Manque de qualification dans les tests TC-ERR-05.
Gravité     : Mineur
Type        : Risque sécu/conformité
Référence   : PD-286-specification.md §4 INV-286-11 (« données temporaires conservées
              selon politique de rétention existante »)
Description : Aucun pointeur vers cette « politique de rétention existante » (durée,
              chiffrement au repos, isolation par utilisateur) ; Q-286-03 est une
              question ouverte. Sans valeur chiffrée, la conformité RGPD/CCPA des temp
              files post-FAILED/EXPIRED est non auditable.
Impact      : Conformité non vérifiable. Tests Q-286-03 marqués Mineur — devraient être
              Majeur tant que la politique n'est pas pointée explicitement.
Gravité     : Mineur

Tableau de synthèse

# Type Référence Gravité
1 Contradiction matrice tests §2 vs spec §7 (CA-286-XX) Bloquant
2 Incohérence Spec↔Tests INV-286-12 dans tests, absent spec Bloquant
3 Contradiction INV-286-10 (machine état spec vs DEK tests) Bloquant
4 Contradiction preuve 900 MB acceptée (spec) vs rejetée (tests) Bloquant
5 Incohérence Spec↔Tests CA-286-10 (>10 GB) sans test Bloquant
6 Incohérence Spec↔Tests Q-286-01 dans tests, absent spec Majeur
7 Contradiction totalVolumes max 14 (tests) vs illimité (spec) Majeur
8 Contradiction terminologique complaintId / ComplaintFileResponseDto (diagramme) absent spec Majeur
9 Ambiguïté calcul backend integrityHash inférable du diagramme uniquement Majeur
10 Hypothèse dangereuse RFC 8785 stable Node ↔ React Native (H-286-01) Majeur
11 Hypothèse dangereuse .pvproof legacy tolère volumes_count/assembled_from[] (TC-NR-02) Majeur
12 Risque sécu/conformité « audit WORM fail-closed » non défini Majeur
13 Ambiguïté DTO ExportVolumeDto non défini formellement Mineur
14 Ambiguïté ordre de tri de volumes[] Mineur
15 Incohérence diagrammes (5bis) transitions INTERDITES partiellement représentées Mineur
16 Ambiguïté « preuves validées » (INV-286-03) Mineur
17 Hypothèse dangereuse source d'horloge TTL non spécifiée Mineur
18 Risque sécu/conformité politique rétention temp files non chiffrée (Q-286-03) Mineur

Verdict d'auditabilité (sans correction proposée)

La spécification PD-286 décrit un contrat fonctionnel cohérent en flux nominal et en états terminaux, mais comporte des contradictions structurelles avec ses propres tests (numérotation INV/CA, codes d'erreur, comportement borne 768 MB / 10 GB) qui rendent l'acceptation formelle de Gate ⅝ non démontrable en l'état. La levée des 5 bloquants est un préalable à toute soumission Gate 5.