PD-277 — Décomposition en tâches agents¶
1. Matrice des dépendances¶
| ID | Agent | Module (CC) | Description | Produit | Consomme | Dépend de | Niveau |
|---|---|---|---|---|---|---|---|
| T1 | agent-developer | pd277-migration | Migration DDL : 3 colonnes vault_secure.legal_rekey | *-PD277-AddNonceAndCertificateColumns.ts | — | [] | 0 |
| T2 | agent-developer | pd277-entity-extension | Extension entité LegalReKey (3 @Column) | legal-rekey.entity.ts | — | [] | 0 |
| T3 | agent-developer | pd277-error-codes | 5 codes d'erreur PD-277 | legal-pre.exception.ts | — | [] | 0 |
| T4 | agent-developer | pd277-tsp-interface | Extension TspVerificationResult (2 champs optionnels) | tsp-verifier.interface.ts | — | [] | 0 |
| T5 | agent-developer | pd277-tsp-stub | Extension TspVerifierStub pour certificateId | tsp-verifier.stub.ts | tsp-verifier.interface.ts | [T4] | 1 |
| T6 | agent-developer | pd277-rekey-manager-controls | Anti-rejeu nonce + PKI binding dans LegalReKeyManagerService | legal-rekey-manager.service.ts | legal-rekey.entity.ts, legal-pre.exception.ts, tsp-verifier.interface.ts | [T2, T3, T4] | 1 |
| T7 | agent-developer | pd277-rekey-repository | Garde d'immuabilité certificats dans LegalReKeyRepository | legal-rekey.repository.ts | legal-rekey.entity.ts | [T2] | 1 |
| T8 | agent-qa-unit-integration | pd277-tests | Tests unitaires + intégration (TC-NOM, TC-ERR, TC-INV, TC-NEG, TC-NR) | *.spec.ts, test/legal-pre/** | Tous les modules T1-T7 | [T1, T2, T3, T4, T5, T6, T7] | 2 |
2. Stratégie de parallélisation¶
parallelization:
strategy: by_level
levels:
- level: 0
tasks: [1, 2, 3, 4]
agents: [agent-developer, agent-developer, agent-developer, agent-developer]
branches:
- "feature/PD-277-l0-migration"
- "feature/PD-277-l0-entity"
- "feature/PD-277-l0-errors"
- "feature/PD-277-l0-tsp-interface"
estimated_time: "1h"
- level: 1
tasks: [5, 6, 7]
agents: [agent-developer, agent-developer, agent-developer]
branches:
- "feature/PD-277-l1-tsp-stub"
- "feature/PD-277-l1-rekey-manager"
- "feature/PD-277-l1-rekey-repository"
estimated_time: "2h"
- level: 2
tasks: [8]
agents: [agent-qa-unit-integration]
branches:
- "feature/PD-277-l2-tests"
estimated_time: "3h"
total_sequential_time: "10h"
total_parallel_time: "6h"
speedup_factor: 1.67
git_strategy: branch_per_level
3. Détail des tâches¶
Tâche 1 — Migration DDL (AddNonceAndCertificateColumns)¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract : pd277-migration
- Fichiers :
src/database/migrations/{timestamp}-PD277-AddNonceAndCertificateColumns.ts- Description : Créer la migration TypeORM qui ajoute 3 colonnes à
vault_secure.legal_rekey: used_nonces JSONB NOT NULL DEFAULT '[]'::jsonbowner_certificate_id VARCHAR(255) NOT NULL DEFAULT ''recipient_certificate_id VARCHAR(255) NOT NULL DEFAULT ''
La méthode up() exécute les 3 ALTER TABLE ADD COLUMN. La méthode down() exécute les 3 ALTER TABLE DROP COLUMN correspondants.
Invariants : INV-277-02, INV-277-04, CA-277-09.
Justification DEFAULT transitoire : Le DEFAULT '' pour les certificats est une décision d'implémentation (H-277-T01) pour compatibilité avec les LegalReKey pré-existants. Protégé par le contrôle fail-closed en T6 (certificats vides → rejet PRE_CERTIFICATE_BINDING_FAILED).
Interdit : modifier des colonnes existantes, créer de nouvelles tables, modifier des triggers ou supprimer des index.
Tâche 2 — Extension entité LegalReKey¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract : pd277-entity-extension
- Fichiers :
src/modules/legal-pre/entities/legal-rekey.entity.ts- Description : Ajouter 3 propriétés TypeORM à l'entité
LegalReKeyexistante : usedNonces: string[]avec@Column('jsonb', { name: 'used_nonces', default: () => "'[]'" })ownerCertificateId: stringavec@Column('varchar', { name: 'owner_certificate_id', length: 255 })recipientCertificateId: stringavec@Column('varchar', { name: 'recipient_certificate_id', length: 255 })
Invariants : INV-277-02, INV-277-04, INV-277-05, INV-277-07, INV-277-08.
Les @Column produisent automatiquement les faits Prolog entity_column(legal_re_key, ...) via extract-facts.py (INV-277-07).
Interdit : modifier des @Column existants, ajouter des valeurs à LegalReKeyStatus, modifier select:false sur encryptedKfrags, modifier les index existants.
Tâche 3 — Codes d'erreur PD-277¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract : pd277-error-codes
- Fichiers :
src/modules/legal-pre/errors/legal-pre.exception.ts- Description : Ajouter les 5 codes d'erreur spécifiques PD-277 dans le fichier d'exceptions existant :
| Code | Constante | HTTP |
|---|---|---|
ERR-NONCE-MISSING | ERR_NONCE_MISSING | 400 |
ERR-NONCE-FORMAT | ERR_NONCE_FORMAT | 400 |
PRE_NONCE_REPLAY_DETECTED | ERR_NONCE_REPLAY | 409 |
PRE_CERTIFICATE_BINDING_FAILED | ERR_CERTIFICATE_BINDING | 400 |
ERR-PERSISTENCE-CONTROL | ERR_PERSISTENCE_CONTROL | 500 |
Chaque code d'erreur est déterministe (même entrée → même code).
Interdit : modifier les codes d'erreur PD-81 existants (ERR-81-*), utiliser des codes génériques sans distinction nonce/certificat, retourner HTTP 200 sur erreur.
Tâche 4 — Extension interface TSP¶
- Agent : agent-developer
- Niveau : 0
- Dépend de : []
- Contract : pd277-tsp-interface
- Fichiers :
src/modules/legal-pre/interfaces/tsp-verifier.interface.ts- Description : Étendre
TspVerificationResultavec 2 champs optionnels : ownerCertificateId?: stringrecipientCertificateId?: string
L'interface ITspVerifier existante n'est PAS modifiée (rétrocompatibilité). Seul le type de résultat est enrichi.
Invariants : INV-277-04.
Interdit : supprimer des champs existants, modifier la signature de ITspVerifier.verify().
Tâche 5 — Extension stub TSP¶
- Agent : agent-developer
- Niveau : 1
- Dépend de : [T4]
- Contract : pd277-tsp-stub
- Fichiers :
src/modules/legal-pre/providers/tsp-verifier.stub.ts- Description : Enrichir
TspVerifierStubpour retourner descertificateIddans le résultat de vérification : ownerCertificateId: chaîne non vide cohérente avec le mandatrecipientCertificateId: chaîne non vide cohérente avec le mandat
Le stub reste un stub — aucune vérification cryptographique réelle. Les TODO traces existants (AC-81-01-PARTIAL) sont préservés.
En mode nominal, le stub retourne toujours des certificats valides. En configuration de test explicite (TC-ERR-06, TC-NEG-05), il peut retourner des certificats invalides/expirés/révoqués.
Interdit : logique métier dans le stub, appels réseau, suppression de champs existants.
Tâche 6 — Contrôles anti-rejeu nonce + PKI certificate binding¶
- Agent : agent-developer
- Niveau : 1
- Dépend de : [T2, T3, T4]
- Contract : pd277-rekey-manager-controls + pd277-rekey-repository
- Fichiers :
src/modules/legal-pre/services/legal-rekey-manager.service.tssrc/modules/legal-pre/repositories/legal-rekey.repository.ts- Description : Tâche principale de PD-277. Deux responsabilités dans le même agent (propriétaire des 2 modules) :
6a — Anti-rejeu nonce (reEncryptWithNonce) : 1. Valider format nonce (UUID v4 lowercase, 36 chars, regex stricte) → ERR-NONCE-MISSING si absent, ERR-NONCE-FORMAT si hors format 2. Transaction SERIALIZABLE : - Charger le LegalReKey - Vérifier binding PKI valide (certificats non vides) → sinon PRE_CERTIFICATE_BINDING_FAILED (fail-closed sur ReKeys hérités) - Vérifier nonce ∉ used_nonces (opérateur JSONB @>) → PRE_NONCE_REPLAY_DETECTED si déjà présent - Insérer nonce dans used_nonces (opérateur JSONB ||) - Appeler preService.reEncrypt() 3. Rollback complet si une étape échoue 4. Retourner résultat seulement après COMMIT 5. Erreurs de sérialisation (40001) → ERR-PERSISTENCE-CONTROL
6b — PKI certificate binding (generateLegalReKey) : 1. Après verifyBobIdentity() (existant), extraire les certificateId depuis TspVerificationResult 2. Valider non-nullité et non-vacuité des 2 IDs 3. Valider validité des certificats (non expirés, non révoqués, compatibles mandat) → sinon PRE_CERTIFICATE_BINDING_FAILED 4. Persister les certificateId dans le LegalReKey à la création
6c — Garde d'immuabilité (repository) : - updateStatus() ne touche JAMAIS les champs certificats - Vérification explicite si un DTO de mise à jour contient ces champs → rejet fail-closed
Invariants : INV-277-01 à 05.
Interdit : modifier PreService.reEncrypt(), retry automatique sur erreur 40001, comparaison nonce côté applicatif (toujours DB), Math.random(), accepter nonce hors UUID v4, certificats fournis par l'appelant (résolution interne uniquement), méthode de modification des certificats après création.
Décision architecturale : Le nonce est contrôlé au niveau LegalReKeyManagerService, en amont de l'appel à PreService. C'est conforme au principe de séparation : legal-pre gère la conformité, crypto/pre gère la cryptographie. Alternative rejetée : contrôle dans PreService (violerait le périmètre PD-41).
Tâche 7 — Vérification faits Prolog (non-agent)¶
Cette tâche est une vérification manuelle par l'orchestrateur, pas un agent autonome. Après merge de T2 (entity extension), vérifier que extract-facts.py produit les 3 faits attendus :
entity_column(legal_re_key, used_nonces, jsonb).
entity_column(legal_re_key, owner_certificate_id, varchar).
entity_column(legal_re_key, recipient_certificate_id, varchar).
Aucune modification de extract-facts.py requise (INV-277-07). Vérification intégrée dans la CI via run_audit. (24/24 checks).
Tâche 8 — Tests unitaires et d'intégration¶
- Agent : agent-qa-unit-integration
- Niveau : 2
- Dépend de : [T1, T2, T3, T4, T5, T6]
- Contract : pd277-tests
- Fichiers :
src/modules/legal-pre/**/*.spec.tstest/legal-pre/**- Description : Couvrir l'intégralité de la matrice de tests PD-277 :
Nominaux (TC-NOM-01 à 05) : - TC-NOM-01 : PKI binding nominal (generateReKey avec certificats) - TC-NOM-02 : Anti-rejeu nonce (1er succès + 2e rejet) - TC-NOM-03 : Vérification faits Prolog générés - TC-NOM-04 : Audit 24/24 (intégration CI) - TC-NOM-05 : Migration up/down
Erreurs (TC-ERR-01 à 10) : - TC-ERR-01/02 : Nonce manquant/format invalide - TC-ERR-03 : Nonce replay - TC-ERR-04/05/06 : Certificats absents/invalides/incohérents - TC-ERR-07 : Erreur persistance → rollback - TC-ERR-08 : Tentative modification certificats → rejet - TC-ERR-09/10 : Facts obsolètes, audit < 24/24
Invariants (TC-INV-03, 05, 06, 08) : - TC-INV-03 : Nonce replay sans duplication - TC-INV-05/06 : Certificat owner/recipient absent → rejet total - TC-INV-08 : Snapshot StatusEnum avant/après
Négatifs (TC-NEG-01 à 06) : - TC-NEG-01 : Variations casse/espaces nonce - TC-NEG-02 : Concurrence réelle (Promise.all, PAS séquentiel) - TC-NEG-03 : Même nonce sur 2 LegalReKey → les 2 réussissent - TC-NEG-04 : Substitution certificats post-création - TC-NEG-05 : Certificat expiré/révoqué - TC-NEG-06 : Facts anciens réutilisés
Non-régression (TC-NR-01 à 04) : - TC-NR-01 : Stabilité 22 checks initiaux - TC-NR-02 : Absence d'impact hors legal-pre - TC-NR-03 : Migration up/down répétable - TC-NR-04 : Suppression ReKey → suppression used_nonces
Contraintes : - Utiliser crypto.randomUUID() pour les nonces de test - TC-NEG-02 doit utiliser Promise.all (concurrence réelle) - Ne PAS mocker la transaction SERIALIZABLE en intégration - Ne PAS modifier PreService ou UmbralProvider
4. Décisions architecturales¶
DA-1 : Nonce contrôlé au niveau LegalReKeyManagerService¶
- Approche choisie : Le contrôle anti-rejeu est dans
LegalReKeyManagerService.reEncryptWithNonce(), en amont dePreService.reEncrypt(). - Alternatives rejetées :
- Contrôle dans
PreService: viole le périmètre PD-41 et mélange conformité légale et cryptographie bas niveau. - Contrôle dans le controller : trop haut niveau, pas transactionnel.
- Trade-off :
PreServicene sait rien du nonce, ce qui impose que tout appelant dereEncryptpasse parreEncryptWithNonce.
DA-2 : Modules repository et service dans le même agent¶
- Approche choisie : T6 combine
pd277-rekey-manager-controlsetpd277-rekey-repositorydans un seul agent (agent-nonce-pki). - Alternatives rejetées :
- 2 agents séparés : introduirait une dépendance cyclique (le service appelle le repository, le repository protège les invariants du service).
- Trade-off : agent légèrement plus complexe mais cohésion fonctionnelle forte (invariants INV-277-05 partagés).
5. Résumé¶
| Métrique | Valeur |
|---|---|
| Total tâches agents | 7 (+ 1 vérification orchestrateur) |
| Niveaux de parallélisation | 3 |
| Temps séquentiel estimé | 10h |
| Temps parallèle estimé | 6h |
| Speedup factor | 1.67x |
| Stratégie Git | branch_per_level |
| Agents developer | 6 tâches (T1-T6) |
| Agents QA | 1 tâche (T8) |
| Vérification orchestrateur | 1 tâche (T7 — faits Prolog) |
Graphe d'exécution¶
Niveau 0 ─────────────────────────────────────────
T1 (migration) T2 (entity) T3 (errors) T4 (interface)
│ │ │ │ │ │
│ │ │ │ │ │
Niveau 1 ─────────────────────────────────────────
│ T7 (repo) T6 (manager) T5 (stub)
│ │ │ │
│ │ │ │
Niveau 2 ─────────────────────────────────────────
└──────────── T8 (tests) ────────────────────┘