PD-279 — Scénarios de tests contractuels
1. Références
- Spécification : PD-279-specification.md
- Epic : EPIC-XX
2. Matrice de couverture
| ID Invariant | ID Critère | ID Test | Couverture | Commentaire |
| INV-279-01-state-model | CA-279-01 | TC-NOM-01 | Oui | Enum RESTITUTED présent et exploitable en runtime. |
| INV-279-02-restitute-guards | CA-279-03 | TC-NOM-01 | Oui | Restitution autorisée quand toutes gardes sont vraies. |
| INV-279-02-restitute-guards | CA-279-04 | TC-ERR-05 | Oui | Refus 409 si état source invalide. |
| INV-279-02-restitute-guards | CA-279-04 | TC-ERR-06 | Oui | Refus 409 si geo_copy_count < 2. |
| INV-279-02-restitute-guards | CA-279-04 | TC-ERR-07 | Oui | Refus 409 si legal_lock=true. |
| INV-279-02-restitute-guards | CA-279-12 | TC-ERR-03 | Oui | Refus 403 si appelant non propriétaire. |
| INV-279-03-return-guards | CA-279-05 | TC-NOM-02 | Oui | Retour autorisé si owner et état RESTITUTED. |
| INV-279-03-return-guards | CA-279-06 | TC-ERR-08 | Oui | Refus 409 si état source != RESTITUTED. |
| INV-279-03-return-guards | CA-279-12 | TC-ERR-04 | Oui | Refus 403 au retour si non owner. |
| INV-279-04-traceability | CA-279-07 | TC-NOM-04 | Oui | Attestation complète + audit sur chaque transition. |
| INV-279-05-sla | CA-279-09 | TC-NOM-01 | Oui | deadline = restituted_at + SLA à la seconde. |
| INV-279-05-sla | CA-279-10 | TC-NOM-03 | Oui | Alerte 80% et escalade 100% observables et distinctes. |
| INV-279-06-no-destruction-while-restituted | CA-279-08 | TC-NOM-05 | Oui | Destruction refusée en 409 pour RESTITUTED. |
| INV-279-07-transition-matrix | CA-279-04 | TC-ERR-05 | Oui | Transition non autorisée explicitement rejetée. |
| INV-279-07-transition-matrix | CA-279-06 | TC-ERR-08 | Oui | Matrice appliquée côté retour restitution. |
| INV-279-08-ddl-reversible | CA-279-02 | TC-NOM-06 | Oui | Migration up/down validée en CI. |
| INV-279-09-atomicity | CA-279-07 | TC-INV-09A | Oui | Changement état + lifecycle_log atomiques (même transaction). |
| INV-279-09-atomicity | CA-279-10 | TC-INV-09B | Oui | Jobs SLA post-commit idempotents et rattrapables. |
| INV-279-10-cross-module-guard | CA-279-08 | TC-NOM-05 | Oui | Garde cross-module destruction active et auditée. |
| INV-279-01-state-model | CA-279-11 | TC-NOM-07 | Oui | Vérification formelle AnchorAssume_States en PASS. |
3. Scénarios de test – Flux nominaux
TEST-ID: TC-NOM-01
Référence spec: INV-279-01, INV-279-02, INV-279-05, CA-279-01, CA-279-03, CA-279-09
GIVEN
- Document existant avec `status=SEALED`, `legal_lock=false`, `geo_copy_count=2`
- Appelant authentifié propriétaire du document
- Configuration SLA valide (ex: `restitution_max_duration=30j`)
- Horloge de test figée en UTC (T0) pour déterminisme
WHEN
- `POST /documents/:id/restitute`
THEN
- Réponse HTTP 200
- `status` devient `RESTITUTED`
- `restituted_at = T0` (UTC) et `restitution_deadline = T0 + 30j` (écart 0 seconde)
AND
- Une attestation `lifecycle_log(type=RESTITUTION)` est persistée
- Un événement d'audit de restitution est émis post-commit
TEST-ID: TC-NOM-02
Référence spec: INV-279-03, CA-279-05
GIVEN
- Document existant avec `status=RESTITUTED`
- Appelant authentifié propriétaire du document
WHEN
- `POST /documents/:id/return-from-restitution`
THEN
- Réponse HTTP 200
- `status` devient `SEALED`
AND
- Une attestation `lifecycle_log(type=RETURN_FROM_RESTITUTION)` est persistée
- Un événement d'audit de retour est émis
- Les alertes/escalades SLA actives pour cette fenêtre de restitution sont clôturées
TEST-ID: TC-NOM-03
Référence spec: INV-279-05, CA-279-10
GIVEN
- Document en `RESTITUTED` avec `restituted_at=T0`, SLA=30 jours
- Scheduler SLA actif avec source temps contrôlée
WHEN
- Le temps simulé atteint T0 + 24 jours (80%), puis T0 + 30 jours (100%)
THEN
- Un événement d'alerte 80% est produit exactement une fois
- Un événement d'escalade 100% est produit exactement une fois
AND
- Le document reste `RESTITUTED` (pas de transition automatique)
- Les deux événements sont traçables (horodatage UTC, document_id)
TEST-ID: TC-NOM-04
Référence spec: INV-279-04, CA-279-07
GIVEN
- Un document éligible pour restitution puis retour
- Appelant owner avec `actor_id` UUID v4 valide
WHEN
- Exécution séquentielle de `restitute` puis `return-from-restitution`
THEN
- Deux entrées `lifecycle_log` existent avec types attendus
- Chaque entrée contient `timestamp_utc`, `actor_id`, `type`, `security_level`
AND
- Deux événements d'audit correspondants existent
- Les timestamps sont en UTC RFC3339
TEST-ID: TC-NOM-05
Référence spec: INV-279-06, INV-279-10, CA-279-08
GIVEN
- Document existant avec `status=RESTITUTED`
- Appelant autorisé sur module destruction
WHEN
- Appel endpoint destruction du module PD-250
THEN
- Réponse HTTP 409 avec code métier de refus destruction
- Aucune destruction effective (intégrité document préservée)
AND
- Un audit de refus est enregistré
TEST-ID: TC-NOM-06
Référence spec: INV-279-08, CA-279-02
GIVEN
- Base de données initiale au schéma n-1
WHEN
- Exécution migration `up` puis migration `down`
THEN
- Les deux commandes réussissent sans erreur
- Le schéma final après `down` est cohérent avec l'état initial attendu
AND
- Aucun état structurel invalide n'est introduit
TEST-ID: TC-NOM-07
Référence spec: CA-279-11
GIVEN
- Modèle formel et implémentation de statuts synchronisés
WHEN
- Exécution de la vérification `AnchorAssume_States`
THEN
- Résultat PASS
AND
- Rapport de vérification archivé comme preuve de conformité
4. Scénarios de test – Cas d’erreur
TEST-ID: TC-ERR-01
Référence spec: §6 (400 Bad Request), §5.1
GIVEN
- `document_id` non conforme UUID v4
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 400
- Aucune mutation de statut
- Aucune attestation de transition
TEST-ID: TC-ERR-02
Référence spec: §6 (404 Not Found)
GIVEN
- `document_id` valide mais inexistant
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 404
- Aucune attestation
- Aucun événement de transition
TEST-ID: TC-ERR-03
Référence spec: INV-279-02, CA-279-12, §6 (403)
GIVEN
- Document `SEALED` appartenant à un autre utilisateur
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 403
- Statut inchangé
- Aucune attestation de restitution
TEST-ID: TC-ERR-04
Référence spec: INV-279-03, CA-279-12, §6 (403)
GIVEN
- Document `RESTITUTED` appartenant à un autre utilisateur
WHEN
- `POST /documents/:id/return-from-restitution`
THEN
- HTTP 403
- Statut inchangé
- Aucune attestation de retour
TEST-ID: TC-ERR-05
Référence spec: INV-279-02, INV-279-07, CA-279-04, §6 (409)
GIVEN
- Document existant avec `status` différent de `SEALED`
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 409
- Transition refusée selon matrice d'états
- Aucune attestation de restitution
TEST-ID: TC-ERR-06
Référence spec: INV-279-02, CA-279-04, §6 (409)
GIVEN
- Document `SEALED` avec `geo_copy_count=1`
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 409
- Statut inchangé
- Aucune attestation de restitution
TEST-ID: TC-ERR-07
Référence spec: INV-279-02, CA-279-04, §6 (409)
GIVEN
- Document `SEALED` avec `legal_lock=true`
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 409
- Statut inchangé
- Audit de refus présent
TEST-ID: TC-ERR-08
Référence spec: INV-279-03, INV-279-07, CA-279-06, §6 (409)
GIVEN
- Document existant avec `status != RESTITUTED`
WHEN
- `POST /documents/:id/return-from-restitution`
THEN
- HTTP 409
- Statut inchangé
- Aucune attestation `RETURN_FROM_RESTITUTION`
TEST-ID: TC-ERR-09
Référence spec: INV-279-05, §6 (422 ou rejet config)
GIVEN
- Configuration SLA invalide (ex: `restitution_max_duration=0` ou `31`)
WHEN
- Démarrage service / chargement configuration
THEN
- Rejet explicite de la configuration (422 ou erreur de validation config)
- Aucun traitement de restitution accepté tant que configuration invalide
TEST-ID: TC-ERR-10
Référence spec: INV-279-09, §6 (500)
GIVEN
- Injection d'une faute transactionnelle au moment de l'écriture `lifecycle_log`
WHEN
- `POST /documents/:id/restitute`
THEN
- HTTP 500
- Rollback total: statut document inchangé
- Aucune attestation partielle persistée
5. Tests d’invariants (non négociables)
| Invariant | Test(s) dédiés | Observable | Commentaire |
| INV-279-01-state-model | TC-NOM-01 | Enum RESTITUTED accepté en lecture/écriture runtime | Couvre alignement modèle/implémentation. |
| INV-279-02-restitute-guards | TC-NOM-01, TC-ERR-03, TC-ERR-05, TC-ERR-06, TC-ERR-07 | Autorisation/refus strict selon gardes | Aucune garde implicite. |
| INV-279-03-return-guards | TC-NOM-02, TC-ERR-04, TC-ERR-08 | Retour autorisé uniquement si owner + RESTITUTED | Contrôle d'accès et état source vérifiés. |
| INV-279-04-traceability | TC-NOM-04 | lifecycle_log complet + audit pour chaque transition | Horodatage UTC obligatoire. |
| INV-279-05-sla | TC-NOM-01, TC-NOM-03, TC-ERR-09 | Deadline exacte + événements 80/100 + validation bornes config | Vérifie temps et gouvernance SLA. |
| INV-279-06-no-destruction-while-restituted | TC-NOM-05 | Refus destruction en 409 | Non-destruction effective contrôlée. |
| INV-279-07-transition-matrix | TC-ERR-05, TC-ERR-08 | Rejets explicites des transitions interdites | Anti-ambiguïté machine à états. |
| INV-279-08-ddl-reversible | TC-NOM-06 | Migration up/down sans incohérence structurelle | Test CI obligatoire. |
| INV-279-09-atomicity | TC-INV-09A, TC-INV-09B, TC-ERR-10 | Atomicité sync + fiabilité async post-commit | Couvre crash/retry/rattrapage. |
| INV-279-10-cross-module-guard | TC-NOM-05 | Garde destruction active au niveau service module destruction | Couvre contrainte inter-modules. |
Détails complémentaires atomicité
TEST-ID: TC-INV-09A
Référence spec: INV-279-09
GIVEN
- Transaction DB instrumentée avec point d'échec contrôlé
WHEN
- Exécution restitution avec erreur forcée avant commit
THEN
- Ni statut `RESTITUTED` ni attestation `RESTITUTION` ne sont persistés
AND
- Aucun événement async SLA n'est planifié
TEST-ID: TC-INV-09B
Référence spec: INV-279-09, §5.8
GIVEN
- Document `RESTITUTED` commité
- Worker SLA redémarré après interruption
WHEN
- Reprise des jobs de rattrapage
THEN
- Les événements 80/100 manquants sont émis
- Les doublons sont évités (idempotence)
AND
- L'état DB reste cohérent (aucune mutation transactionnelle rétroactive)
6. Tests de non-régression
| Test ID | Objet | Observable | Commentaire |
| TC-NR-01 | Compatibilité lecture status existants (PENDING,SEALED,EXPIRED) | Aucune erreur de désérialisation ou de contrat API | Vérifie ajout non cassant de RESTITUTED. |
| TC-NR-02 | Flux hors périmètre non modifiés (ex: SEALED -> EXPIRED) | Comportement identique baseline pré-PD-279 | Non-régression fonctionnelle transversale. |
| TC-NR-03 | Triggers de traçabilité/immutabilité existants | Écriture restitution possible sans violer triggers | Vérifie compatibilité DDL/runtime. |
| TC-NR-04 | Endpoint destruction pour statuts non RESTITUTED | Politique de destruction préexistante inchangée | Valide absence d'effet de bord cross-module. |
7. Tests négatifs et adversariaux
| Test ID | Entrée invalide / abus | Résultat attendu | Observable |
| TC-NEG-01 | Double appel concurrent restitute sur même document SEALED | 1 succès 200 max, autres requêtes rejetées 409 | Un seul passage à RESTITUTED, une seule attestation RESTITUTION. |
| TC-NEG-02 | Rejeu d'appel return-from-restitution après retour déjà effectué | Requête rejouée en 409 | Aucune attestation de retour additionnelle. |
| TC-NEG-03 | UUID valide mais avec casse mixte et format correct | Traitement normal sans faux négatif | Validation UUID conforme contrat v4. |
| TC-NEG-04 | Tentative de forger security_level invalide dans contexte transition | Rejet transactionnel | Aucune attestation partiellement persistée. |
| TC-NEG-05 | Crash applicatif immédiatement post-commit restitution | État DB cohérent + rattrapage async SLA | Preuve audit/lifecycle intacte après redémarrage. |
8. Observabilité requise pour les tests
- État système : lecture DB (
documents.status, restituted_at, restitution_deadline) avant/après action. - Réponse API : code HTTP, payload fonctionnel, code métier de conflit (quand défini).
- Journal d’audit : événement transition/rejet,
document_id, actor_id, horodatage UTC, type événement. - Événement signé / horodaté : flux alertes 80% et escalade 100%, corrélables au document et à la fenêtre SLA.
- Export probatoire : artefacts de preuve (logs, traces, rapport CI migrations, rapport vérification TLA+) versionnés et rejouables.
9. Règles non testables
| Règle | Raison | Impact |
Mapping exact des error_code métier pour chaque 409 (Q-279-02) | La spécification liste les HTTP mais pas la table normative des codes métier attendus client par client | Majeur |
Caractère obligatoire de security_level sur RETURN_FROM_RESTITUTION (Q-279-03) | Exigence indiquée "si requis par contrat existant" sans contrat consolidé joint | Majeur |
| Exhaustivité des routes destruction couvertes (Q-279-05) | Liste exhaustive des endpoints du module PD-250 non fournie dans l'entrée | Majeur |
| Séquence DDL canonique exacte de down migration PostgreSQL (Q-279-04) | Réversibilité testable, mais conformité à la convention DBA interne non vérifiable sans standard détaillé | Mineur |
10. Verdict QA
- ⚠️ Testable partiellement (avec réserves listées)
Réserve principale: le périmètre est fortement testable sur le comportement métier, transactionnel et temporel, mais certains points contractuels inter-modules (error_code 409, obligation security_level retour, inventaire routes destruction) doivent être figés pour lever toute ambiguïté de conformité stricte.