PD-250 — Décomposition en tâches agents — Job destruction définitive et bordereau¶
1. Matrice des dépendances¶
| ID | Agent | Description | Produit | Consomme | Dépend de | Niveau |
|---|---|---|---|---|---|---|
| T1 | agent-developer | Configuration Joi (13 params + 3 SLA + preNoticeJobInterval) | config/destruction.config.ts, constantes queues | — | [] | 0 |
| T8 | agent-developer | Machine à états documents (5 transitions interdites) | services/document-state-machine.service.ts | — | [] | 0 |
| T13 | agent-developer | Migrations DDL (enum, had_legal_lock, tables, séquence) | Tables DB, enum étendu, audit_destruction_seq | — | [] | 0 |
| T2 | agent-developer | Service d'éligibilité (triple condition WORM) | services/eligibility.service.ts | Entities DB (T13), DocumentSecure | [T13] | 1 |
| T6 | agent-developer | Service d'audit transactionnel (audit_destruction_seq) | services/destruction-audit.service.ts | Séquence audit_destruction_seq (T13) | [T13] | 1 |
| T9 | agent-developer | Service de zeroization document (flux legal_lock) | services/document-zeroization.service.ts | Colonne had_legal_lock (T13) | [T13] | 1 |
| T7 | agent-developer | Service d'alertes et métriques batch | services/destruction-alert.service.ts, events/destruction.events.ts | — | [T6] | 2 |
| T3 | agent-developer | Service de génération du bordereau (PDF/A + sig + TSA) | services/bordereau.service.ts, entities/destruction-bordereau.entity.ts | EligibilityService (T2) | [T2, T13] | 2 |
| T4 | agent-developer | Service d'exécution de destruction séquentielle | services/destruction-execution.service.ts | Eligibility (T2), Audit (T6), Zeroization (T9), Bordereau (T3), Alert (T7), StateMachine (T8) | [T2, T3, T6, T7, T8, T9] | 3 |
| T5 | agent-developer | Service de réconciliation post-crash | services/reconciliation.service.ts | Audit (T6), Alert (T7), StateMachine (T8) | [T6, T7, T8] | 3 |
| T10 | agent-developer | Contrôleur admin bordereaux (GET /admin/bordereaux) | controllers/bordereau.controller.ts, DTOs | Bordereau entity (T3), Audit (T6) | [T3, T6] | 3 |
| T11 | agent-developer | Processor préavis BullMQ (quotidien) | processors/pre-notice.processor.ts, events/pre-notice.events.ts | Eligibility (T2), Config (T1) | [T1, T2] | 2 |
| T12 | agent-developer | Processor principal destruction BullMQ | processors/destruction.processor.ts | Execution (T4), Bordereau (T3), Alert (T7), Config (T1), Reconciliation (T5) | [T1, T3, T4, T5, T7] | 4 |
| T15 | agent-developer | Module NestJS principal (wiring) | destruction.module.ts, enums/*.ts | Tous les services et processors | [T1..T12] | 5 |
| T14 | agent-qa-unit-integration | Tests contractuels transversaux | __tests__/contractual/*.spec.ts | Tous les fichiers produits | [T1..T13, T15] | 6 |
| T16 | agent-adversarial | Review sécurité (fail-closed, PII, timing) | Rapport de vulnérabilités | Tous les fichiers produits | [T15] | 6 |
2. Bloc de parallélisation¶
parallelization:
strategy: by_level
levels:
- level: 0
tasks: [1, 8, 13]
agents: [agent-developer, agent-developer, agent-developer]
branches: ["feature/PD-250-l0-config", "feature/PD-250-l0-state-machine", "feature/PD-250-l0-migrations"]
estimated_time: "2h"
- level: 1
tasks: [2, 6, 9]
agents: [agent-developer, agent-developer, agent-developer]
branches: ["feature/PD-250-l1-eligibility", "feature/PD-250-l1-audit", "feature/PD-250-l1-zeroization"]
estimated_time: "2.5h"
- level: 2
tasks: [3, 7, 11]
agents: [agent-developer, agent-developer, agent-developer]
branches: ["feature/PD-250-l2-bordereau", "feature/PD-250-l2-alerts", "feature/PD-250-l2-prenotice"]
estimated_time: "3h"
- level: 3
tasks: [4, 5, 10]
agents: [agent-developer, agent-developer, agent-developer]
branches: ["feature/PD-250-l3-execution", "feature/PD-250-l3-reconciliation", "feature/PD-250-l3-admin-api"]
estimated_time: "3h"
- level: 4
tasks: [12]
agents: [agent-developer]
branches: ["feature/PD-250-l4-processor"]
estimated_time: "2.5h"
- level: 5
tasks: [15]
agents: [agent-developer]
branches: ["feature/PD-250-l5-module-wiring"]
estimated_time: "1h"
- level: 6
tasks: [14, 16]
agents: [agent-qa-unit-integration, agent-adversarial]
branches: ["feature/PD-250-l6-contractual-tests", "feature/PD-250-l6-security-review"]
estimated_time: "2h"
total_sequential_time: "22h"
total_parallel_time: "16h"
speedup_factor: 1.37
git_strategy: branch_per_level
Note : Le speedup est modéré (1.37x) car le DAG a une profondeur de 7 niveaux avec peu de largeur au-delà du niveau 3. La stratégie
branch_per_levelest pertinente pour limiter la complexité de merge (6 merges vs 16 merges avecbranch_per_task).
3. Détail de chaque tâche¶
Tâche 1 — Configuration et validation Joi¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract :
destruction-config - Fichiers :
src/modules/destruction/config/destruction.config.tssrc/modules/destruction/__tests__/destruction.config.spec.ts- Description : Implémenter la validation Joi stricte pour les 14 paramètres numériques (13 originaux +
preNoticeJobIntervalajouté pour MAJ-02) et les 3 SLA temporels. Utiliser le patternregisterAs()existant (cf.legal-pre.config.ts). Définir les constantes de noms de queue (pv-jobs-destruction,pv-jobs-prenotice) sans caractère:. Options Joi :abortEarly: false,allowUnknown: false,stripUnknown: false. Rejet strict (pas de clamp). - Réserve Gate 5 intégrée :
- MAJ-02 : Ajouter
preNoticeJobInterval(défaut 24h, min 1h, max 168h) comme variable dédiée distincte dedestructionJobInterval. Variable env :DESTRUCTION_PRE_NOTICE_JOB_INTERVAL. - Tests : TC-250-18 (queue names), TC-250-23 (config hors bornes, échantillonnage MIN-15 : 3 params × bornes min+max)
- Décision architecturale :
- Choix :
registerAs()+ fichier constantes dédié (pas de Joi global) - Pourquoi : Cohérent avec le pattern
legal-pre.config.tsexistant. La validation globale (config.schema.ts) est pour l'infra (DB, Redis), pas pour les modules fonctionnels. - Trade-off : Pas de fail-fast au boot pour les params destruction (validation au premier accès via
ConfigService.get). Mitigation : appelervalidate()dans leonModuleInit()du module.
Tâche 2 — Service d'éligibilité¶
- Agent : agent-developer
- Niveau : 1
- Dépend de : [T13]
- Contract :
destruction-eligibility - Fichiers :
src/modules/destruction/services/eligibility.service.tssrc/modules/destruction/__tests__/eligibility.service.spec.ts- Description : Implémenter la sélection des documents éligibles (triple condition WORM + clockSkewTolerance soustractive), l'exclusion des bordereaux (MIN-13), la sélection de préavis (J+N), et la re-vérification unitaire (
SELECT ... FOR UPDATE). La query utiliseDocumentSecureexistant (PD-63). Tracer les motifs d'exclusion par document. - Tests : TC-250-01, TC-250-02, TC-250-03, TC-250-10, TC-250-12
- Décision architecturale :
- Choix : QueryBuilder TypeORM avec paramètres bindés (pas de raw SQL)
- Pourquoi : Sécurité injection SQL + testabilité avec mocks TypeORM. Alternative raw SQL plus performante mais non nécessaire (batchSize max 5000, filtres indexés).
- Trade-off : Moins de contrôle sur le plan d'exécution PostgreSQL. Mitigation : index
idx_documents_had_legal_locket index existant surstatus.
Tâche 3 — Service de génération du bordereau¶
- Agent : agent-developer
- Niveau : 2
- Dépend de : [T2, T13]
- Contract :
destruction-bordereau - Fichiers :
src/modules/destruction/services/bordereau.service.tssrc/modules/destruction/entities/destruction-bordereau.entity.tssrc/modules/destruction/__tests__/bordereau.service.spec.ts- Description : Générer un bordereau PDF/A consolidé par batch avec uniquement les champs autorisés (§3, pas de PII), signer via HSM (PD-36), horodater via TSA RFC 3161 (PD-39) avec retry ≤
tsaRetryCount, valider signature+timestamp (fail-closed), persister en S3 (Object Lock COMPLIANCE) + DB avecretentionExpiry = null. - Dépendance externe nouvelle :
pdf-lib(CJS compatible, HYP-IMPL-05) - Tests : TC-250-04, TC-250-05, TC-250-08, TC-250-08b, TC-250-10, TC-250-11
- Décision architecturale :
- Choix :
pdf-libpour la génération PDF/A - Pourquoi : Compatible CJS (pas de configuration Jest spéciale), API ergonomique pour le format tabulaire, support du standard PDF/A. Alternative
pdfkit: moins de support PDF/A natif. Alternativepuppeteer: overhead de headless Chrome inacceptable pour un job batch. - Trade-off :
pdf-libest principalement un éditeur de PDF, la génération from-scratch est plus verbeuse. Acceptable pour un format tabulaire simple.
Tâche 4 — Service d'exécution de destruction¶
- Agent : agent-developer
- Niveau : 3
- Dépend de : [T2, T3, T6, T7, T8, T9]
- Contract :
destruction-execution - Fichiers :
src/modules/destruction/services/destruction-execution.service.tssrc/modules/destruction/__tests__/destruction-execution.service.spec.ts- Description : Orchestrer la destruction unitaire séquentielle post-validation du bordereau. Boucle
for...of(pasPromise.all— MAJ-25). Pour chaque document : re-vérification éligibilité (ERR-250-03), branchement zeroization sihadLegalLock(INV-250-12, fail-closed MAJ-27), S3DeleteObjectavec retry, confirmation HTTP 204, transaction DB atomique (UPDATE DESTROYED + INSERT audit_log). Gestion SLAdestructionExecutionSla(MAJ-26 : FAILED si dépassé avant 1er doc, PARTIAL_FAILED sinon). Émission d'alerte unitaire pour chaque ERR-250-03/04 (résolution MAJ-05 Gate 5). - Réserve Gate 5 intégrée :
- MAJ-05 : Émettre une alerte unitaire (via
DestructionAlertService) pour chaque document en erreur ERR-250-03 et ERR-250-04, en plus du statut batch global. - Tests : TC-250-06, TC-250-07, TC-250-12, TC-250-17, TC-250-25, TC-250-27
- Décision architecturale :
- Choix : Transaction DB par document (pas de transaction englobante pour tout le batch)
- Pourquoi : Conforme à §10.4 « synchrone par unité, après confirmation S3 ». Un crash mid-batch ne corrompt que le document en cours. Alternative transaction globale : un échec unitaire rollback tout le batch (non conforme PARTIAL_FAILED).
- Trade-off : Plus de commits DB (N transactions vs 1). Acceptable car batchSize ≤ 5000 et chaque commit est rapide.
Tâche 5 — Service de réconciliation¶
- Agent : agent-developer
- Niveau : 3
- Dépend de : [T6, T7, T8]
- Contract :
destruction-reconciliation - Fichiers :
src/modules/destruction/services/reconciliation.service.tssrc/modules/destruction/__tests__/reconciliation.service.spec.ts- Description : Converger vers un état terminal contractuel après crash post-suppression S3. Retry DB avec backoff exponentiel (≤
reconciliationDbRetryCount), vérificationreconciliationSla. Si réussi → DESTROYED + audit DESTROYED. Si échec persistant hors SLA → RECONCILIATION_FAILED + audit de type RECONCILIATION_FAILED (pas DESTROYED) + escalade critique.RECONCILIATION_FAILED → *interdit (MAJ-28). - Tests : TC-250-07, TC-250-13, TC-250-28
Tâche 6 — Service d'audit de destruction¶
- Agent : agent-developer
- Niveau : 1
- Dépend de : [T13]
- Contract :
destruction-audit - Fichiers :
src/modules/destruction/services/destruction-audit.service.tssrc/modules/destruction/__tests__/destruction-audit.service.spec.tssrc/modules/destruction/__tests__/destruction-audit.integration.spec.ts(BLQ-01)- Description : Implémenter l'audit transactionnel avec séquence
audit_destruction_seq(nom aligné MAJ-03) pour garantir non-perte, ordre causal et complétude. MéthodelogDestruction(queryRunner, params)exécutée dans la même transaction que la finalisation DESTROYED (§10.4b). InclureparentBatchIddans l'audit log (résolution MAJ-01). Définir les actions d'audit :DOCUMENT_DESTROY,DOCUMENT_DESTROY_BATCH,DOCUMENT_DESTROY_BORDEREAU,DOCUMENT_DESTROY_RECONCILIATION_FAILED,DOCUMENT_DESTROY_ACCESS_DENIED. MéthodeensureAvailable()pour fail-closed si chaîne d'audit indisponible (ERR-250-07). - Réserves Gate 5 intégrées :
- BLQ-01 : Créer un test d'intégration PostgreSQL réel (
destruction-audit.integration.spec.ts) pour TC-250-16. Le test simule un crash post-suppression S3 / pré-commit DB et vérifie la réconciliation. Ce test nécessiteDATABASE_URLen CI. - MAJ-01 : Ajouter
parentBatchIdcomme champ dans l'audit log (paramètre delogDestruction), en plus de l'entity batch. - MAJ-03 : Le nom de la séquence est
audit_destruction_seq(pasaudit_seq). Aligner dans code contracts et migration. - Tests : TC-250-09, TC-250-16 (intégration PostgreSQL)
- Décision architecturale :
- Choix : Séquence PostgreSQL dédiée (
audit_destruction_seq) plutôt que réutilisation de la séquence globale - Pourquoi : Isolation des compteurs par domaine fonctionnel. La monotonie est garantie par domaine (destruction), pas globalement. Alternative séquence globale : contention cross-module.
- Trade-off : Une séquence supplémentaire en DB. Impact négligeable.
Tâche 7 — Service d'alertes et métriques¶
- Agent : agent-developer
- Niveau : 2
- Dépend de : [T6]
- Contract :
destruction-alert - Fichiers :
src/modules/destruction/services/destruction-alert.service.tssrc/modules/destruction/events/destruction.events.tssrc/modules/destruction/__tests__/destruction-alert.service.spec.ts- Description : Publier les résultats batch sur
EventEmitter2avec compteurs agrégés (pas d'identifiants individuels). Restrictionbatch_resultaux rôles ADMIN/SYSTEM (MIN-12). Alertes SLA contractuelles :batchFinalizeSla→ alerte critique,destructionExecutionSla→ alerte,reconciliationSla→ escalade critique. MéthodealertUnitaryError(documentId, errorType)pour les alertes unitaires ERR-250-03/04 (résolution MAJ-05). - Réserve Gate 5 intégrée :
- MAJ-05 : Exposer
alertUnitaryError(documentId, errorType, batchId)pour émettre une alerte unitaire (pas seulement batch-level) pour chaque erreur ERR-250-03 et ERR-250-04. - Tests : TC-250-14, TC-250-26, TC-250-27, TC-250-28
Tâche 8 — Machine à états des documents¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract :
destruction-state-machine - Fichiers :
src/modules/destruction/services/document-state-machine.service.tssrc/modules/destruction/__tests__/document-state-machine.service.spec.ts- Description : Implémenter les gardes de transition d'état pour les documents. Transitions autorisées :
PENDING→SEALED,SEALED→EXPIRED,EXPIRED→DESTROYED,EXPIRED→RECONCILIATION_FAILED. Transitions interdites (5 gardes, incluant MAJ-28) :SEALED→PENDING,EXPIRED→SEALED,DESTROYED→EXPIRED,DESTROYED→SEALED,RECONCILIATION_FAILED→*. MéthodevalidateTransition(current, target)→ throw si interdit + audit. MéthodeapplyTransition(queryRunner, documentId, newStatus). - Tests : TC-250-15 (étendu à 5 transitions)
- Décision architecturale :
- Choix : Matrice de transitions en constante (Map) plutôt que pattern State (classes par état)
- Pourquoi : 5 états, 4 transitions autorisées — trop simple pour justifier le pattern State GoF. Une
Map<Status, Set<Status>>est lisible, testable et extensible. Alternative pattern State : over-engineering pour ce use case. - Trade-off : Moins extensible si le graphe de transitions devient complexe. Acceptable pour PD-250.
Tâche 9 — Service de zeroization document¶
- Agent : agent-developer
- Niveau : 1
- Dépend de : [T13]
- Contract :
destruction-zeroization - Fichiers :
src/modules/destruction/services/document-zeroization.service.tssrc/modules/destruction/__tests__/document-zeroization.service.spec.ts- Description : Implémenter la zeroization cryptographique pour le flux
legal_lock(INV-250-12). Pattern PD-81 adapté : transaction SERIALIZABLE,Buffer.fill(0)pour écraser en mémoire,UPDATE ... SET encrypted_metadata = NULL. Fail-closed (MAJ-27) : si zeroization échoue, document non supprimé de S3. Détection fluxlegal_lockvia colonnehad_legal_lock(backfillée en T13). - Tests : TC-250-17, TC-250-17b (fail-closed zeroization)
Tâche 10 — Contrôleur admin bordereaux¶
- Agent : agent-developer
- Niveau : 3
- Dépend de : [T3, T6]
- Contract :
destruction-admin-api - Fichiers :
src/modules/destruction/controllers/bordereau.controller.tssrc/modules/destruction/dto/bordereau-query.dto.tssrc/modules/destruction/dto/bordereau-response.dto.tssrc/modules/destruction/__tests__/bordereau.controller.spec.ts- Description : Exposer
GET /admin/bordereauxavec@Roles('ADMIN')+AuthorizationGuard. Query params :dateFrom?,dateTo?,batchId?, pagination (offset/limit). Non-ADMIN → HTTP 403 + auditDOCUMENT_DESTROY_ACCESS_DENIED. DTO réponse :bordereauId,batchId,createdAt,documentCount,status,pdfUrl(presigned S3). - Tests : TC-250-20, TC-250-21
Tâche 11 — Processor préavis BullMQ¶
- Agent : agent-developer
- Niveau : 2
- Dépend de : [T1, T2]
- Contract :
destruction-prenotice - Fichiers :
src/modules/destruction/processors/pre-notice.processor.tssrc/modules/destruction/events/pre-notice.events.tssrc/modules/destruction/__tests__/pre-notice.processor.spec.ts- Description : Job BullMQ sur queue
pv-jobs-prenotice(sans:). Scheduling quotidien viapreNoticeJobIntervaldédié (résolution MAJ-02, distinct dedestructionJobInterval). Sélection viaeligibility.selectPreNotice(preNoticeDays). ÉmissionEventEmitter2.emit('destruction.pre-notice', { documentId, eligibleAt, preNoticeDays })— pas de PII. Cas N=0 : jour J, avant run destruction. API BullMQ v5 :getJobSchedulers/removeJobScheduleruniquement. - Réserve Gate 5 intégrée :
- MAJ-02 : Utiliser
preNoticeJobIntervalde T1 (pasdestructionJobInterval) pour le scheduling. - Tests : TC-250-22
Tâche 12 — Processor principal destruction BullMQ¶
- Agent : agent-developer
- Niveau : 4
- Dépend de : [T1, T3, T4, T5, T7]
- Contract :
destruction-processor - Fichiers :
src/modules/destruction/processors/destruction.processor.tssrc/modules/destruction/__tests__/destruction.processor.spec.ts- Description : Processor BullMQ sur queue
pv-jobs-destruction. Orchestration complète du flux §5.1→§5.10 : validation config → sélection éligible → création batch (PENDING→RUNNING,parentBatchIdsi reprise MIN-11) → génération bordereau (fail-closed INV-250-03) → chronodestructionExecutionSla(MAJ-26) → destruction séquentielle (MAJ-25) → vérificationbatchFinalizeSla→ publication résultat. API BullMQ v5 uniquement (INV-250-14).parentBatchIdnon null pour batches de reprise, null sinon. - Tests : TC-250-08, TC-250-12, TC-250-19, TC-250-26
Tâche 13 — Migrations de base de données¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract :
destruction-migrations - Fichiers :
src/database/migrations/1740700000000-PD-250-destruction-schema.tssrc/database/migrations/1740700000001-PD-250-document-status-extension.ts- Description : Créer les migrations TypeORM :
- Extension enum
document_status:ADD VALUE IF NOT EXISTS 'DESTROYED',ADD VALUE IF NOT EXISTS 'RECONCILIATION_FAILED'. - Colonne
had_legal_lock(BOOLEAN, NOT NULL, DEFAULT false) + backfill par batch (résolution MAJ-04 : vérifier historique audit en plus delegal_lock/legal_lock_until). - Table
destruction_batches(id, status, parent_batch_id, bordereau_id, compteurs, timestamps). - Table
destruction_bordereaux(id, batch_id, pdf_s3_path, pdf_hash, tsa_token, signature, document_count, retention_expiry nullable). - Séquence
vault_secure.audit_destruction_seq(nom aligné MAJ-03). - Index :
idx_destruction_batches_status,idx_destruction_batches_created_at,idx_documents_had_legal_lock. Pattern DDL PD-264 : DROP TRIGGER → backfill → ALTER → constraints → index → TRIGGER (si applicable). Backfill par batch de 1000 pour éviter lock long. - Réserves Gate 5 intégrées :
- MAJ-03 : Séquence nommée
audit_destruction_seq(aligné avec le plan, explicite). - MAJ-04 : Le backfill
had_legal_lockdoit vérifier l'historique d'audit (SELECT EXISTS (SELECT 1 FROM audit_log WHERE entity_id = doc.id AND action IN ('legal_lock.applied', 'legal_lock.activated'))) en plus des colonneslegal_lock/legal_lock_untilactuelles. Cela couvre le cas où un legal_lock a été retiré (pas expiré). - Tests : Validation
npm run typeorm migration:runen local
Tâche 14 — Tests contractuels transversaux¶
- Agent : agent-qa-unit-integration
- Niveau : 6
- Dépend de : [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T15]
- Contract : Transversal (tous les code contracts)
- Fichiers :
src/modules/destruction/__tests__/contractual/queue-naming.spec.tssrc/modules/destruction/__tests__/contractual/deprecated-api.spec.tssrc/modules/destruction/__tests__/contractual/state-transitions.spec.tssrc/modules/destruction/__tests__/contractual/parent-batch-id.spec.tssrc/modules/destruction/__tests__/contractual/pii-exclusion.spec.ts- Description : Implémenter les tests contractuels transversaux qui vérifient les invariants cross-cutting :
- TC-250-18 : Queue naming sans
:(regex négative) - TC-250-19 : Scan statique absence
getRepeatableJobs/removeRepeatableByKey+ présencegetJobSchedulers/removeJobScheduler - TC-250-15 étendu : 5 transitions interdites (incluant
RECONCILIATION_FAILED→DESTROYED, MAJ-28) - TC-250-17b : Fail-closed zeroization (MAJ-27)
- TC-250-23 : Config hors bornes — échantillonnage MIN-15 (3 params × min+max)
- MIN-11 :
parentBatchIdnon null pour batch de reprise, null sinon - MIN-12 : Restriction événements
batch_resultaux rôles ADMIN/SYSTEM - PII exclusion : Scan des payloads bordereau et préavis pour absence de données personnelles
Tâche 15 — Module NestJS principal (wiring)¶
- Agent : agent-developer
- Niveau : 5
- Dépend de : [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]
- Contract : Transversal
- Fichiers :
src/modules/destruction/destruction.module.tssrc/modules/destruction/enums/batch-status.enum.tssrc/modules/destruction/enums/destruction-audit-action.enum.tssrc/modules/destruction/entities/destruction-batch.entity.ts- Description : Assembler le module NestJS :
imports(ConfigModule, TypeORM entities, BullModule queues, AuditModule, TsaModule, StorageModule),controllers(BordereauController),providers(tous les services + processors),exports(services publics). Définir les enumsBatchStatusetDestructionAuditAction. EntityDestructionBatchavec relation versDestructionBordereau.
Tâche 16 — Review sécurité adversariale¶
- Agent : agent-adversarial
- Niveau : 6
- Dépend de : [T15]
- Contract : Transversal
- Fichiers : Rapport (pas de production de code)
- Description : Review sécurité du module complet. Vérifier :
- Fail-closed : aucune destruction possible sans bordereau signé+horodaté valide
- PII : absence de données personnelles dans bordereaux, préavis et métriques
- Timing attacks :
crypto.timingSafeEqualpour comparaisons de hashes - Injection : paramètres QueryBuilder bindés (pas de concaténation SQL)
- Contrôle d'accès : endpoint admin protégé, événements restreints
- Idempotence : pas de double destruction, pas de retraitement DESTROYED
- Transitions : matrice de transitions complète, pas de chemin non gardé
4. Intégration des réserves Gate 5¶
| Réserve | Sévérité | Tâche(s) impactée(s) | Résolution |
|---|---|---|---|
| BLQ-01 | BLOQUANT | T6 | Test d'intégration PostgreSQL réel pour TC-250-16 dans destruction-audit.integration.spec.ts. Simule crash post-S3/pré-commit et vérifie réconciliation ACID. |
| MAJ-01 | MAJEUR | T6, T12 | parentBatchId ajouté comme paramètre de logDestruction() et inclus dans chaque entry d'audit (en plus de l'entity batch). |
| MAJ-02 | MAJEUR | T1, T11 | Variable dédiée DESTRUCTION_PRE_NOTICE_JOB_INTERVAL (défaut 24h) ajoutée à la config. T11 utilise cette variable pour le scheduling. |
| MAJ-03 | MAJEUR | T13, T6 | Séquence nommée audit_destruction_seq partout (migration et service). |
| MAJ-04 | MAJEUR | T13 | Backfill enrichi : vérification historique d'audit (événements legal_lock.*) en plus des colonnes courantes. |
| MAJ-05 | MAJEUR | T7, T4 | alertUnitaryError(documentId, errorType, batchId) ajoutée à T7. T4 l'appelle pour chaque ERR-250-03/04. |
5. Decision trace¶
DT-01 — Structure module : destruction/ séparé vs extension documents/¶
- Choix : Module
src/modules/destruction/séparé - Pourquoi : Le domaine destruction a son propre cycle de vie (batch, bordereau, réconciliation, préavis), ses propres entities (batch, bordereau), ses propres jobs BullMQ, et ses propres invariants normés (ISO 14641, NF Z42-013). L'intégrer dans
documents/créerait un module de 2000+ LOC avec des responsabilités mélangées. Alternativedocuments/destruction/sous-module : possible mais complexifie les imports circulaires (DocumentSecure ↔ destruction). - Trade-off : Dépendance croisée vers
DocumentSecureentity. Mitigation : import direct de l'entity (pas du module documents entier).
DT-02 — Audit : séquence dédiée vs séquence globale¶
- Choix : Séquence
audit_destruction_seqdédiée au domaine destruction - Pourquoi : L'invariant INV-250-05 exige la monotonie causale par document, pas la monotonie globale cross-domaine. Une séquence dédiée évite la contention avec d'autres modules auditant en parallèle.
- Trade-off : Si un audit cross-domaine nécessite un ordonnancement global futur, il faudra une séquence supplémentaire. Acceptable pour PD-250.
6. Résumé¶
| Métrique | Valeur |
|---|---|
| Total tâches | 16 |
| Niveaux de parallélisation | 7 |
| Temps séquentiel estimé | 22h |
| Temps parallèle estimé | 16h |
| Speedup factor | 1.37x |
| Stratégie Git | branch_per_level |
| Réserves Gate 5 intégrées | 6/6 (1 BLQ + 5 MAJ) |
| Tests contractuels | 5 fichiers dédiés |
| Tests d'intégration PostgreSQL | 1 (TC-250-16, BLQ-01) |
| Dépendance externe nouvelle | pdf-lib |
| Fichiers produits (estimation) | ~35 fichiers |