PD-278 — Specification Review¶
Auditeur : Claude (agent factuel) Date : 2026-03-01 Documents analysés : PD-278-specification.md, PD-278-tests.md Domaine : legal-compliance (NF Z42-013 / OAIS lifecycle)
Synthèse¶
17 écarts identifiés : 3 Bloquants, 8 Majeurs, 6 Mineurs
Écarts détaillés¶
ECR-01 — Contradiction : code HTTP pour event_type invalide (400 vs 422)¶
Type : Contradiction
Référence : Spec §5.1 (table formats) vs §6 (E-400-ID-FORMAT) vs Tests TC-ERR-02
Description : §5.1 prescrit un rejet `422` pour un `event_type` hors enum contractuelle.
§6 regroupe les identifiants invalides (UUID/timestamp/enum) sous `E-400-ID-FORMAT`
avec code `400`. TC-ERR-02 tranche pour `422`. Trois sources, deux codes HTTP
différents pour le même cas.
Impact : Une équipe tierce ne sait pas quel code implémenter. Le test TC-ERR-02 valide
un comportement qui contredit §6.
Gravité : Majeur
ECR-02 — Ambiguïté : rôles autorisés pour la transition DIP → SEALED¶
Type : Ambiguïté
Référence : Spec INV-278-02 vs §5.4, Tests TC-NOM-03
Description : INV-278-02 liste explicitement les rôles autorisés pour SEALED → DIP :
`{PA, SA, auditor}`. Pour DIP → SEALED, §5.4 mentionne uniquement
« acteur autorisé » sans lister les rôles. TC-NOM-03 présuppose
« acteur authentifié avec rôle autorisé » sans spécifier lequel.
Impact : Impossible de vérifier contractuellement si un rôle donné est autorisé
ou non pour le retour DIP → SEALED. Aucun test négatif ne couvre un
rôle non autorisé pour cette transition.
Gravité : Bloquant
ECR-03 — Contradiction : audit synchrone vs asynchrone¶
Type : Contradiction
Référence : Spec §5.8 vs §6 (E-500-AUDIT) vs INV-278-04
Description : §5.8 définit l'écriture audit comme « synchrone si même transaction,
sinon async post-commit idempotent » avec « aucune perte d'événement tolérée ».
§6 (E-500-AUDIT) conditionne l'échec de transition à « si audit synchrone
obligatoire » (le mot « si » introduit un doute). INV-278-04 exige un événement
audit à chaque transition sans trancher sync/async.
Le contrat ne permet pas de déterminer si une panne d'audit DOIT bloquer
la transition ou peut être rattrapée en asynchrone.
Impact : Deux implémentations contradictoires sont conformes à la spec.
Le comportement en cas de panne audit est non déterministe.
Gravité : Majeur
ECR-04 — Hypothèse dangereuse : absence de gestion de la concurrence¶
Type : Hypothèse dangereuse
Référence : Spec §5.3, §5.4, §5.8 (atomicité)
Description : Aucune mention de verrouillage ou de contrôle de concurrence pour les
transitions d'état. Scénarios non couverts :
- Deux acteurs demandent SEALED → DIP simultanément sur le même document.
- Un acteur demande SEALED → DIP tandis qu'un autre demande SEALED → EXPIRED.
- Package multi-documents : un document est en cours de transition par un autre
acteur pendant l'assemblage du package.
§5.8 mentionne l'atomicité ACID par transaction mais pas le contrôle d'accès
concurrent inter-requêtes.
Impact : Risque de double attestation, état incohérent, ou race condition sur
la machine à états.
Gravité : Majeur
ECR-05 — Incohérence Spec↔Tests : motif_communication non testé en flux nominal¶
Type : Incohérence Spec↔Tests
Référence : Spec §5.1 (motif_communication) vs Tests (aucun TC nominal)
Description : Le champ `motif_communication` est défini dans le modèle de données
contractuel (§5.1, 0..1024 chars UTF-8) mais :
- Aucun flux nominal (§5.3, §5.4) ne le mentionne dans les effets testables.
- Aucun test nominal ne vérifie son stockage, sa persistance ou sa restitution.
- Seul TC-NEG-03 teste le rejet pour longueur > 1024.
- Aucune mention dans les champs d'audit (INV-278-04) ni dans l'attestation.
Impact : Le champ est spécifié mais son cycle de vie (stockage, lecture, présence
en audit/attestation) n'est pas contractualisé. Non implémentable de
manière déterministe.
Gravité : Majeur
ECR-06 — Hypothèse dangereuse : contournement de la politique de rétention via DIP¶
Type : Risque sécu/conformité
Référence : Spec §5.2 (DIP → EXPIRED INTERDITE) + INV-278-03 (pas de timeout auto)
Description : Un document en DIP ne peut ni expirer directement (DIP → EXPIRED interdit)
ni revenir automatiquement en SEALED (INV-278-03). Si un document reste
indéfiniment en DIP, la politique de rétention (SEALED → EXPIRED) ne peut
jamais s'appliquer. Aucun mécanisme de forçage n'est spécifié.
Impact : Un acteur autorisé pourrait maintenir des documents en DIP pour contourner
la rétention légale. Risque RGPD (droit à l'effacement) et conformité
NF Z42-013 (durée de conservation).
Gravité : Bloquant
ECR-07 — Ambiguïté : cardinalité attestation pour package multi-documents¶
Type : Ambiguïté
Référence : Spec INV-278-05, §5.3, Tests TC-INV-05
Description : INV-278-05 exige « une attestation unique reliée au(x) document(s) source(s)
et à l'acteur ». Pour un package de N documents :
- 1 attestation par package (reliée à N documents) ?
- Ou N attestations (1 par document) ?
Le terme « unique » peut signifier « une seule » ou « à identifiant unique ».
TC-INV-05 ne clarifie pas (« attestation unique, liée source(s)+acteur »).
Impact : Deux implémentations contradictoires satisfont la spec.
Gravité : Majeur
ECR-08 — Ambiguïté : dissemination_package_id pour transition mono-document¶
Type : Ambiguïté
Référence : Spec §5.3 vs INV-278-04, Tests TC-NOM-01
Description : §5.3 dit « dissemination_package_id renseigné si package multi-documents ».
INV-278-04 (audit) inclut « package_id (si présent) ». Mais aucune règle
ne définit le comportement pour un mono-document :
- Le champ est-il NULL ?
- Un package_id est-il généré même pour un seul document ?
TC-NOM-01 (mono-document) n'inclut pas de vérification de l'absence ou
présence de package_id.
Impact : Ambiguïté d'implémentation sur le champ nullable et sur la corrélation audit.
Gravité : Mineur
ECR-09 — Ambiguïté : statut PENDING → EXPIRED — interdit ou inchangé ?¶
Type : Ambiguïté
Référence : Spec §5.2 (transitions PENDING)
Description : §5.2 dit « PENDING → EXPIRED : INTERDITE dans cette story (inchangé
existant non modifié) ». Deux lectures possibles :
1. La transition existe actuellement et n'est pas modifiée par PD-278.
2. La transition est interdite.
Le mot « INTERDITE » contredit « inchangé existant ». Si elle est
actuellement autorisée, elle ne peut pas être à la fois INTERDITE et inchangée.
Impact : Ambiguïté sur la matrice complète de transitions. INV-278-09 exige que
« toute transition non listée comme autorisée est explicitement interdite »,
mais le statut réel de PENDING → EXPIRED est ambigu.
Gravité : Mineur
ECR-10 — Incohérence Spec↔Tests : atomicité package — échec partiel non spécifié¶
Type : Incohérence Spec↔Tests
Référence : Spec §5.1 (cardinalité), §5.3 (flux F1), Tests TC-NOM-02
Description : Pour un package multi-documents, §5.1 rejette en bloc si cardinalité
hors bornes. Mais aucune règle ne couvre le cas où un document individuel
du package échoue (ex: un document sur N n'a pas assez de copies, ou un
document n'est pas SEALED). TC-NOM-02 suppose « tous documents en SEALED »
mais ne teste pas le cas mixte.
Aucun test ne vérifie : « si 1 document sur N échoue la garde, le package
entier est rejeté (pas de traitement partiel) ».
Impact : Risque d'état partiel en multi-documents. Le comportement atomique
n'est contractualisé qu'au niveau cardinalité, pas au niveau des gardes
individuelles.
Gravité : Bloquant
ECR-11 — Incohérence Spec↔Tests : TC-ERR-02 teste un champ non exposé¶
Type : Incohérence Spec↔Tests
Référence : Spec §5.1 (event_type), Tests TC-ERR-02
Description : TC-ERR-02 teste une valeur `event_type` hors enum soumise « à validation
contractuelle ». Or `event_type` est un champ d'audit interne
(`DOCUMENT_DISSEMINATED`, `DOCUMENT_RETURNED`) produit par le système,
pas un champ d'entrée utilisateur. La spec ne définit aucun endpoint
permettant à un utilisateur de soumettre un `event_type`.
Impact : Le test couvre un scénario qui ne peut pas se produire via l'API.
Test hors périmètre ou spec incomplète sur un endpoint d'audit.
Gravité : Mineur
ECR-12 — Hypothèse dangereuse : dépendance à l'horloge sans spécification¶
Type : Hypothèse dangereuse
Référence : Spec §5.1 (timestamps RFC3339 UTC), §5.5 (SLA latence)
Description : Les champs `disseminated_at` et `dissemination_returned_at` sont des
timestamps UTC à la milliseconde. Le SLA mesure des latences en millisecondes.
Aucune mention de :
- Source d'horloge (horloge système, NTP, horloge monotone).
- Tolérance au skew d'horloge entre composants.
- Garantie d'ordre temporel (disseminated_at < dissemination_returned_at).
Impact : En environnement distribué, un skew d'horloge peut produire des
timestamps incohérents (retour avant communication). Aucun invariant
ne protège l'ordre temporel.
Gravité : Mineur
ECR-13 — Risque sécu/conformité : absence de rate limiting sur transitions DIP¶
Type : Risque sécu/conformité
Référence : Spec §5.3 (flux F1), INV-278-02
Description : Un acteur avec rôle PA/SA/auditor peut déclencher SEALED → DIP sur un
nombre illimité de documents sans aucune limitation de débit spécifiée.
Aucune mention de quota, rate limiting, ou alerte en cas de communication
massive.
Impact : Risque d'exfiltration massive par un acteur légitime compromis.
Absent de la matrice de risques et des tests.
Gravité : Mineur
ECR-14 — Ambiguïté : « résolution manuelle uniquement » pour état EXPIRED¶
Type : Ambiguïté
Référence : Spec INV-278-08, §5.2 (EXPIRED terminal)
Description : INV-278-08 et §5.2 déclarent EXPIRED terminal avec « résolution manuelle
uniquement ». Ce mécanisme de résolution manuelle n'est défini nulle part :
- Quel acteur est autorisé ?
- Via quel canal (admin, DBA, procédure documentée) ?
- Quelles transitions manuelles sont possibles ?
TC-INV-08 vérifie que toute sortie est interdite, ce qui contredit
l'existence même d'une « résolution manuelle ».
Impact : Contradiction entre « terminal strict » (tests) et « résolution manuelle »
(spec). Impossible de savoir si EXPIRED est réellement terminal ou non.
Gravité : Majeur
ECR-15 — Incohérence Spec↔Tests : absence de test négatif rôle pour DIP → SEALED¶
Type : Incohérence Spec↔Tests
Référence : Tests (aucun TC-ERR pour rôle non autorisé sur DIP→SEALED)
Description : TC-ERR-04 teste le rejet 403 pour un rôle non autorisé sur SEALED → DIP.
Aucun test équivalent n'existe pour DIP → SEALED. Couplé à ECR-02
(rôles non définis pour DIP → SEALED), la vérification du contrôle d'accès
sur le retour est entièrement absente.
Impact : La transition DIP → SEALED n'est couverte en test que pour le cas nominal.
Le contrôle d'accès du retour n'est ni spécifié ni testé.
Gravité : Majeur
ECR-16 — Non testable : INV-278-10 couverture partielle assumée¶
Type : Non testable
Référence : Spec INV-278-10, Tests TC-INV-10 (matrice couverture « Partielle »)
Description : La matrice de couverture (§2 des tests) indique explicitement une
couverture « Partielle » pour INV-278-10 (envelope encryption), dépendante
de « l'accès observabilité sécurité ». Aucun prérequis d'observabilité
n'est contractualisé pour garantir que ce test puisse être exécuté.
Impact : Un invariant non négociable pourrait ne jamais être validé si
l'observabilité sécurité n'est pas disponible.
Gravité : Majeur
ECR-17 — Ambiguïté : SLOW_OPERATION non défini¶
Type : Ambiguïté
Référence : Spec §5.5 (SLA temporels), Tests TC-NOM-05
Description : §5.5 mentionne qu'un dépassement de SLA produit une opération marquée
`SLOW_OPERATION` et « auditée ». TC-NOM-05 vérifie ce comportement.
Mais `SLOW_OPERATION` n'est défini nulle part :
- Ce n'est pas un `event_type` dans l'enum contractuelle (§5.1).
- Pas de structure d'événement définie.
- Pas de destination (même journal d'audit ? métriques ? logs ?).
Impact : Non implémentable de manière déterministe. Le test TC-NOM-05 n'a pas
d'observable précis pour vérifier le marquage.
Gravité : Mineur
Tableau récapitulatif¶
| ID | Type | Référence | Gravité |
|---|---|---|---|
| ECR-01 | Contradiction | §5.1 vs §6 vs TC-ERR-02 — code HTTP event_type | Majeur |
| ECR-02 | Ambiguïté | INV-278-02 vs §5.4 — rôles DIP→SEALED | Bloquant |
| ECR-03 | Contradiction | §5.8 vs §6 — audit sync/async | Majeur |
| ECR-04 | Hypothèse dangereuse | §5.3, §5.8 — concurrence | Majeur |
| ECR-05 | Incohérence Spec↔Tests | §5.1 vs tests — motif_communication | Majeur |
| ECR-06 | Risque sécu/conformité | §5.2 + INV-278-03 — rétention via DIP | Bloquant |
| ECR-07 | Ambiguïté | INV-278-05 — attestation par package | Majeur |
| ECR-08 | Ambiguïté | §5.3 vs INV-278-04 — package_id mono-doc | Mineur |
| ECR-09 | Ambiguïté | §5.2 — PENDING→EXPIRED interdit ou inchangé | Mineur |
| ECR-10 | Incohérence Spec↔Tests | §5.1, §5.3, TC-NOM-02 — atomicité package | Bloquant |
| ECR-11 | Incohérence Spec↔Tests | TC-ERR-02 — event_type non exposé | Mineur |
| ECR-12 | Hypothèse dangereuse | §5.1, §5.5 — horloge | Mineur |
| ECR-13 | Risque sécu/conformité | §5.3, INV-278-02 — rate limiting | Mineur |
| ECR-14 | Ambiguïté | INV-278-08, §5.2 — résolution manuelle EXPIRED | Majeur |
| ECR-15 | Incohérence Spec↔Tests | Tests — pas de test rôle pour DIP→SEALED | Majeur |
| ECR-16 | Non testable | INV-278-10 — observabilité non garantie | Majeur |
| ECR-17 | Ambiguïté | §5.5 — SLOW_OPERATION non défini | Mineur |
Points à clarifier existants (Q-01 à Q-05)¶
Les 5 questions en suspens du §10.2 de la spécification sont confirmées comme légitimes. Q-01 (N_MAX) est effectivement bloquant et impacte CA-08, TC-ERR-08B, TC-ERR-08C. Les écarts ci-dessus s'ajoutent à ces questions et ne les remplacent pas.