Aller au contenu

PD-81 - Decomposition en taches agents

Statut: DECOMPOSITION Version: 1.0.0 Date: 2026-02-23 Source: PD-81-plan.md v1.2.0, PD-81-code-contracts.yaml v1.1.0, PD-81-specification.md v1.0.0, PD-81-tests.md v1.0.0


1. Matrice des dependances

ID Agent Description Produit Consomme Depend de Niveau
T1 agent-developer Fondations : constants, enums, interfaces constants/, enums/, interfaces/ - [] 0
T2 agent-developer Entites TypeORM entities/ constants/, enums/, interfaces/ [T1] 1
T3 agent-developer DTOs (validation class-validator) dto/ constants/, enums/, interfaces/ [T1] 1
T4 agent-developer Providers stubs (TSP, Identity) providers/ interfaces/ (ITspVerifier, ILegalIdentityResolver) [T1] 1
T5 agent-sre Migration BDD + triggers + index src/migrations/*legal-pre* entities/ [T2] 2
T6 agent-developer Custom repository LegalReKey repositories/legal-rekey.repository.ts entities/, constants/ [T2] 2
T7 agent-developer MandateValidatorService services/mandate-validator.service.ts interfaces/, entities/, providers/, constants/ + PD-38 HashService, DocumentsModule [T2, T4] 2
T8 agent-developer LegalAuditTrailService services/legal-audit-trail.service.ts interfaces/, entities/, enums/, constants/ + PD-37 HsmService, PD-38 HashService, PD-39 BatchService [T2] 2
T9 agent-developer LegalDestructionService services/legal-destruction.service.ts entities/, enums/, constants/ + LegalAuditTrailService [T2, T8] 3
T10 agent-developer LegalValidationAdapterService services/legal-validation-adapter.service.ts entities/, interfaces/, constants/ + PD-82 DualValidationService [T2] 2
T11 agent-developer LegalReKeyManagerService services/legal-rekey-manager.service.ts entities/, interfaces/, constants/, repositories/, providers/ + PD-41 PreService, LegalAuditTrailService, PD-38 HashService [T6, T4, T8] 3
T12 agent-developer LegalCompositeProofService services/legal-composite-proof.service.ts entities/, interfaces/, constants/ + PD-39 InclusionProofService [T2] 2
T13 agent-developer LegalPreOrchestratorService services/legal-pre-orchestrator.service.ts Tous les services (T7, T8, T9, T10, T11, T12), interfaces/, entities/ [T7, T9, T10, T11, T12] 4
T14 agent-developer Guards (Access, WriteBlock, RateLimit) guards/ entities/, enums/, constants/, LegalAuditTrailService [T8] 3
T15 agent-developer Schedulers (Expiration, Destruction, AnchoringMonitor) schedulers/ entities/, constants/, LegalReKeyManagerService, LegalDestructionService, PD-39 BatchService [T9, T11] 4
T16 agent-developer Controller + Module NestJS + registration app.module controllers/, legal-pre.module.ts + patch app.module.ts Tous les composants (T1-T15) [T13, T14, T15] 5
T17 agent-qa-unit-integration Tests unitaires (tous services, guards, schedulers, repository) __tests__/*.spec.ts, __tests__/fixtures/ Tous les fichiers source (T1-T16) [T16] 6
T18 agent-qa-unit-integration Tests d'integration (N1-N4, E01-E18, S1-S6, R1-R7, L1-L5) __tests__/*.integration.spec.ts Tous les fichiers source (T1-T16) [T16] 6
T19 agent-sre Configuration et monitoring legal-pre.config.ts constants/ [T1] 1

2. Strategie de parallelisation

parallelization:
  strategy: by_level
  levels:
    - level: 0
      tasks: [1]
      agents: [agent-developer]
      branches: ["feature/PD-81-l0-foundations"]
      estimated_time: "1.5h"
    - level: 1
      tasks: [2, 3, 4, 19]
      agents: [agent-developer, agent-developer, agent-developer, agent-sre]
      branches: ["feature/PD-81-l1-entities", "feature/PD-81-l1-dtos", "feature/PD-81-l1-providers", "feature/PD-81-l1-config"]
      estimated_time: "2h"
    - level: 2
      tasks: [5, 6, 7, 8, 10, 12]
      agents: [agent-sre, agent-developer, agent-developer, agent-developer, agent-developer, agent-developer]
      branches: ["feature/PD-81-l2-migration", "feature/PD-81-l2-repository", "feature/PD-81-l2-mandate-validator", "feature/PD-81-l2-audit-trail", "feature/PD-81-l2-validation-adapter", "feature/PD-81-l2-composite-proof"]
      estimated_time: "3h"
    - level: 3
      tasks: [9, 11, 14]
      agents: [agent-developer, agent-developer, agent-developer]
      branches: ["feature/PD-81-l3-destruction", "feature/PD-81-l3-rekey-manager", "feature/PD-81-l3-guards"]
      estimated_time: "3h"
    - level: 4
      tasks: [13, 15]
      agents: [agent-developer, agent-developer]
      branches: ["feature/PD-81-l4-orchestrator", "feature/PD-81-l4-schedulers"]
      estimated_time: "2.5h"
    - level: 5
      tasks: [16]
      agents: [agent-developer]
      branches: ["feature/PD-81-l5-controller-module"]
      estimated_time: "1.5h"
    - level: 6
      tasks: [17, 18]
      agents: [agent-qa-unit-integration, agent-qa-unit-integration]
      branches: ["feature/PD-81-l6-unit-tests", "feature/PD-81-l6-integration-tests"]
      estimated_time: "4h"
  total_sequential_time: "22h"
  total_parallel_time: "17.5h"
  speedup_factor: 1.26
  git_strategy: branch_per_level

Note sur le speedup factor : Le ratio de 1.26 est modere car le graphe de dependances est profond (7 niveaux). Le gain principal est aux niveaux 1 (4 taches paralleles) et 2 (6 taches paralleles). La strategie by_level reste pertinente car les niveaux 1 et 2 concentrent 10 des 19 taches.


3. Detail de chaque tache

Tache 1 -- Fondations (constants, enums, interfaces)

  • Agent : agent-developer
  • Niveau : 0
  • Depend de : []
  • Contract : CC legal-pre-foundations (Module 1) -- volet constants/enums/interfaces uniquement
  • Fichiers :
  • src/modules/legal-pre/constants/legal-pre.constants.ts
  • src/modules/legal-pre/enums/legal-rekey-status.enum.ts
  • src/modules/legal-pre/enums/legal-access-event-type.enum.ts
  • src/modules/legal-pre/enums/legal-mandate-status.enum.ts
  • src/modules/legal-pre/interfaces/legal-pre.interfaces.ts
  • src/modules/legal-pre/interfaces/tsp-verifier.interface.ts
  • src/modules/legal-pre/interfaces/legal-identity-resolver.interface.ts
  • Description : Produire tous les fichiers de fondation du module Legal PRE : constantes contractuelles (TTL max 30j, rate limit 10/min, destruction deadline 3600s, storage domain LEGAL, intervalles schedulers), les 3 enums (LegalReKeyStatus avec transitions ACTIVE->{REVOKED,EXPIRED,COMPLETED}->DESTROYED, LegalAccessEventType avec distinction probatoire/informatif via PROBATIVE_EVENT_TYPES, LegalMandateStatus), et les 3 fichiers d'interfaces (LegalPreInterfaces §9.1/§9.2, ITspVerifier avec token d'injection TSP_VERIFIER_TOKEN, ILegalIdentityResolver avec token LEGAL_IDENTITY_RESOLVER_TOKEN).

Respecter strictement le plan §3.1, §3.2, §3.3 pour les valeurs et signatures. Les interfaces GenerateLegalReKeyInput excluent ownerSecretKey/ownerSigningKey (CORRECTION v2 plan). Pas de valeur hardcodee hors legal-pre.constants.ts.

Decision architecturale : Les constantes contractuelles sont centralisees dans un seul fichier pour garantir qu'un changement de borne (ex: TTL max) se propage partout par import, sans risque de divergence.


Tache 2 -- Entites TypeORM

  • Agent : agent-developer
  • Niveau : 1
  • Depend de : [T1]
  • Contract : CC legal-pre-foundations (Module 1) -- volet entites
  • Fichiers :
  • src/modules/legal-pre/entities/legal-mandate.entity.ts
  • src/modules/legal-pre/entities/legal-validation-case.entity.ts
  • src/modules/legal-pre/entities/legal-rekey.entity.ts
  • src/modules/legal-pre/entities/legal-access-event.entity.ts
  • src/modules/legal-pre/entities/legal-composite-proof.entity.ts
  • Description : Implementer les 5 entites TypeORM dans le schema vault_secure, conformement au plan §3.4. Points critiques :
  • LegalReKey.encryptedKfrags : select: false, type bytea, nullable (zeroisation = set null apres overwrite).
  • LegalReKey.storageDomain : default LEGAL_STORAGE_DOMAIN importe des constantes (INV-81-10).
  • LegalAccessEvent : table append-only (enforcement par trigger en migration T5).
  • LegalReKey.terminalStateAt : nullable, utilise par les schedulers pour calculer le deadline de destruction.
  • Tous les index declares dans le plan §9.3 via decorateurs @Index.
  • Relations @ManyToOne entre LegalReKey -> LegalMandate, LegalReKey -> LegalValidationCase, LegalValidationCase -> LegalMandate.

Decision architecturale : Colonne discriminante storageDomain='LEGAL' plutot que schema PostgreSQL dedie -- moins intrusif, compatible avec le repository guard (ECT-07), pas de refactoring d'entites necessaire.


Tache 3 -- DTOs

  • Agent : agent-developer
  • Niveau : 1
  • Depend de : [T1]
  • Contract : CC legal-pre-dto (Module 13)
  • Fichiers :
  • src/modules/legal-pre/dto/register-legal-mandate.dto.ts
  • src/modules/legal-pre/dto/submit-internal-validation.dto.ts
  • src/modules/legal-pre/dto/activate-legal-access.dto.ts
  • src/modules/legal-pre/dto/close-legal-access.dto.ts
  • src/modules/legal-pre/dto/get-legal-audit-proof.dto.ts
  • src/modules/legal-pre/dto/legal-consultation.dto.ts
  • src/modules/legal-pre/dto/legal-access-status-response.dto.ts
  • Description : Produire les 7 DTOs avec decorateurs class-validator obligatoires. Validation stricte :
  • contextId : @IsIn([LEGAL_PRE_CONTEXT_ID]) quand present.
  • validatorRole : @IsIn(['DPO', 'LegalOfficer']).
  • reason : @IsIn(['REVOKE', 'EXPIRE', 'END_OF_CONSULTATION']).
  • Champs optionnels avec @IsOptional().
  • Aucun champ de cle privee ni kfrags dans les DTOs de reponse.
  • @IsUUID() sur tous les identifiants.
  • Documentation Swagger via @ApiProperty().

Tache 4 -- Providers stubs (TSP, Identity)

  • Agent : agent-developer
  • Niveau : 1
  • Depend de : [T1]
  • Contract : CC legal-pre-providers (Module 2)
  • Fichiers :
  • src/modules/legal-pre/providers/tsp-verifier.stub.ts
  • src/modules/legal-pre/providers/legal-identity-resolver.stub.ts
  • Description : Implementer les 2 stubs injectables :

TspVerifierStub : implemente ITspVerifier. Valide le format du mandat (presence des champs obligatoires, structure JSON/Buffer) mais ne verifie PAS la cryptographie reelle. Retourne un TspVerificationResult avec valid=true si le format est correct, valid=false sinon. Chaque methode porte un commentaire // TODO AC-81-01-PARTIAL: Remplacer par TSP reel (story de dependance). Injectable via TSP_VERIFIER_TOKEN.

LegalIdentityResolverStub : implemente ILegalIdentityResolver. resolveJudicialAuthority(bobPublicKey) retourne une identite fictive autorisee si bobPublicKey est non vide, null sinon. resolveInternalValidator(userId, role) retourne une identite valide pour les userId de test. Chaque methode porte un commentaire // TODO: Integrer IAM reel. Injectable via LEGAL_IDENTITY_RESOLVER_TOKEN.

Aucun appel reseau, aucune logique metier, aucune generation de certificats reels.


Tache 5 -- Migration BDD

  • Agent : agent-sre
  • Niveau : 2
  • Depend de : [T2]
  • Contract : CC legal-pre-migration (Module 16)
  • Fichiers :
  • src/migrations/*-create-legal-pre-tables.ts
  • Description : Creer la migration TypeORM pour les 5 tables dans le schema vault_secure :
  • legal_mandate : avec index idx_legal_mandate_status.
  • legal_validation_case : avec index idx_legal_case_mandate.
  • legal_rekey : avec index idx_legal_rekey_mandate, idx_legal_rekey_status, index partiel idx_legal_rekey_expiration (WHERE status='ACTIVE'), index partiel idx_legal_rekey_destruction (WHERE status IN ('REVOKED','EXPIRED','COMPLETED')).
  • legal_access_event : avec index idx_legal_event_type, idx_legal_event_mandate + trigger BEFORE UPDATE OR DELETE -> RAISE EXCEPTION (append-only, pattern identique a validation_record PD-82).
  • legal_composite_proof : avec index idx_legal_proof_mandate.

Migration reversible (methode down). Types de colonnes strictement conformes aux entites T2. Pas de modification de tables existantes (PD-41, PD-82, PD-39). Pas de subquery dans les index partiels (learning PostgreSQL PD-55).


Tache 6 -- Custom repository LegalReKey

  • Agent : agent-developer
  • Niveau : 2
  • Depend de : [T2]
  • Contract : CC legal-pre-rekey-manager (Module 5) -- volet repository
  • Fichiers :
  • src/modules/legal-pre/repositories/legal-rekey.repository.ts
  • Description : Implementer LegalReKeyRepository (custom TypeORM repository, plan §8.2.1). Applique systematiquement le filtre storageDomain='LEGAL' sur toutes les operations via une methode baseWhere() privee.

Methodes a exposer : - findOneById(legalReKeyId) : avec filtre domain. - findOneByMandateId(mandateId) : avec filtre domain. - findActiveByMandateId(mandateId) : filtre domain + status=ACTIVE. - findExpired() : filtre domain + status=ACTIVE + expiresAt < NOW(). - findPendingDestruction() : filtre domain + status IN (REVOKED, EXPIRED, COMPLETED) + terminalStateAt IS NOT NULL. - findOneWithKfrags(legalReKeyId) : query explicite avec select de encryptedKfrags (le seul endroit ou kfrags est charge). - save(entity), updateStatus(id, status, terminalStateAt?).

Invariant structurel : Aucun service du module ne doit utiliser @InjectRepository(LegalReKey) directement. Seul ce custom repository est injecte (ECT-07).


Tache 7 -- MandateValidatorService

  • Agent : agent-developer
  • Niveau : 2
  • Depend de : [T2, T4]
  • Contract : CC legal-pre-mandate-validator (Module 3)
  • Fichiers :
  • src/modules/legal-pre/services/mandate-validator.service.ts
  • Description : Implementer le service de validation eIDAS du mandat (flux N1, INV-81-02, plan §3.5.1).

Methode principale validateMandate(payload: Buffer) : 1. Verifier format/presence du payload (ERR-81-01). 2. Appeler ITspVerifier.verifyMandateSignature(payload) -- fail-closed (INV-81-11, ERR-81-15). 3. Si valid=false -> lever exception avec code specifique (ERR-81-02). 4. Si certificateChainValid=false -> ERR-81-03. 5. Si revocationStatus='revoked' -> ERR-81-04. 6. Verifier fenetre temporelle validFrom <= NOW() <= validUntil (ERR-81-05). 7. Extraire scopeDocumentIds, verifier non vide (ERR-81-06), resoudre vers IDs internes via DocumentsModule. 8. Calculer mandateHashSha3 via HashService.hash() (PD-38).

Aucun catch silencieux sur les exceptions TSP. Aucune acceptation sans appel a ITspVerifier. Aucun acces direct a la base de donnees.


Tache 8 -- LegalAuditTrailService

  • Agent : agent-developer
  • Niveau : 2
  • Depend de : [T2]
  • Contract : CC legal-pre-audit-trail (Module 6)
  • Fichiers :
  • src/modules/legal-pre/services/legal-audit-trail.service.ts
  • Description : Implementer la tracabilite probatoire complete (INV-81-08, INV-81-09, plan §3.5.4).

emitProbativeEvent(params) (chemin critique, fail-closed) : 1. Construire le payload canonique (JSON deterministe). 2. Calculer eventPayloadHashSha3 via HashService.hash() (PD-38). 3. Signer via HsmService.sign() (PD-37). Echec -> LegalPreException(ERR_HSM_SIGNING_FAILED) (ERR-81-13). Pas de catch silencieux. 4. Horodatage TSA RFC 3161. Echec -> LegalPreException(ERR_TSA_TIMESTAMP_FAILED) (ERR-81-14). Pas de catch silencieux. 5. Persister LegalAccessEvent (append-only). 6. Ajouter au batch d'ancrage PD-39 (asynchrone, non bloquant).

emitInformativeEvent(params) : meme pipeline sauf TSA non bloquant (pas de fail-closed sur echec TSA pour les evenements informatifs).

getEventsForMandate(mandateId) : recuperation des evenements.

Distinction PROBATIVE_EVENT_TYPES vs informatifs. Aucun UPDATE/DELETE sur legal_access_event. Respecter AUDIT_FORBIDDEN_FIELDS de PD-41.


Tache 9 -- LegalDestructionService

  • Agent : agent-developer
  • Niveau : 3
  • Depend de : [T2, T8]
  • Contract : CC legal-pre-destruction (Module 7)
  • Fichiers :
  • src/modules/legal-pre/services/legal-destruction.service.ts
  • Description : Implementer la destruction cryptographique verifiable (INV-81-07, plan §3.5.6).

destroyReKey(legalReKeyId) (transaction SERIALIZABLE) : 1. Charger la ReKey. Si deja DESTROYED -> idempotent (retour succes). 2. Si status not in [REVOKED, EXPIRED, COMPLETED] -> erreur interne. 3. Charger encryptedKfrags (via repository findOneWithKfrags). 4. Overwrite avec Buffer.alloc(originalSize, 0) (zeroisation). 5. Set encryptedKfrags = null. 6. Update status = DESTROYED. 7. Emettre evenement probatoire LEGAL_REKEY_DESTROYED via LegalAuditTrailService.

processDestructionQueue() : iteree par le scheduler, traite toutes les ReKey en etat terminal. Alerte si deadline depasse.

Aucune destruction sans overwrite prealable. Aucune destruction d'une ReKey ACTIVE. Transaction SERIALIZABLE obligatoire. Utiliser crypto.randomUUID() pour tout identifiant genere (learning PD-63).


Tache 10 -- LegalValidationAdapterService

  • Agent : agent-developer
  • Niveau : 2
  • Depend de : [T2]
  • Contract : CC legal-pre-validation-adapter (Module 4)
  • Fichiers :
  • src/modules/legal-pre/services/legal-validation-adapter.service.ts
  • Description : Implementer l'adaptation PD-82 au contexte Legal PRE (flux N2, INV-81-03, plan §3.5.2).

Mapping des roles : DPO -> ValidatorType.PARENT, LegalOfficer -> ValidatorType.AUTHORITY. Mapping des etats (presentation DTO) : PENDING_AUTHORITY -> PENDING_LEGAL_OFFICER, PENDING_PARENT -> PENDING_DPO.

createLegalValidationCase(mandateId, validationTtl) : cree le LegalValidationCase + delegue a DualValidationService.createRequest().

submitValidation(input) : 1. Charger LegalValidationCase. 2. Si validation 1 deja faite ET input.validatorIdentity === case.validator1Identity -> rejet ERR_SAME_IDENTITY (ERR-81-08, INV-81-03). Controle AVANT delegation a PD-82. 3. Mapper le role puis deleguer a DualValidationService.submitValidation(). 4. Mettre a jour LegalValidationCase (validator, state).

getValidationState(legalCaseId) : lecture etat avec alias.

Aucune reimplementation de la state machine PD-82. Aucune modification des enums/entites PD-82.


Tache 11 -- LegalReKeyManagerService

  • Agent : agent-developer
  • Niveau : 3
  • Depend de : [T6, T4, T8]
  • Contract : CC legal-pre-rekey-manager (Module 5) -- volet service
  • Fichiers :
  • src/modules/legal-pre/services/legal-rekey-manager.service.ts
  • Description : Implementer la gestion du cycle de vie des ReKey legales (flux N3, plan §3.5.3). Service central du module.

generateLegalReKey(input) : 1. Verifier contextId === LEGAL_PRE_CONTEXT_ID (INV-81-12). 2. Verifier ttl <= LEGAL_REKEY_MAX_TTL_SECONDS (ERR-81-09). 3. Verifier scopeDocumentIds non vide (INV-81-05). 4. Controle bloquant bobPublicKey (CORRECTION v2) : (a) ITspVerifier pour chaine certificats, (b) ILegalIdentityResolver pour rapprochement IAM. Si echec -> ERR_BOB_IDENTITY_UNVERIFIED (fail-closed). 5. Appeler PreService.generateReKey() avec contextId=LEGAL_PRE_MANDATE, scope=mandateId. 6. Valider l'artefact via PreService.validate(). 7. Stocker encryptedKfrags chiffre dans LegalReKey (domain LEGAL) via LegalReKeyRepository. 8. Emettre evenement probatoire LEGAL_ACCESS_ACTIVATED.

revokeReKey(input) : transaction SERIALIZABLE, idempotence (R5), evenement LEGAL_REKEY_REVOKED.

expireReKey(legalReKeyId) : appele par le scheduler d'expiration.

closeByEndOfConsultation(legalReKeyId, actor) : transition vers COMPLETED.

validateConsultationAccess(legalReKeyId, documentId) : verifie status ACTIVE, expiresAt, documentId dans scope, mandateId coherent. Controle lecture seule renforce par LegalWriteBlockGuard (T14).

getLegalAccessStatus(legalReKeyId) : statut courant.

Utiliser uniquement LegalReKeyRepository (pas @InjectRepository(LegalReKey)). Transactions SERIALIZABLE pour toutes les mutations d'etat. crypto.randomUUID() obligatoire.


Tache 12 -- LegalCompositeProofService

  • Agent : agent-developer
  • Niveau : 2
  • Depend de : [T2]
  • Contract : CC legal-pre-composite-proof (Module 8)
  • Fichiers :
  • src/modules/legal-pre/services/legal-composite-proof.service.ts
  • Description : Implementer l'assemblage de la preuve composite (INV-81-09, AC-81-12, plan §3.5.5).

generateProof(mandateId) : 1. Recuperer tous les LegalAccessEvent pour le mandateId. 2. Recuperer LegalMandate (evidence du mandat). 3. Recuperer LegalValidationCase (evidence de double validation). 4. Recuperer les LegalReKey (evidence du cycle de vie). 5. Pour chaque evenement probatoire, recuperer InclusionProof via PD-39 InclusionProofService. 6. Assembler LegalCompositeProof avec les 5 sections d'evidence + verificationMaterial (cles publiques HSM, racines TSA, algorithmes).

verifyProofIntegrity(proofId) : verification de coherence interne.

La preuve doit etre verifiable hors plateforme. Aucune inclusion de secrets cryptographiques. Aucune preuve pour un dossier non finalise (ReKey encore ACTIVE).


Tache 13 -- LegalPreOrchestratorService

  • Agent : agent-developer
  • Niveau : 4
  • Depend de : [T7, T9, T10, T11, T12]
  • Contract : CC legal-pre-orchestrator (Module 9)
  • Fichiers :
  • src/modules/legal-pre/services/legal-pre-orchestrator.service.ts
  • Description : Implementer le point d'entree principal du module (§9.1 spec, plan §3.5.7). Orchestre les 5 etapes du flux N1-N4.

registerLegalMandate(input) : verifier contextId -> deleguer a MandateValidator -> persister LegalMandate -> creer dossier via LegalValidationAdapter -> emettre MANDATE_QUALIFIED.

submitInternalValidation(input) : deleguer a LegalValidationAdapter.submitValidation() -> emettre VALIDATION_SUBMITTED (+ VALIDATION_ACTIVATED si isActivation).

activateLegalAccess(input) : charger LegalValidationCase (assert ACTIVATED, ERR-81-07) -> verifier validite temporelle mandat -> deleguer a LegalReKeyManager.generateLegalReKey().

closeLegalAccess(input) : selon reason -> deleguer a revokeReKey / closeByEndOfConsultation / expireReKey.

getLegalAuditProof(input) (CORRECTION v2 -- AC-81-14) : verifier autorisation (requesterId === ownerUserId OU role delegue audit_delegate via ILegalIdentityResolver) -> deleguer a LegalCompositeProof.generateProof().

consultDocument(legalReKeyId, documentId, actorIdentity) : deleguer a LegalReKeyManager.validateConsultationAccess() -> PreService.reEncrypt() -> emettre LEGAL_DOCUMENT_ACCESSED.

Aucun appel direct a PreService/DualValidationService sans passer par les services intermediaires. Aucune logique de validation/state machine dans l'orchestrateur.


Tache 14 -- Guards

  • Agent : agent-developer
  • Niveau : 3
  • Depend de : [T8]
  • Contract : CC legal-pre-guards (Module 10)
  • Fichiers :
  • src/modules/legal-pre/guards/legal-pre-access.guard.ts
  • src/modules/legal-pre/guards/legal-write-block.guard.ts
  • src/modules/legal-pre/guards/legal-rate-limit.guard.ts
  • Description : Implementer les 3 guards NestJS :

LegalPreAccessGuard : refuse toute requete sans role legal (dpo, legal_officer, vault_owner). Role admin retire (CORRECTION v2 -- non rattache a la spec Legal PRE).

LegalWriteBlockGuard (CORRECTION v2 -- ERR-81-11) : intercepte PUT, PATCH, DELETE sur /legal-pre/**. Emet evenement ACCESS_DENIED_WRITE_ATTEMPT via LegalAuditTrailService.emitInformativeEvent() (d'ou la dependance sur T8). Retourne HTTP 403 WRITE_OPERATION_FORBIDDEN. Defense en profondeur testable par E11.

LegalRateLimitGuard : compteur Redis atomique par legalReKeyId, fenetre glissante 60s. Default 10/min, configurable [1..60] via ConfigService. HTTP 429 + Retry-After header. Evenement ACCESS_DENIED_RATE_LIMIT. Fail-closed si Redis indisponible (refuse toute consultation, INV-81-11). Aucun bypass, aucune whitelist.


Tache 15 -- Schedulers

  • Agent : agent-developer
  • Niveau : 4
  • Depend de : [T9, T11]
  • Contract : CC legal-pre-schedulers (Module 11)
  • Fichiers :
  • src/modules/legal-pre/schedulers/legal-rekey-expiration.scheduler.ts
  • src/modules/legal-pre/schedulers/legal-rekey-destruction.scheduler.ts
  • src/modules/legal-pre/schedulers/legal-anchoring-monitor.scheduler.ts
  • Description : Implementer les 3 schedulers NestJS (@nestjs/schedule) :

LegalReKeyExpirationScheduler (INV-81-01) : toutes les 30s (LEGAL_EXPIRATION_CHECK_INTERVAL_MS). Query ReKey ACTIVE avec expiresAt <= NOW() via LegalReKeyRepository.findExpired(). Appeler LegalReKeyManager.expireReKey() pour chacune. SELECT FOR UPDATE pour eviter concurrence.

LegalReKeyDestructionScheduler (INV-81-07) : toutes les 60s (LEGAL_DESTRUCTION_CHECK_INTERVAL_MS). Query ReKey terminales via LegalReKeyRepository.findPendingDestruction(). Appeler LegalDestruction.destroyReKey() pour chacune. Alerte si NOW() - terminalStateAt > destructionDeadline.

LegalAnchoringMonitorScheduler (ECT-08, INV-81-08) : toutes les 6h (CronExpression.EVERY_6_HOURS). Query evenements non ancres (anchoringBatchRef IS NULL) avec eventAt < threshold_18h. Force l'ajout au batch courant via BatchService.addItem(). Log WARN pour monitoring externe. Champs alignes avec entite : eventAt (pas createdAt), anchoringBatchRef (pas anchoringBatchId), eventId (pas id).


Tache 16 -- Controller + Module NestJS

  • Agent : agent-developer
  • Niveau : 5
  • Depend de : [T13, T14, T15]
  • Contract : CC legal-pre-api (Module 12)
  • Fichiers :
  • src/modules/legal-pre/controllers/legal-pre.controller.ts
  • src/modules/legal-pre/legal-pre.module.ts
  • src/app.module.ts (patch : ajout LegalPreModule dans imports)
  • Description : Controller : base path /legal-pre, 8 endpoints conformes au plan §3.8. Tous proteges par @UseGuards(JwtAuthGuard, LegalPreAccessGuard). Le guard LegalWriteBlockGuard applique globalement sur le controller. Le endpoint de consultation ajoute LegalRateLimitGuard. Documentation Swagger (@ApiOperation, @ApiResponse). Aucune logique metier dans le controller.

Pas d'endpoint PUT/PATCH/DELETE sur les documents (INV-81-06).

Module : imports TypeOrmModule.forFeature([5 entites]), CryptoModule, TsaModule, DualValidationModule, ScheduleModule. Providers : 7 services + 3 guards + 1 repository + 3 schedulers + 2 stubs (via token injection). Export LegalPreOrchestratorService.

Registration : ajout de LegalPreModule dans AppModule.imports. Verifier l'absence d'import circulaire.


Tache 17 -- Tests unitaires

  • Agent : agent-qa-unit-integration
  • Niveau : 6
  • Depend de : [T16]
  • Contract : CC legal-pre-unit-tests (Module 14)
  • Fichiers :
  • src/modules/legal-pre/__tests__/fixtures/legal-mandate.fixture.ts
  • src/modules/legal-pre/__tests__/fixtures/legal-rekey.fixture.ts
  • src/modules/legal-pre/__tests__/fixtures/legal-identities.fixture.ts
  • src/modules/legal-pre/__tests__/legal-pre-orchestrator.service.spec.ts
  • src/modules/legal-pre/__tests__/mandate-validator.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-validation-adapter.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-rekey-manager.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-audit-trail.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-composite-proof.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-destruction.service.spec.ts
  • src/modules/legal-pre/__tests__/legal-write-block.guard.spec.ts
  • src/modules/legal-pre/__tests__/legal-rate-limit.guard.spec.ts
  • src/modules/legal-pre/__tests__/legal-rekey-expiration.scheduler.spec.ts
  • src/modules/legal-pre/__tests__/legal-rekey-destruction.scheduler.spec.ts
  • src/modules/legal-pre/__tests__/legal-anchoring-monitor.scheduler.spec.ts
  • src/modules/legal-pre/__tests__/legal-rekey.repository.spec.ts
  • Description : Produire les tests unitaires pour chaque service, guard, scheduler et repository. Utiliser Jest + @nestjs/testing. Fixtures deterministes :
  • mandate-valid-001 : mandat valide, scope ['DOC-1001', 'DOC-1002'].
  • mandate-scope-empty-001, mandate-expired-001, mandate-notyet-001.
  • validator-dpo-001, validator-legal-001, validator-dual-001.
  • Certificats : valide, non qualifie, chaine incomplete, revoque.

Couverture cible >= 85% sur chaque fichier service. Tous les ERR-81-01 a ERR-81-18 couverts. Tous les INV-81-01 a INV-81-12 verifies. Les tests de fail-closed verifient que l'exception est propagee (pas swallowee). Mocks pour HSM, TSP, TSA, PreService, DualValidationService. Aucun service externe reel.

Mapping tests spec -> fichiers : conforme au plan §11.2.


Tache 18 -- Tests d'integration

  • Agent : agent-qa-unit-integration
  • Niveau : 6
  • Depend de : [T16]
  • Contract : CC legal-pre-integration-tests (Module 15)
  • Fichiers :
  • src/modules/legal-pre/__tests__/legal-pre.integration.spec.ts
  • src/modules/legal-pre/__tests__/legal-pre.security.spec.ts
  • src/modules/legal-pre/__tests__/legal-pre.robustness.spec.ts
  • src/modules/legal-pre/__tests__/legal-pre.lifecycle.spec.ts
  • Description : Produire les tests d'integration couvrant les 4 categories du cahier de tests :
  • Nominaux (N1-N4) : flux complet de bout en bout avec DB de test + mocks HSM/TSP/TSA.
  • Erreurs (E01-E18) : chaque cas d'erreur contractuel avec comportement exact attendu.
  • Securite (S1-S6) : tentatives d'exploitation (backdoor, escalade, reutilisation, cloisonnement, extraction massive, non titulaire).
  • Robustesse (R1-R7) : pannes TSP/HSM/TSA, concurrence validations, idempotence revokeReKey, concurrence consultation/expiration, concurrence consultation/revocation fenetre 5s.
  • Cycle de vie (L1-L5) : expiration TTL automatique, destruction fin consultation, destruction revocation, audit hors plateforme, delai de destruction.

Base de donnees de test resetee entre chaque scenario. Horloge controlable pour tests TTL. Redis de test pour rate limiting. Mocks HSM/TSP/TSA configurables par scenario. Variables CI : DATABASE_URL, REDIS_URL, CI=true, NODE_ENV=test, HSM_MOCK=true, TSP_MOCK=true.


Tache 19 -- Configuration et monitoring

  • Agent : agent-sre
  • Niveau : 1
  • Depend de : [T1]
  • Contract : CC legal-pre-config (Module 17)
  • Fichiers :
  • src/modules/legal-pre/legal-pre.config.ts
  • Description : Produire le fichier de configuration NestJS (@nestjs/config ou ConfigService). Variables d'environnement documentees avec valeurs par defaut securisees alignees sur les constantes contractuelles :
  • LEGAL_PRE_MAX_TTL_DAYS (defaut: 30)
  • LEGAL_PRE_DESTRUCTION_DEADLINE_SECONDS (defaut: 3600)
  • LEGAL_PRE_RATE_LIMIT_PER_MINUTE (defaut: 10, plage [1..60])
  • LEGAL_PRE_EXPIRATION_CHECK_INTERVAL_MS (defaut: 30000)
  • LEGAL_PRE_DESTRUCTION_CHECK_INTERVAL_MS (defaut: 60000)
  • LEGAL_PRE_ANCHORING_MONITOR_INTERVAL_HOURS (defaut: 6)
  • LEGAL_PRE_ANCHORING_ALERT_THRESHOLD_HOURS (defaut: 18)

Aucune valeur par defaut qui viole les bornes contractuelles.


4. Decisions architecturales cles

DA-01 : Colonne discriminante vs schema dedie (INV-81-10)

  • Choix : colonne storageDomain='LEGAL' avec custom repository guard.
  • Alternatives : (1) schema PostgreSQL dedie vault_legal, (2) table separee legal_rekey_legal.
  • Justification : moins intrusif, pas de refactoring d'entites, le repository guard centralise le filtre et empeche les oublis. Le pattern est teste par S4 et verifie par grep CI.
  • Trade-off : un oubli de passer par le repository pourrait causer un melange -- mitigue par forbidden_patterns dans le code contract et test lint CI.

DA-02 : Stubs avec interface + token d'injection (H-01, H-04)

  • Choix : interfaces ITspVerifier et ILegalIdentityResolver avec injection par token NestJS.
  • Alternative : mock direct dans les services.
  • Justification : le token d'injection permet de substituer le stub par une implementation reelle sans modifier les consommateurs. Le pattern est standard NestJS (custom providers).
  • Trade-off : leger overhead de configuration module, compense par la testabilite et la substituabilite.

5. Resume

Metrique Valeur
Total taches 19
Niveaux de parallelisation 7 (0-6)
Temps sequentiel estime 22h
Temps parallele estime 17.5h
Speedup factor 1.26x
Strategie Git branch_per_level
Agents developer 16 taches
Agents QA 2 taches
Agents SRE 2 taches (migration + config)
Total fichiers a produire ~55 fichiers