Aller au contenu

PD-250 — Spécification — Job destruction définitive et bordereau (v4)

1. Objectif et conformité normative

Spécifier de manière contractuelle le processus automatique de destruction définitive des documents expirés, avec production d'un bordereau probatoire signé/horodaté, traçabilité unitaire et conservation permanente de la preuve, en conformité avec : - ISO 14641:2018 §11.4 (traçabilité, preuve de destruction, auditabilité), - NF Z42-013:2020 §9.2 (exigences de journalisation, intégrité et conservation des preuves), - Règlement eIDAS (UE) n°910/2014 art. 26 (signature qualifiée) et art. 42 (horodatage qualifié), - RFC 3161 (Time-Stamp Protocol), - RGPD (minimisation des données).

2. Périmètre / Hors périmètre

Inclus

  • Automatisation de la destruction définitive des documents éligibles (base + objet S3).
  • Fusion dans un même pipeline des documents expirés avec ou sans historique legal_lock, sous réserve d'éligibilité complète.
  • Génération d'un bordereau consolidé par batch, au format PDF/A, signé électroniquement et horodaté RFC 3161.
  • Traçabilité unitaire en audit log avec référence obligatoire au bordereau.
  • Conservation sans limite de durée des bordereaux.
  • Endpoint d'administration pour consultation des bordereaux (filtre date, batch), restreint aux rôles habilités ADMIN.
  • Notification de préavis avant destruction automatique.

Exclu

  • Modification des durées légales de rétention existantes.
  • Restauration d'un document détruit.
  • Refonte de la destruction manuelle utilisateur déjà existante.
  • Migration rétroactive des destructions historiques antérieures à la mise en service.
  • Zeroization cryptographique pour les destructions post-rétention standard (hors documents legal_lock) : hors périmètre.

3. Définitions

  • Document éligible à destruction : document satisfaisant simultanément les conditions d'éligibilité définies en section 4.
  • Batch de destruction : ensemble des documents traités dans un run unique du job, associé à un identifiant unique de batch (batchId, UUID).
  • Bordereau de destruction : preuve consolidée du batch, en PDF/A signé et horodaté RFC 3161.
  • Traçabilité unitaire : entrée d'audit par document détruit, liée à l'identifiant du bordereau.
  • Fail-closed : en cas d'échec de prérequis probatoire (signature, horodatage, intégrité), aucune destruction physique n'est autorisée.
  • Convergence WORM : état où les contraintes de rétention DB et S3 Object Lock sont toutes expirées.
  • Flux legal_lock : un document appartient au flux legal_lock si un legal_lock lui a été assigné à un moment quelconque de son cycle de vie, qu'il soit actif ou expiré au moment de la destruction. Ce critère détermine l'obligation de zeroization cryptographique (cf. INV-250-12).
  • Données personnelles directes (liste fermée) : nom, prénom, email, adresse postale, numéro de téléphone, numéro de sécurité sociale, et toute donnée permettant l'identification directe d'une personne physique.
  • Champs autorisés dans le bordereau : batchId, horodatage run, documentId technique, type documentaire, hash probatoire, date scellement, date expiration, date destruction prévue.

4. Invariants (non négociables)

ID Règle Justification
INV-250-01 Un document est destructible uniquement si rétention DB expirée ET rétention S3 Object Lock expirée ET (legal_lock absent OU expiré). Conformité WORM + RGPD + sécurité juridique
INV-250-02 Aucun document SEALED ou PENDING ne peut être ciblé. Protection WORM
INV-250-03 Aucune destruction physique (DB/S3) sans bordereau de batch signé + horodaté valide. Fail-closed, ISO 14641:2018 §11.4, NF Z42-013:2020 §9.2
INV-250-04 Un batch produit exactement un bordereau consolidé. Exigence métier OBJ-03
INV-250-05 Chaque destruction unitaire génère un audit log liant documentId, batchId, bordereauId. L'audit est mesurable : non-perte (tout événement émis est persisté via transaction ACID, cf. §10.4b), ordre causal (timestamps monotones croissants par document, garantis par une séquence PostgreSQL audit_seq incrémentale utilisée comme clé d'ordonnancement — l'horloge système n'est PAS le mécanisme de monotonie), complétude (exactement une entrée par document traité, incluant les documents en RECONCILIATION_FAILED avec type d'événement correspondant, cf. §10.5). Traçabilité complète
INV-250-06 Les bordereaux sont conservés indéfiniment : aucune date d'expiration de rétention assignée (retentionExpiry absent ou null). Ils ne sont jamais éligibles à la destruction automatique. Preuve permanente NF Z42-013:2020 §9.2
INV-250-07 Le contenu du bordereau exclut les données personnelles directes (cf. §3, liste fermée); seuls les champs autorisés (cf. §3) sont inclus. Résolution TENSION-01, RGPD
INV-250-08 Le job est idempotent : un document déjà marqué DESTROYED ne peut jamais être retraité. L'identité d'un batch est son batchId (UUID). L'idempotence repose sur le statut DESTROYED comme marqueur terminal (pas sur un TTL de rejeu). Robustesse opérationnelle
INV-250-09 En échec TSA persistant après tsaRetryCount tentatives (défaut 3, configurable en §10.2), le batch est en échec bloquant et aucune destruction n'est exécutée. Décision PO Q-04
INV-250-10 Toute erreur partielle est observable (audit + alerte) et reprise possible sans corruption d'état. Échec silencieux = non conforme. Non-silence des échecs
INV-250-11 Les transitions inverses sont interdites : DESTROYED→EXPIRED, EXPIRED→SEALED, SEALED→PENDING, DESTROYED→SEALED. Irréversibilité légale
INV-250-12 La destruction cryptographique (PD-81) est obligatoire uniquement pour documents du flux legal_lock; hors flux legal_lock, suppression physique seule. Résolution TENSION-03
INV-250-13 Les noms de queue BullMQ ne contiennent pas :. Compatibilité conventions existantes
INV-250-14 Les API BullMQ dépréciées (getRepeatableJobs, removeRepeatableByKey) sont interdites. Seules getJobSchedulers/removeJobScheduler sont autorisées. Conformité BullMQ v5
INV-250-15 L'endpoint admin bordereaux est restreint au rôle ADMIN. Toute requête sans habilitation est rejetée avec code d'erreur explicite et trace d'audit. Sécurité, contrôle d'accès
INV-250-16 Les SLA temporels (batchFinalizeSla, destructionExecutionSla, reconciliationSla) sont contractuels : tout dépassement déclenche le comportement spécifié en §10.3 (respectivement batch FAILED, batch PARTIAL_FAILED, RECONCILIATION_FAILED). Observabilité, conformité opérationnelle

5. Flux nominaux

5.1 Sélection éligible

Le job identifie les documents candidats selon INV-250-01, dans la limite du batchSize configuré. La sélection d'éligibilité applique clockSkewTolerance comme marge de sécurité soustractive : un document n'est considéré éligible que si sa date d'expiration + clockSkewTolerance est strictement inférieure à la date courante. Cette règle s'applique aux trois contrôles d'éligibilité (rétention DB, S3 Object Lock, legal_lock). La clockSkewTolerance ne s'applique PAS à la validation du jeton TSA (§5.3) : la vérification du jeton TSA utilise la tolérance horaire intégrée au protocole RFC 3161 (champ accuracy du jeton). La désynchronisation horloge applicatif/TSA est couverte par HYP-250-01 et l'attribut accuracy du jeton.

5.2 Prévalidation probatoire batch

Le système prépare le bordereau consolidé du batch avec les champs autorisés (cf. §3) : batchId, horodatage run, liste {documentId technique, type documentaire, hash probatoire, date scellement, date expiration, date destruction prévue}. Les données personnelles directes (cf. §3, liste fermée) sont interdites.

5.3 Scellement probatoire du bordereau

Le bordereau est produit en PDF/A, signé électroniquement par un service de signature qualifié (eIDAS art. 26) puis horodaté par un TSA qualifié (eIDAS art. 42, RFC 3161).

5.4 Validation fail-closed

Si signature/horodatage invalides ou absents, arrêt du batch sans destruction physique.

5.5 Destruction unitaire post-validation (ordonnancement en deux temps)

La suppression est orchestrée dans le même job BullMQ, document par document de manière séquentielle. La phase de suppression S3 démarre uniquement après validation complète du bordereau (pas pendant). Le pattern est séquentiel par document (pas de fire-and-forget). Le délai entre la validation du bordereau (§5.4) et le début de la destruction du premier document est borné par le SLA destructionExecutionSla (§10.3). Si ce SLA est dépassé avant le traitement du premier document, le batch passe en FAILED (pas PARTIAL_FAILED, car aucune destruction n'a eu lieu).

Pour chaque document du batch : 1. Suppression S3 : await sur l'opération de suppression (DeleteObject), avec retry contrôlé selon s3DeleteRetryCount. 2. Confirmation S3 : la confirmation est définie comme la réception d'un code HTTP 204 (No Content) de l'opération DeleteObject. S3 (OVH Object Storage) est eventually consistent — un objet peut rester temporairement lisible après un 204. Cette persistance physique résiduelle est un risque accepté (cf. §10.6). La confirmation 204 est suffisante pour autoriser la finalisation DB. 3. Finalisation DB synchrone par unité : suppression de la référence DB et marquage final DESTROYED, uniquement après confirmation S3 (HTTP 204). L'audit log est inséré dans la même transaction DB (cf. §10.4b).

Si un document devient non éligible entre la sélection et son traitement unitaire (ex: re-scellement d'urgence → SEALED), le document est exclu de la destruction avec audit d'anomalie, et le batch continue sans lui (cf. ERR-250-03).

Pour les documents du flux legal_lock (cf. §3, définition), la séquence de destruction est strictement ordonnancée : 1. Zeroization cryptographique (PD-81) : await sur la confirmation de zeroization. 2. Suppression S3 : uniquement après confirmation de zeroization réussie. 3. Finalisation DB : après confirmation S3 (HTTP 204). Si la zeroization échoue, le document n'est PAS supprimé de S3 (fail-closed). Cette séquence garantit l'auditabilité de la zeroization avant la disparition physique de l'objet.

5.6 Journalisation unitaire

Écriture d'un audit log par document avec référence du bordereau. L'audit respecte les propriétés mesurables : non-perte, ordre causal, complétude (cf. INV-250-05).

5.7 Conservation du bordereau

Le bordereau est stocké en tant que document probatoire à conservation indéfinie (retentionExpiry absent/null, cf. INV-250-06). La protection physique du bordereau est assurée par : (1) la protection WORM PostgreSQL (triggers SECURITY DEFINER existants, empêchant modification/suppression), (2) le statut SEALED sans date d'expiration (jamais éligible à la destruction automatique), (3) Object Lock COMPLIANCE sur S3 avec rétention maximale supportée par le provider (configuration d'exploitation, cf. HYP-250-04).

5.8 Notification de préavis

Le préavis de destruction est émis comme événement applicatif sur le bus d'événements interne. Le contenu est limité aux identifiants techniques : documentId, date d'éligibilité prévue, preNoticeDays. Le destinataire direct est le bus d'événements ; le routage vers les canaux finaux (email, webhook) est hors périmètre de cette story (cf. HYP-250-08).

Déclencheur : le préavis est émis par un job BullMQ dédié de préavis (distinct du job de destruction), exécuté quotidiennement. Il sélectionne les documents dont la date d'éligibilité est à J+N (avec N = preNoticeDays).

Cas N=0 : avec preNoticeDays=0, le préavis est émis le jour même de l'éligibilité, avant le run du job de destruction (le job de préavis s'exécute en premier dans la séquence). Le préavis N=0 a valeur de notification informative « jour J », pas de délai de préavis effectif. L'intervalle entre préavis et destruction est la différence de scheduling entre les deux jobs (typiquement quelques heures, configurable).

5.9 Machine à états du batch et reprise

États d'un batch : PENDINGRUNNING → (SUCCESS | PARTIAL_FAILED | FAILED).

  • Les états SUCCESS, PARTIAL_FAILED, FAILED sont finaux pour le batch courant : aucune transition retour n'est autorisée (un batch FAILED ne peut jamais devenir SUCCESS). Le terme « terminal » signifie que le batch lui-même ne change plus d'état. Il ne signifie PAS que les documents non détruits sont abandonnés.
  • Reprise après PARTIAL_FAILED : la reprise crée un nouveau batch (nouveau batchId) qui sélectionne uniquement les documents encore non-DESTROYED du batch d'origine. Le batch d'origine reste en PARTIAL_FAILED (pas de modification rétroactive). La traçabilité de la filiation est assurée par un champ parentBatchId obligatoire dans l'audit log du nouveau batch, référençant le batchId d'origine. Ce champ est absent (null) pour les batches initiaux (sans parent).
  • Reprise après FAILED : idem, nouveau batch avec parentBatchId obligatoire. Un batch FAILED avant toute destruction ne produit que des documents non-DESTROYED, tous reprisables.

5.10 Publication de résultat batch

À la fin de chaque batch, l'état final est publié avec métriques agrégées (nombre de documents traités/détruits/en erreur, durée totale) et alertes (si erreurs). Les métriques sont publiées sur le bus d'événements interne avec restriction d'accès : seuls les consumers avec rôle ADMIN ou SYSTEM peuvent consommer les événements de type batch_result. Le contenu des métriques exclut les identifiants de documents individuels (seuls les compteurs agrégés sont publiés).

5bis. Diagrammes Mermaid

5bis.1 Machine à états — Document (INV-250-11, §10.5)

stateDiagram-v2
    [*] --> PENDING
    PENDING --> SEALED : scellement probatoire
    SEALED --> EXPIRED : rétention DB + S3 expirées
    EXPIRED --> DESTROYED : destruction confirmée (S3 204 + finalisation DB)
    EXPIRED --> RECONCILIATION_FAILED : échec réconciliation post-crash (ERR-250-05)

    RECONCILIATION_FAILED --> [*] : état terminal — résolution manuelle uniquement
    DESTROYED --> [*] : état terminal

    note right of PENDING : INV-250-02 — PENDING\nne peut être ciblé\npar la destruction
    note right of SEALED : INV-250-02 — SEALED\nne peut être ciblé\npar la destruction
    note left of RECONCILIATION_FAILED : S3 supprimé mais\nfinalisation DB échouée\naprès reconciliationDbRetryCount retries

    %% Transitions inverses INTERDITES (INV-250-11)
    %% DESTROYED → EXPIRED : INTERDITE
    %% DESTROYED → SEALED : INTERDITE
    %% EXPIRED → SEALED : INTERDITE
    %% SEALED → PENDING : INTERDITE
    %% RECONCILIATION_FAILED → * : INTERDITE

5bis.2 Machine à états — Batch (§5.9)

stateDiagram-v2
    [*] --> PENDING : création batch (batchId UUID)
    PENDING --> RUNNING : démarrage job BullMQ
    RUNNING --> SUCCESS : tous documents détruits
    RUNNING --> PARTIAL_FAILED : au moins un document en échec (ERR-250-03, ERR-250-04)
    RUNNING --> FAILED : échec bloquant (ERR-250-01, ERR-250-02, ERR-250-06, INV-250-09)

    SUCCESS --> [*] : état final
    PARTIAL_FAILED --> [*] : état final — reprise via nouveau batch (parentBatchId)
    FAILED --> [*] : état final — reprise via nouveau batch (parentBatchId)

    note right of FAILED : INV-250-03 — aucune\ndestruction si bordereau\nnon validé
    note left of PARTIAL_FAILED : Reprise crée un nouveau\nbatch avec parentBatchId\nobligatoire (§5.9)

5bis.3 Séquence — Destruction nominale d'un batch (§5.1→§5.7)

sequenceDiagram
    autonumber
    participant Job as Job BullMQ<br/>(destruction)
    participant DB as PostgreSQL
    participant S3 as OVH S3<br/>(Object Storage)
    participant Sign as Service Signature<br/>(eIDAS art. 26)
    participant TSA as TSA qualifié<br/>(RFC 3161)
    participant Bus as Bus événements

    Note over Job,DB: §5.1 — Sélection éligible (INV-250-01)
    Job->>DB: SELECT documents éligibles<br/>(rétention DB + S3 expirées, legal_lock absent/expiré)<br/>clockSkewTolerance appliquée
    DB-->>Job: liste candidats (≤ batchSize)

    Note over Job,Sign: §5.2–§5.3 — Prévalidation + scellement probatoire
    Job->>Job: génération bordereau PDF/A<br/>(champs autorisés §3, INV-250-07)
    Job->>Sign: signature qualifiée du bordereau
    Sign-->>Job: bordereau signé
    Job->>TSA: horodatage RFC 3161
    TSA-->>Job: jeton TSA

    Note over Job: §5.4 — Validation fail-closed (INV-250-03)
    alt signature/horodatage invalide
        Job->>DB: batch → FAILED, aucune destruction
    end

    Note over Job,S3: §5.5 — Destruction unitaire post-validation
    loop pour chaque document du batch (séquentiel)
        Job->>S3: DeleteObject (await, retry ≤ s3DeleteRetryCount)
        S3-->>Job: HTTP 204 (confirmation)
        Job->>DB: BEGIN transaction
        Job->>DB: suppression référence + marquage DESTROYED
        Job->>DB: INSERT audit log (documentId, batchId, bordereauId) — INV-250-05
        Job->>DB: COMMIT
    end

    Note over Job,DB: §5.7 — Conservation bordereau (INV-250-06)
    Job->>DB: persistance bordereau (retentionExpiry = null)
    Job->>S3: stockage bordereau (Object Lock COMPLIANCE)

    Note over Job,Bus: §5.10 — Publication résultat
    Job->>Bus: événement batch_result<br/>(métriques agrégées, accès ADMIN/SYSTEM)
sequenceDiagram
    autonumber
    participant Job as Job BullMQ
    participant Crypto as Zeroization<br/>(PD-81)
    participant S3 as OVH S3
    participant DB as PostgreSQL

    Note over Job: Document du flux legal_lock détecté<br/>(INV-250-12 — zeroization obligatoire)

    Job->>Crypto: zeroization cryptographique (await)
    alt zeroization échouée
        Crypto-->>Job: échec
        Note over Job,S3: fail-closed — document NON supprimé de S3
        Job->>DB: audit anomalie zeroization
    else zeroization réussie
        Crypto-->>Job: confirmation
        Job->>S3: DeleteObject (await)
        S3-->>Job: HTTP 204
        Job->>DB: BEGIN transaction
        Job->>DB: suppression référence + DESTROYED
        Job->>DB: INSERT audit log (documentId, batchId, bordereauId)
        Job->>DB: COMMIT
    end

6. Cas d'erreur

  • ERR-250-01 — TSA indisponible/timeout : 3 tentatives, puis FAILED; destruction interdite.
  • ERR-250-02 — Signature invalide : FAILED; destruction interdite.
  • ERR-250-03 — Document non éligible détecté en cours de run : document exclu, événement d'audit d'anomalie, batch continue sans ce document. L'état final du batch est PARTIAL_FAILED (car au moins un document sélectionné n'a pas été détruit). Un document exclu pour ERR-250-03 conserve son état courant (ex: SEALED si re-scellé) et n'est pas comptabilisé comme « détruit ».
  • ERR-250-04 — S3 injoignable après prévalidation : document en échec unitaire, batch PARTIAL_FAILED, reprise idempotente obligatoire.
  • ERR-250-05 — Échec suppression DB après suppression S3 : anomalie critique, traçabilité obligatoire. Réconciliation vers état terminal contractuel : DESTROYED si S3 confirmé supprimé et DB nettoyée, RECONCILIATION_FAILED si DB échoue après reconciliationDbRetryCount retries (escalade obligatoire). Délai borné par reconciliationSla.
  • ERR-250-06 — Bordereau non persistant : rollback logique du batch, aucune destruction autorisée.
  • ERR-250-07 — Échec silencieux interdit : absence d'audit/alerte = non conforme. Si chaîne d'audit indisponible, arrêt fail-closed du job + alerte immédiate.
  • ERR-250-08 — Dépassement de bornes de configuration : rejet de configuration au démarrage du job, aucun traitement, alerte.

7. Critères d'acceptation (testables)

ID Critère Observable
CA-250-01 Le job ne détruit que des documents satisfaisant toutes les conditions d'éligibilité. Journal d'exécution + audit des filtres
CA-250-02 Un batch réussi génère exactement un bordereau PDF/A signé+horodaté valide. Artefact bordereau + vérification signature/TSA
CA-250-03 Aucune destruction n'a lieu si le bordereau n'est pas validé. Zéro transition DESTROYED en cas d'échec probatoire
CA-250-04 Chaque document détruit a une trace d'audit unitaire liée au bordereau, respectant non-perte, ordre causal et complétude. Audit log corrélé documentId/batchId/bordereauId
CA-250-05 Les bordereaux restent accessibles sans limite temporelle (retentionExpiry absent/null, non ciblés par le job). Lecture API admin sur bordereaux historiques + absence de sélection
CA-250-06 Les données personnelles directes (cf. §3 liste fermée) ne figurent pas dans le bordereau. Contrôle de schéma bordereau vs liste fermée
CA-250-07 Le retry TSA est de tsaRetryCount tentatives max (défaut 3, cf. §10.2), puis arrêt fail-closed. Logs retry + statut batch FAILED
CA-250-08 Le traitement est idempotent : un document DESTROYED n'est jamais retraité. Absence de double destruction/audit doublon interdit
CA-250-09 Les documents avec legal_lock actif ne sont jamais détruits. Tests de sélection
CA-250-10 Endpoint admin retourne les bordereaux filtrables par date et batch. Réponse API conforme aux filtres
CA-250-11 Préavis N jours est émis avant destruction automatique (y compris N=0 = jour J avant exécution). Traces notification horodatées
CA-250-12 Les transitions inverses (DESTROYED→EXPIRED, EXPIRED→SEALED, SEALED→PENDING, DESTROYED→SEALED) sont rejetées. Tentatives de rollback en erreur explicite
CA-250-13 Les noms de queue BullMQ ne contiennent pas :. Test contractuel de configuration
CA-250-14 Les API BullMQ dépréciées sont absentes du code. Seules getJobSchedulers/removeJobScheduler sont utilisées. Scan statique CI
CA-250-15 L'endpoint admin bordereaux est accessible uniquement au rôle ADMIN. Requête non autorisée → rejet 403 + trace d'audit. Test d'accès refusé
CA-250-16 Le dépassement de chaque SLA temporel (§10.3) déclenche le comportement contractualisé : batchFinalizeSlaFAILED, destructionExecutionSlaPARTIAL_FAILED, reconciliationSlaRECONCILIATION_FAILED. Statut batch/document après timeout

8. Scénarios de test (Given / When / Then)

  • ST-250-01 — Batch nominal : Given des documents éligibles complets. When le job s'exécute. Then un bordereau valide est généré, les documents passent à DESTROYED, et chaque trace unitaire référence le bordereau.

  • ST-250-02 — TSA en échec persistant : Given des documents éligibles et TSA indisponible. When le job tente la signature/horodatage 3 fois. Then le batch est FAILED et aucun document n'est détruit.

  • ST-250-03 — legal_lock actif : Given un document avec legal_lock non expiré. When le job filtre les candidats. Then le document est exclu avec trace d'exclusion.

  • ST-250-04 — Rétention S3 non expirée : Given rétention DB expirée mais S3 Object Lock actif. When le job évalue l'éligibilité. Then destruction refusée, document maintenu hors DESTROYED.

  • ST-250-05 — Reprise idempotente après panne partielle : Given panne S3 pendant un batch partiellement traité. When le job est relancé. Then seuls les documents non convergés sont retraités sans doublon.

  • ST-250-06 — Contrôle RGPD du bordereau : Given un bordereau produit. When son contenu est inspecté. Then aucune donnée personnelle directe (cf. §3) n'est présente, uniquement les champs probatoires autorisés.

  • ST-250-07 — Flux legal_lock expiré : Given un document avec legal_lock expiré et autres verrous expirés. When le job exécute la destruction. Then la destruction inclut l'étape cryptographique obligatoire et la trace associée.

  • ST-250-08 — Transition inverse interdite : Given un document DESTROYED. When une transition vers EXPIRED ou SEALED est demandée. Then la requête est rejetée avec erreur métier.

  • ST-250-09 — Endpoint admin non autorisé : Given un utilisateur sans rôle ADMIN. When il appelle l'endpoint de consultation des bordereaux. Then accès refusé (403), aucun contenu renvoyé, trace d'audit.

  • ST-250-10 — Configuration hors bornes : Given une configuration avec paramètre hors bornes. When le job démarre. Then erreur de validation, aucun traitement, alerte.

9. Hypothèses explicites

ID Hypothèse Impact si faux
HYP-250-01 Les horloges systèmes sont synchronisées (tolérance max définie en §10.2). Invalidité de fenêtres SLA et timestamps probatoires
HYP-250-02 Le service TSA est joignable sur la fenêtre de job. Batchs en échec fail-closed répétés
HYP-250-03 Les métadonnées probatoires minimales (hash, dates, type) existent pour chaque document. Document non destructible automatiquement
HYP-250-04 Le stockage des bordereaux dispose d'une politique de conservation indéfinie effective (retentionExpiry absent/null). Non-conformité NF Z42-013:2020 §9.2
HYP-250-05 Les notifications de préavis disposent d'un canal opérationnel. Préavis non délivré, anomalie de conformité opérationnelle
HYP-250-06 Les contraintes WORM DB et S3 sont vérifiables au moment de la sélection. Risque de faux positifs d'éligibilité
HYP-250-07 Le TSP utilisé pour signature et TSA est qualifié eIDAS (listé UE Trust List). Si faux, destruction non conforme, blocage mise en production. Non-conformité eIDAS, invalidité probatoire
HYP-250-08 Un consumer du bus d'événements existe pour router les préavis de destruction vers les canaux finaux (email, webhook). Ce routage est hors périmètre de cette story. Préavis émis mais non délivré aux utilisateurs finaux

10. Contraintes techniques

10.1 Stack technique cible (obligatoire)

Projet cible : ProbatioVault-backend Stack contractuelle : NestJS + TypeORM + PostgreSQL + BullMQ v5 + S3 (OVH Object Storage)

Toute spécification incompatible avec cette stack est non conforme.

10.2 Paramètres numériques contractualisés

Paramètre Valeur par défaut Min Max Unité Comportement hors bornes
destructionBatchSize 500 1 5000 documents rejet de configuration + alerte
destructionJobInterval 24 1 168 heures rejet de configuration + alerte
preNoticeDays 30 0 365 jours rejet de configuration + alerte
tsaRetryCount 3 0 5 tentatives clamp interdit, rejet requis
tsaTimeout 5000 1000 30000 ms rejet de configuration + alerte
signatureTimeout 10000 1000 60000 ms rejet de configuration + alerte
s3DeleteRetryCount 5 0 10 tentatives rejet de configuration + alerte
s3DeleteTimeout 10000 1000 60000 ms rejet de configuration + alerte
clockSkewTolerance 5 1 60 secondes rejet de configuration + alerte
reconciliationDbRetryCount 3 1 10 tentatives rejet de configuration + alerte

10.3 SLA temporels contractuels

Paramètre Valeur par défaut Borne minimale Borne maximale Configurabilité Comportement à expiration
Préavis destruction (preNoticeDays) 30j 0j 365j via configuration notification émise puis éligibilité inchangée
Fenêtre max de finalisation d'un batch (batchFinalizeSla) 2h 5min 24h via configuration batch FAILED + alerte critique
Délai max de réconciliation post-crash (reconciliationSla) 24h 1h 168h via configuration RECONCILIATION_FAILED + escalade critique
Délai max entre bordereau validé et destruction unitaire (destructionExecutionSla) 30min 1min 24h via configuration batch PARTIAL_FAILED + reprise

10.4 Atomicité multi-composant

Scope Synchrone/Async Garantie
Validation d'éligibilité + préparation bordereau Synchrone Cohérence de sélection
Signature + horodatage bordereau Synchrone Précondition bloquante (fail-closed)
Suppression S3 Async post-validation Idempotent, retry-safe (cf. §5.5 ordonnancement deux temps)
Finalisation DB / marquage DESTROYED Synchrone par unité, après confirmation S3 Atomicité unitaire (cf. §5.5)
Audit log unitaire Transactionnel : inséré dans la même transaction DB que la finalisation DESTROYED (cf. §10.4b) Non-perte, ordre causal, complétude
Crash pré-validation bordereau Aucun document détruit
Crash post-validation et en cours de destruction Reprise par réconciliation vers état terminal contractuel (cf. ERR-250-05)

10.4b Mécanisme de non-perte audit log (contractuel)

Le mécanisme de non-perte est garanti par écriture transactionnelle dans la même transaction DB que la finalisation de l'état DESTROYED. L'audit log est inséré avant le commit de transition d'état. En cas d'échec de la transaction, ni l'état ni l'audit ne sont persistés (atomicité ACID). Ce mécanisme élimine l'ambiguïté sync/async pour l'audit.

10.5 Modèle d'états et transitions

États d'un document : PENDING, SEALED, EXPIRED, DESTROYED, RECONCILIATION_FAILED.

  • Transitions nominales : PENDING → SEALED → EXPIRED → DESTROYED.
  • Transition de réconciliation : EXPIRED → RECONCILIATION_FAILED (uniquement en cas d'échec de réconciliation post-crash, cf. ERR-250-05). RECONCILIATION_FAILED est un état terminal de document (pas de batch). Un document en RECONCILIATION_FAILED a été supprimé physiquement sur S3 mais la finalisation DB a échoué après reconciliationDbRetryCount retries. C'est un état d'anomalie nécessitant une escalade obligatoire.
  • Transitions retour (toutes INTERDITES, alignées avec INV-250-11) :
  • SEALED → PENDING : INTERDITE
  • EXPIRED → SEALED : INTERDITE
  • DESTROYED → EXPIRED : INTERDITE
  • DESTROYED → SEALED : INTERDITE
  • RECONCILIATION_FAILED → * : INTERDITE (état terminal, résolution manuelle uniquement)
  • Toute tentative de transition inverse doit échouer explicitement et être auditée.

Complétude audit pour RECONCILIATION_FAILED : un document en RECONCILIATION_FAILED DOIT avoir une entrée d'audit de type RECONCILIATION_FAILED (pas DESTROYED). L'invariant INV-250-05 (complétude = exactement une entrée par document traité) s'applique avec le type d'événement correspondant à l'état terminal effectif.

10.6 Résolution contractuelle des tensions

  • TENSION-01 (granularité bordereau) : le bordereau contient uniquement les champs autorisés (cf. §3) ; aucune donnée personnelle directe (cf. §3, liste fermée).
  • TENSION-02 (DB vs S3 convergence) : stratégie de convergence stricte; DESTROYED uniquement après expiration des deux rétentions et destruction effective des deux supports. Réconciliation vers état terminal contractuel (cf. ERR-250-05).
  • TENSION-03 (zeroization) : obligatoire pour flux legal_lock (cf. §3, définition); hors flux legal_lock, suppression physique seule (zeroization hors périmètre).
  • Risque résiduel accepté : après suppression logique S3, la persistance physique résiduelle sur les supports du provider (OVH) est acceptée. La zeroization cryptographique (INV-250-12) couvre les documents à fort enjeu juridique (flux legal_lock). Pour les documents standard, le risque est considéré acceptable au regard du rapport coût/bénéfice. Cette décision est traçable dans le besoin PD-250.

11. Références normatives

  • ISO 14641:2018 §11.4 — Exigences de traçabilité et preuve des opérations de destruction.
  • NF Z42-013:2020 §9.2 — Exigences relatives aux journaux, intégrité et auditabilité probatoire.
  • Règlement eIDAS (UE) n°910/2014 art. 26 (signature électronique qualifiée), art. 42 (horodatage qualifié).
  • RFC 3161 — Time-Stamp Protocol (champs obligatoires du jeton TSA).
  • RGPD (UE) 2016/679 — Minimisation des données (art. 5.1.c).

Références projet

  • Epic : PD-217 LEGAL & COMPLIANCE
  • JIRA : PD-250
  • Repos concernés : ProbatioVault-backend
  • Documents associés : PD-250-besoin.md