PD-278 — Specification Review v3¶
Statut des bloquants v2¶
CONTR-01 (v2 — Bloquant) → RÉSOLU¶
INV-278-02 inclut désormais explicitement retention_due=false comme garde de SEALED → DIP. Cohérent avec INV-278-14 qui interdit l'entrée en DIP quand retention_due=true. TC-ERR-14 teste le scénario de rejet 409 E-409-RETENTION-DUE. La contradiction entre les deux invariants est éliminée.
INC-02 (v2 — Bloquant) → RÉSOLU¶
INV-278-14 est couvert par deux tests complémentaires : - TC-ERR-14 : blocage SEALED → DIP quand retention_due=true (volet entrée) - TC-INV-13 Cas B : DIP → SEALED explicite par retention_service quand retention_due=true (volet cloture)
Les deux faces du mécanisme anti-contournement sont testées.
Écarts identifiés (v3)¶
ÉCART GAP-01¶
Type : Ambiguïté / Incohérence Spec↔Tests Référence : §5.1 (event_type enum), INV-278-04, TC-ERR-12 Description : L'enum event_type audit définit trois valeurs : DOCUMENT_DISSEMINATED, DOCUMENT_RETURNED, DOCUMENT_DISSEMINATION_DENIED. Le terme "dissemination denied" désigne linguistiquement un refus de communication (SEALED → DIP). Or INV-278-04 stipule que "chaque tentative refusée pour 401/403/429/409-retention_due persiste un événement audit sécurité". Un refus 403 sur DIP → SEALED (TC-ERR-12) est couvert par INV-278-04 (code 403), mais aucun event_type dédié n'existe pour un refus de retour. Faut-il réutiliser DOCUMENT_DISSEMINATION_DENIED (sémantiquement incorrect) ou ajouter un type DOCUMENT_RETURN_DENIED ? Impact : Un implémenteur ne sait pas quel event_type logger pour un refus DIP → SEALED. Incohérence entre le périmètre d'audit de INV-278-04 et l'enum disponible. Gravité : Majeur
ÉCART GAP-02¶
Type : Incohérence Spec↔Tests Référence : INV-278-04 (audit refus sécurité), TC-ERR-12 Description : TC-ERR-12 vérifie qu'un acteur non autorisé reçoit 403 et que le statut reste DIP, mais ne vérifie pas la persistance d'un événement audit sécurité de refus. INV-278-04 exige l'audit de toute tentative refusée 403. Les tests TC-ERR-03, TC-ERR-04, TC-ERR-05, TC-ERR-13, TC-ERR-14 vérifient tous l'audit de refus — TC-ERR-12 est le seul test de refus sécurité qui omet cette vérification. Impact : Couverture de test incomplète sur l'auditabilité des refus DIP → SEALED. Gravité : Majeur
ÉCART GAP-03¶
Type : Ambiguïté Référence : §5.13 (attestation schema), champs hash_evidence et signature_ref Description : hash_evidence est décrit comme "empreinte intégrité" sans préciser : intégrité de quoi (contenu documentaire ? métadonnées d'attestation ? requête complète ?), quel algorithme (SHA-256 ? SHA-512 ?), quel encodage (hex ? base64 ?). signature_ref est décrit comme "référence clé/KMS/HSM" sans préciser s'il s'agit de l'identifiant de clé, de la signature elle-même, ou d'une URI de référence. Impact : Un implémenteur ne peut pas produire une attestation conforme au contrat sans arbitrages supplémentaires. Deux implémentations indépendantes produiraient des attestations incompatibles. Gravité : Majeur
ÉCART GAP-04¶
Type : Ambiguïté Référence : §5.1 (motif_communication), §5.6 (bornes numériques) Description : La limite de motif_communication est définie comme "0..1024 caractères UTF-8". L'unité "caractère" est ambiguë en UTF-8 : codepoints Unicode, octets, ou grapheme clusters. Exemple : l'emoji 👨👩👧👦 fait 1 grapheme cluster, 7 codepoints, 25 octets UTF-8. La limite de 1024 varie d'un facteur ~25× selon l'interprétation. Impact : Comportement de validation divergent entre implémentations. Tests limites (TC-NEG-03 avec longueur 1025) non déterministes. Gravité : Mineur
ÉCART GAP-05¶
Type : Ambiguïté Référence : §5.2 (machine à états), §5.3 (F1), §5.4 (F2) Description : Le cycle SEALED → DIP → SEALED → DIP (re-dissemination) est implicitement autorisé par la machine à états mais jamais décrit. La spec ne précise pas si les champs disseminated_at, disseminated_by, dissemination_package_id, motif_communication sont écrasés lors d'une seconde dissemination, ni si dissemination_returned_at est remis à NULL. L'historique des cycles précédents n'existe alors qu'en audit, pas sur le document — comportement non contractualisé. Impact : Implémentation non déterministe du comportement des métadonnées de dissemination lors de cycles multiples. Perte potentielle de traçabilité directe (hors audit). Gravité : Mineur
ÉCART GAP-06¶
Type : Non testable Référence : INV-278-10 (envelope encryption) Description : L'invariant mentionne "tout artefact cryptographique temporaire lié à la communication DIP". La spécification ne définit nulle part quels artefacts cryptographiques temporaires sont produits pendant le flux DIP. La génération d'attestation (§5.13) implique un hash et une signature, mais la spec ne décrit pas d'artefacts intermédiaires persistés puis nettoyés. TC-INV-10 vérifie "chiffrement au repos actif" mais sans définition des artefacts cibles, le périmètre du test est indéterminé. Impact : L'invariant est contractuellement valide mais opérationnellement non vérifiable sans clarification des artefacts couverts. Gravité : Mineur
ÉCART GAP-07¶
Type : Incohérence Spec↔Tests Référence : §2 (matrice de couverture tests), TC-NOM-07 Description : TC-NOM-07 (vérification dissemination_package_id NULL/non-NULL selon cardinalité) n'apparaît dans aucune ligne de la matrice de couverture (§2 du document tests). Le scénario est couvert fonctionnellement par TC-NOM-01 (mono) et TC-NOM-02 (multi), mais TC-NOM-07 est orphelin dans la matrice. Impact : Traçabilité incomplète de la couverture. Risque de suppression accidentelle d'un test non rattaché. Gravité : Mineur
ÉCART GAP-08¶
Type : Hypothèse dangereuse Référence : §5.9 (concurrence et isolation), règle cross-module Description : La spec impose un "ordre de verrouillage global (tri lexicographique croissant de document_id)" et exige que "tout module qui verrouille ces documents applique le même ordre". Cette contrainte cross-module dépasse le périmètre de PD-278. Aucun mécanisme d'enforcement n'est décrit (convention documentaire, abstraction de locking partagée, linter). Si un module existant ou futur ne respecte pas cet ordre, des deadlocks surviennent en production. Impact : Risque de deadlock non détectable par les tests de PD-278 seuls. Gravité : Mineur
ÉCART GAP-09¶
Type : Non testable Référence : §5.13 (attestation), "Conservation minimale : 10 ans" Description : La durée de conservation de 10 ans n'est pas vérifiable par un test fonctionnel. Elle relève d'une politique de stockage/rétention infrastructure. Aucun test n'adresse ce critère. Impact : Exigence contractuelle sans preuve de conformité possible dans le périmètre tests. Gravité : Mineur
Synthèse¶
| Gravité | Nombre | IDs |
|---|---|---|
| Bloquant | 0 | — |
| Majeur | 3 | GAP-01, GAP-02, GAP-03 |
| Mineur | 6 | GAP-04, GAP-05, GAP-06, GAP-07, GAP-08, GAP-09 |
Bloquants v2 résolus : 2/2 (CONTR-01 ✓, INC-02 ✓)
Verdict : Aucun bloquant résiduel. 3 écarts majeurs identifiés portant sur l'auditabilité des refus DIP → SEALED (GAP-01 + GAP-02 couplés) et la sous-spécification du schéma d'attestation cryptographique (GAP-03). Les 6 mineurs relèvent de précisions contractuelles souhaitables mais non bloquantes pour l'implémentation.