PD-103 — Decomposition multi-agents¶
1. Analyse de l'existant (codebase probe)¶
ProbatioVault-app¶
| Element | Statut | Impact |
|---|---|---|
src/capture/ | N'existe pas | Creation complete |
src/seal/state-machine.ts | Existe | Pattern FSM a copier (ALLOWED_TRANSITIONS, InvalidTransitionError, monotone) |
src/seal/orchestrator.ts | Existe | Pattern orchestration multi-etapes a suivre |
src/export/crypto-pipeline.ts | Existe | Pattern pipeline crypto (hash + encrypt) |
src/crypto/aes-gcm.ts | Existe | Reutilise tel quel pour AES-256-GCM |
src/crypto/zeroize.ts | Existe | Reutilise pour withZeroize() / zeroization DEK |
@noble/hashes v1.5.0 | Installe | SHA3-256 via @noble/hashes/sha3 |
react-native-quick-crypto | Non installe | Decision : utiliser @noble/hashes (deja present, pur JS, Hermes-compatible) |
expo-screen-capture v8.0.9 | Installe | Capture ecran disponible |
zustand v5.0.8 | Installe | Store pattern via useSealStore.ts |
zod v4.3.6 | Installe | Validation schemas |
| Jest config | Mock expo-screen-capture deja present | Tests unitaires prets |
| Vitest config | src/crypto/__tests__/ separe | Tests crypto ESM-only |
ProbatioVault-backend¶
| Element | Statut | Impact |
|---|---|---|
src/modules/capture/ | N'existe pas | Creation complete |
src/modules/documents/services/deposit.service.ts | Existe | Pattern pg_advisory_xact_lock pour idempotence |
src/modules/urgent-seal/services/seal-crypto.service.ts | Existe | Pattern DEK wrapping AES-256-GCM |
| Rate-limit Redis | Existe | Extension config pour /documents/capture |
| BullMQ | Existe | Queues async post-commit |
| Migration pattern | {timestamp}-PD103-{Description}.ts | Naming confirme |
ProbatioVault-infra¶
| Element | Statut | Impact |
|---|---|---|
terraform/modules/s3-captures/ | N'existe pas | Nouveau module Terraform |
| Pattern module | main.tf + variables.tf + outputs.tf | Confirme |
2. Decision trace¶
| # | Decision | Alternatives considerees | Choix | Justification |
|---|---|---|---|---|
| D1 | Librairie SHA3-256 mobile | react-native-quick-crypto (natif) vs @noble/hashes/sha3 (pur JS) | @noble/hashes/sha3 | Deja installe, Hermes-compatible, evite ajout native module + rebuild EAS. Si P95 > 3s sur images larges, escalade vers module natif (HT-103-01). |
| D2 | AES-256-GCM mobile | react-native-quick-crypto vs src/crypto/aes-gcm.ts existant | Reutiliser src/crypto/aes-gcm.ts | Code prouve en production (PD-284, PD-248). Pas de nouvelle dependance. |
| D3 | RSA-OAEP wrapping mobile | react-native-quick-crypto vs expo-crypto | expo-crypto (deja installe) | Expo SDK 54 fournit RSA-OAEP via expo-crypto. Evite ajout native module. Verifier support SHA-256 digest dans expo-crypto sinon fallback WebCrypto polyfill. |
| D4 | Zeroization DEK | Custom vs src/crypto/zeroize.ts existant | Reutiliser withZeroize() | Pattern deja valide et teste (PD-284). Limitation GC documentee dans spec. |
| D5 | FSM capture | Custom vs copie src/seal/state-machine.ts | Copie + adaptation | Pattern monotone prouve. 8 etats vs 6 pour seal. Ajout gardes specifiques (hash+encrypt pour CAPTURED->UPLOADING). |
| D6 | Store capture | Redux vs Zustand | Zustand | Coherence projet (tous les stores sont Zustand). Pattern useSealStore.ts. |
| D7 | Idempotence backend | Application-level vs pg_advisory_xact_lock | pg_advisory_xact_lock | Pattern identique a deposit.service.ts (INV-60-02). Lock sur capture_id normalis lowercase. |
| D8 | Journal append-only | Table separee vs colonne JSON | Table capture_audit_log separee | INSERT-ONLY avec trigger BEFORE UPDATE/DELETE. Separation mutation (capture_events) vs immutable (journal). |
| D9 | GC orphelins S3 | S3 lifecycle rules seules vs cron reconciliation | Cron + lifecycle rules | Double protection : lifecycle rules comme filet, cron pour detection active + audit log. |
| D10 | Parallelisation agents | sequential vs by_level (waves) | by_level | 4 waves avec max 5 agents paralleles. Reduit le temps total de ~15 agents sequentiels a ~4 waves. |
| D11 | Projet des tests mobile | Jest seul vs Jest + Vitest | Jest pour capture + Vitest pour crypto pure | Coherence : les tests crypto ESM (@noble/*) sont deja sous Vitest. Les tests d'integration capture restent sous Jest. |
| D12 | Upload multipart | Custom vs AWS SDK @aws-sdk/lib-storage | @aws-sdk/lib-storage (Upload class) | Gestion automatique chunking, retry, abort. Deja utilise cote backend. Cote mobile : implementation manuelle car pas d'AWS SDK RN. |
3. Liste ordonnee des taches¶
Wave 1 — Fondations (5 agents paralleles, aucune dependance inter-agents)¶
T1 : capture-types (agent-developer, app)¶
- Scope : Types partages et branded types pour le domaine capture
- Fichiers :
src/capture/types.tssrc/types/capture.ts(re-export branded types)- Dependances : aucune
- Invariants couverts : INV-103-28 (enum CaptureState), INV-103-31 (CaptureId branded)
- Tests : aucun (types purs)
- Estimation : XS
T2 : capture-state-machine (agent-developer, app) — CC-1¶
- Scope : FSM monotone 8 etats, gardes de transition, terminal enforcement
- Fichiers :
src/capture/state-machine.tssrc/capture/__tests__/state-machine.test.ts- Dependances : T1 (types)
- Pattern source : Copier
src/seal/state-machine.tspuis adapter - Invariants couverts : INV-103-20..29, INV-103-38, INV-103-28
- TC couverts : TC-INV-02, TC-INV-09, TC-INV-10, TC-NOM-12, TC-ERR-02
- Estimation : S
T3 : capture-crypto (agent-developer, app) — CC-2¶
- Scope : Pipeline crypto local (SHA3-256, AES-256-GCM, RSA-OAEP wrapping, zeroization)
- Fichiers :
src/capture/crypto-pipeline.tssrc/capture/kek-provider.tssrc/capture/__tests__/crypto-pipeline.test.ts(Jest, mocks crypto)src/capture/__tests__/crypto-pipeline.vitest.ts(Vitest, real crypto)- Dependances : aucune (utilise
src/crypto/aes-gcm.tsetsrc/crypto/zeroize.tsexistants) - Invariants couverts : INV-103-01..03, INV-103-06, INV-103-09, INV-103-30, INV-103-32, INV-103-39
- TC couverts : TC-INV-01, TC-INV-03, TC-INV-12, TC-ERR-05, TC-ERR-07
- Decisions : D1 (@noble/hashes), D2 (aes-gcm existant), D3 (expo-crypto RSA), D4 (zeroize existant)
- Estimation : M
T4 : capture-ocr (agent-developer, app) — CC-3¶
- Scope : OCR local Apple Vision, non-bloquant, desactivable
- Fichiers :
src/capture/ocr-service.tssrc/capture/__tests__/ocr-service.test.ts- Dependances : aucune
- Invariants couverts : INV-103-04, INV-103-05
- TC couverts : TC-NOM-02, TC-NOM-03, TC-ERR-03
- Estimation : S
T5 : capture-purge (agent-developer, app) — CC-7¶
- Scope : purgeStale() au demarrage, suppression locale post-UPLOADED, watchdog TTL differe
- Fichiers :
src/capture/purge-manager.tssrc/capture/__tests__/purge-manager.test.ts- Dependances : aucune
- Invariants couverts : INV-103-07, INV-103-38
- TC couverts : TC-NOM-04, TC-NOM-17, TC-ERR-11
- Estimation : S
T6 : capture-migration (agent-developer, backend) — CC-13¶
- Scope : Migration DDL : tables
capture_events+capture_audit_log - Fichiers :
src/database/migrations/1743638400000-PD103-CreateCaptureEvents.tssrc/database/migrations/1743638400001-PD103-CreateCaptureAuditLog.ts- Dependances : aucune
- Invariants couverts : INV-103-10, INV-103-37
- Colonnes cles :
capture_events:capture_id(PK, lowercase),status,signature_status,hsm_signature_ref,payload_canonical_sha256,dek_wrapped,kek_id,seal_delayed,seal_delayed_conforming_cycles,created_at,updated_atcapture_audit_log:id,capture_id,event_type,payload_json,created_at+ trigger BEFORE UPDATE/DELETE RAISE EXCEPTION- Contrainte :
ALTER TYPE ADD VALUE->commitTransaction()AVANT toute clause WHERE (learning PD-282) - Estimation : S
Wave 2 — Services dependants (4 agents paralleles)¶
T7 : capture-store (agent-developer, app) — CC-5¶
- Scope : Zustand store persistant pour etat capture + differe + progression
- Fichiers :
src/store/useCaptureStore.tssrc/store/__tests__/useCaptureStore.test.ts- Dependances : T1 (types), T2 (state-machine)
- Pattern source :
src/store/useSealStore.ts - Estimation : S
T8 : capture-upload (agent-developer, app) — CC-4¶
- Scope : Upload single + multipart S3, retry borne, integrite Content-MD5, annulation, reprise differee
- Fichiers :
src/capture/upload-service.tssrc/capture/multipart-upload.tssrc/capture/__tests__/upload-service.test.ts- Dependances : T3 (crypto — besoin du ciphertext)
- Invariants couverts : INV-103-06, INV-103-22, INV-103-23, INV-103-29
- TC couverts : TC-NOM-05, TC-NOM-13, TC-NOM-14, TC-ERR-01, TC-ERR-04, TC-ERR-14
- Estimation : L
T9 : capture-kek-keyring (agent-developer, backend) — CC-11¶
- Scope : Keyring KEK backend (courante + historiques), unwrap DEK, codes 422/503
- Fichiers :
src/modules/capture/services/kek-keyring.service.tssrc/modules/capture/__tests__/kek-keyring.service.spec.ts- Dependances : aucune (mais T6 migration utile pour integration)
- Pattern source :
src/modules/urgent-seal/services/seal-crypto.service.ts - Invariants couverts : INV-103-09, INV-103-30, INV-103-34
- TC couverts : TC-NOM-16, TC-INV-13, TC-ERR-16, TC-ERR-17
- Estimation : M
T10 : capture-idempotence (agent-developer, backend) — CC-10¶
- Scope : Calcul
payload_canonical_sha256, serialisation JSON deterministe, comparaison fingerprint - Fichiers :
src/modules/capture/services/capture-idempotence.service.tssrc/modules/capture/__tests__/capture-idempotence.service.spec.ts- Dependances : aucune
- Pattern source :
src/modules/documents/services/deposit.service.ts(pg_advisory_xact_lock) - Invariants couverts : INV-103-31, INV-103-37
- TC couverts : TC-NOM-15, TC-INV-06, TC-ERR-13
- Decisions : D7 (pg_advisory_xact_lock)
- Estimation : M
Wave 3 — Orchestration (3 agents, M12 depend de M9)¶
T11 : capture-orchestrator (agent-developer, app) — CC-6¶
- Scope : Coordination sequentielle purgeStale -> capture -> hash -> encrypt -> wrap -> upload -> purge locale
- Fichiers :
src/capture/orchestrator.tssrc/capture/api-client.tssrc/capture/notifications.tssrc/capture/index.ts(barrel export)src/capture/__tests__/orchestrator.test.ts- Dependances : T2 (state-machine), T3 (crypto), T4 (ocr), T5 (purge), T7 (store), T8 (upload)
- Pattern source :
src/seal/orchestrator.ts - Invariants couverts : INV-103-03, INV-103-07, INV-103-12, INV-103-24, INV-103-31
- TC couverts : TC-NOM-01, TC-NOM-06, TC-NOM-08 (push)
- Estimation : L
T12 : capture-ingest (agent-developer, backend) — CC-9¶
- Scope : POST /documents/capture — controller, DTO, validation, skew, unwrap, idempotence, persistance
- Fichiers :
src/modules/capture/capture.module.tssrc/modules/capture/capture.controller.tssrc/modules/capture/services/capture-ingest.service.tssrc/modules/capture/dto/create-capture.dto.tssrc/modules/capture/entities/capture-event.entity.tssrc/modules/capture/entities/capture-audit-log.entity.tssrc/modules/capture/__tests__/capture-ingest.service.spec.tssrc/modules/capture/__tests__/capture.controller.spec.ts- Dependances : T6 (migration), T9 (kek-keyring), T10 (idempotence)
- Invariants couverts : INV-103-08, INV-103-10, INV-103-11, INV-103-25
- TC couverts : TC-NOM-07, TC-NOM-08, TC-ERR-06, TC-ERR-08, TC-ERR-10, TC-ERR-12
- Estimation : XL
T13 : capture-reconciliation (agent-developer, backend) — CC-12¶
- Scope : Cron 10min : scan non-terminaux, SEAL_DELAYED trigger/clearing, GC orphelins S3, re-enqueue
- Fichiers :
src/modules/capture/services/capture-reconciliation.service.tssrc/modules/capture/__tests__/capture-reconciliation.service.spec.ts- Dependances : T12 (capture-ingest — besoin entity + service references)
- Invariants couverts : INV-103-11, INV-103-33, INV-103-35, INV-103-36
- TC couverts : TC-INV-07, TC-INV-08, TC-INV-11, TC-INV-14, TC-ERR-09
- Decisions : D8 (journal separe), D9 (cron + lifecycle)
- Estimation : L
Wave 4 — UI + Infra + Integration tests (3 agents paralleles)¶
T14 : capture-ui (agent-developer, app) — CC-8¶
- Scope : Ecran capture, previsualisation, validation/annulation, toggle OCR, progression upload
- Fichiers :
src/screens/capture/CaptureScreen.tsxsrc/components/capture/CapturePreview.tsxsrc/components/capture/CaptureProgress.tsxsrc/components/capture/CaptureButton.tsxsrc/hooks/useCapture.tssrc/i18n/locales/fr/capture.jsonsrc/i18n/locales/en/capture.jsonsrc/screens/capture/__tests__/CaptureScreen.test.tsx- Dependances : T11 (orchestrator)
- TC couverts : (UI, non contractuels directement)
- Estimation : M
T15 : capture-tests-integration (agent-developer, backend) — CC-14¶
- Scope : Tests d'integration backend complets (controller + service + DB)
- Fichiers :
src/modules/capture/__tests__/capture-ingest.integration.spec.tssrc/modules/capture/__tests__/capture-reconciliation.integration.spec.tssrc/modules/capture/__tests__/capture-idempotence.integration.spec.ts- Dependances : T12 (capture-ingest), T13 (reconciliation)
- TC couverts : TC-INV-04, TC-INV-05, TC-INV-07, TC-INV-11
- Estimation : L
T16 : capture-s3-config (agent-developer, infra) — CC-15¶
- Scope : Module Terraform bucket S3 captures avec lifecycle rules orphelins
- Fichiers :
terraform/modules/s3-captures/main.tfterraform/modules/s3-captures/variables.tfterraform/modules/s3-captures/outputs.tfterraform/s3-captures-module.tf(instantiation)- Dependances : aucune
- Invariants couverts : INV-103-33
- Estimation : S
4. Strategie de parallelisation¶
Mode : by_level (4 waves)
Wave 1 (5 agents) ─────────────────────────────────────────
T1:types T2:fsm T3:crypto T4:ocr T5:purge T6:migration
Wave 2 (4 agents) ─────────────────────────────────────────
T7:store T8:upload T9:kek-keyring T10:idempotence
Wave 3 (3 agents, T13 apres T12) ──────────────────────────
T11:orchestrator T12:ingest → T13:reconciliation
Wave 4 (3 agents) ─────────────────────────────────────────
T14:ui T15:tests-integration T16:s3-config
Verification TypeScript incrementale : Apres chaque wave, executer npx tsc --noEmit sur le projet cible (learning PD-254/282/265/283/85).
5. Graphe de dependances¶
graph TD
subgraph "Wave 1"
T1[T1: types]
T2[T2: state-machine]
T3[T3: crypto-pipeline]
T4[T4: ocr-service]
T5[T5: purge-manager]
T6[T6: migration]
end
subgraph "Wave 2"
T7[T7: capture-store]
T8[T8: upload-service]
T9[T9: kek-keyring]
T10[T10: idempotence]
end
subgraph "Wave 3"
T11[T11: orchestrator]
T12[T12: capture-ingest]
T13[T13: reconciliation]
end
subgraph "Wave 4"
T14[T14: capture-ui]
T15[T15: tests-integration]
T16[T16: s3-config]
end
T1 --> T2
T1 --> T7
T2 --> T7
T2 --> T11
T3 --> T8
T3 --> T11
T4 --> T11
T5 --> T11
T7 --> T11
T8 --> T11
T6 --> T12
T9 --> T12
T10 --> T12
T12 --> T13
T11 --> T14
T12 --> T15
T13 --> T15 6. Matrice de couverture TC -> Taches¶
| Test ID | Tache(s) | Niveau |
|---|---|---|
| TC-NOM-01 | T3, T8, T11 | Integration |
| TC-NOM-02 | T4 | Unit |
| TC-NOM-03 | T4 | Unit |
| TC-NOM-04 | T5 | Unit |
| TC-NOM-05 | T8 | Integration |
| TC-NOM-06 | T11 | Integration |
| TC-NOM-07 | T12 | Integration |
| TC-NOM-08 | T12 (garde), T11 (push) | Integration |
| TC-NOM-09 | Pipeline existant | Integration |
| TC-NOM-10 | T3, T11 | Perf |
| TC-NOM-11 | T8, T11 | Perf |
| TC-NOM-12 | T2 | Unit |
| TC-NOM-13 | T8 | Integration |
| TC-NOM-14 | T8, T5 | Integration |
| TC-NOM-15 | T10 | Integration |
| TC-NOM-16 | T9 | Integration |
| TC-NOM-17 | T5 | Unit |
| TC-ERR-01 | T8 | Unit |
| TC-ERR-02 | T2 | Unit |
| TC-ERR-05 | T3 | Unit |
| TC-ERR-06 | T12 | Unit |
| TC-ERR-07 | T3 | Unit |
| TC-ERR-08 | T12 | Unit |
| TC-ERR-09 | T13 | Unit |
| TC-ERR-10 | T12 | Integration |
| TC-ERR-11 | T5 | Unit |
| TC-ERR-12 | T12 | Unit |
| TC-ERR-13 | T10 | Unit |
| TC-ERR-16 | T9 | Unit |
| TC-ERR-17 | T9 | Unit |
| TC-INV-01 | T3, T11 | Integration |
| TC-INV-02 | T2 | Unit |
| TC-INV-03 | T3 | Unit + Vitest |
| TC-INV-04 | T15 | Integration |
| TC-INV-05 | T15 | Integration |
| TC-INV-06 | T10 | Unit |
| TC-INV-07 | T13, T15 | Integration |
| TC-INV-08 | T13 | Unit |
| TC-INV-09 | T8, T5 | Integration |
| TC-INV-10 | T2 | Unit |
| TC-INV-11 | T13, T15 | Integration |
| TC-INV-12 | T3 | Unit (Vitest) |
| TC-INV-13 | T9 | Unit |
| TC-INV-14 | T13 | Unit |
7. TODO restants / STUBS¶
| ID | Stub | Story destination | Impact |
|---|---|---|---|
| STUB-01 | Pipeline scellement (Merkle leaf enqueue) | PD-56 | Transitions PENDING_SEAL -> SEALED -> ANCHOR_CONFIRMED non testables E2E |
| STUB-02 | Worker HSM signature | PD-55 | Garde INV-103-08 testable en mock uniquement |
| STUB-03 | Ancrage blockchain | PD-41 | Transition SEALED -> ANCHOR_CONFIRMED stubbe |
| STUB-04 | Push notification iOS (APNs) | PD-41 / config EAS | Notification mock cote mobile |
8. Risques identifies¶
| Risque | Probabilite | Severite | Mitigation |
|---|---|---|---|
| SHA3-256 pur JS trop lent (>3s P95 sur images >100MB) | Moyenne | Haute | Benchmark TC-NOM-10 des wave 1. Si echec : module natif JSI. |
expo-crypto ne supporte pas RSA-OAEP-SHA256 | Faible | Haute | Verifier API expo-crypto. Fallback : WebCrypto polyfill ou react-native-quick-crypto. |
expo-screen-capture transcodage implicite PNG | Faible | Critique | TC-NR-01 (hash triplet corpus) apres chaque upgrade SDK. |
| Watchdog TTL ne s'execute pas (app killed iOS) | Haute | Moyenne | purgeStale() au prochain lancement couvre ce cas. |
| Orphelins S3 multipart non supprimes immediatement | Moyenne | Faible | Lifecycle rules S3 + GC cron M12 comme double filet. |
# ──────────────────────────────────────────────────
# MANIFEST YAML — PD-103 Decomposition multi-agents
# ──────────────────────────────────────────────────
manifest:
story_id: "PD-103"
story_title: "Capture probatoire d'ecran et scellement automatique"
spec_version: "v3"
tests_version: "v3"
plan_version: "v1"
code_contracts: "PD-103-code-contracts.yaml"
created_at: "2026-04-03"
strategy: by_level
waves:
- id: wave-1
name: "Fondations"
parallel: true
tasks:
- id: T1
name: capture-types
agent: agent-developer
project: app
contract: null
files:
- "src/capture/types.ts"
- "src/types/capture.ts"
depends_on: []
invariants: ["INV-103-28", "INV-103-31"]
tests: []
estimate: XS
- id: T2
name: capture-state-machine
agent: agent-developer
project: app
contract: CC-1
files:
- "src/capture/state-machine.ts"
- "src/capture/__tests__/state-machine.test.ts"
depends_on: [T1]
invariants: ["INV-103-20", "INV-103-21", "INV-103-22", "INV-103-23", "INV-103-24", "INV-103-25", "INV-103-26", "INV-103-27", "INV-103-28", "INV-103-29", "INV-103-38"]
tests: ["TC-INV-02", "TC-INV-09", "TC-INV-10", "TC-NOM-12", "TC-ERR-02"]
estimate: S
- id: T3
name: capture-crypto
agent: agent-developer
project: app
contract: CC-2
files:
- "src/capture/crypto-pipeline.ts"
- "src/capture/kek-provider.ts"
- "src/capture/__tests__/crypto-pipeline.test.ts"
- "src/capture/__tests__/crypto-pipeline.vitest.ts"
depends_on: []
invariants: ["INV-103-01", "INV-103-02", "INV-103-03", "INV-103-06", "INV-103-09", "INV-103-30", "INV-103-32", "INV-103-39"]
tests: ["TC-INV-01", "TC-INV-03", "TC-INV-12", "TC-ERR-05", "TC-ERR-07"]
estimate: M
- id: T4
name: capture-ocr
agent: agent-developer
project: app
contract: CC-3
files:
- "src/capture/ocr-service.ts"
- "src/capture/__tests__/ocr-service.test.ts"
depends_on: []
invariants: ["INV-103-04", "INV-103-05"]
tests: ["TC-NOM-02", "TC-NOM-03", "TC-ERR-03"]
estimate: S
- id: T5
name: capture-purge
agent: agent-developer
project: app
contract: CC-7
files:
- "src/capture/purge-manager.ts"
- "src/capture/__tests__/purge-manager.test.ts"
depends_on: []
invariants: ["INV-103-07", "INV-103-38"]
tests: ["TC-NOM-04", "TC-NOM-17", "TC-ERR-11"]
estimate: S
- id: T6
name: capture-migration
agent: agent-developer
project: backend
contract: CC-13
files:
- "src/database/migrations/1743638400000-PD103-CreateCaptureEvents.ts"
- "src/database/migrations/1743638400001-PD103-CreateCaptureAuditLog.ts"
depends_on: []
invariants: ["INV-103-10", "INV-103-37"]
tests: []
estimate: S
- id: wave-2
name: "Services dependants"
parallel: true
tasks:
- id: T7
name: capture-store
agent: agent-developer
project: app
contract: CC-5
files:
- "src/store/useCaptureStore.ts"
- "src/store/__tests__/useCaptureStore.test.ts"
depends_on: [T1, T2]
invariants: []
tests: []
estimate: S
- id: T8
name: capture-upload
agent: agent-developer
project: app
contract: CC-4
files:
- "src/capture/upload-service.ts"
- "src/capture/multipart-upload.ts"
- "src/capture/__tests__/upload-service.test.ts"
depends_on: [T3]
invariants: ["INV-103-06", "INV-103-22", "INV-103-23", "INV-103-29"]
tests: ["TC-NOM-05", "TC-NOM-13", "TC-NOM-14", "TC-ERR-01", "TC-ERR-04", "TC-ERR-14"]
estimate: L
- id: T9
name: capture-kek-keyring
agent: agent-developer
project: backend
contract: CC-11
files:
- "src/modules/capture/services/kek-keyring.service.ts"
- "src/modules/capture/__tests__/kek-keyring.service.spec.ts"
depends_on: []
invariants: ["INV-103-09", "INV-103-30", "INV-103-34"]
tests: ["TC-NOM-16", "TC-INV-13", "TC-ERR-16", "TC-ERR-17"]
estimate: M
- id: T10
name: capture-idempotence
agent: agent-developer
project: backend
contract: CC-10
files:
- "src/modules/capture/services/capture-idempotence.service.ts"
- "src/modules/capture/__tests__/capture-idempotence.service.spec.ts"
depends_on: []
invariants: ["INV-103-31", "INV-103-37"]
tests: ["TC-NOM-15", "TC-INV-06", "TC-ERR-13"]
estimate: M
- id: wave-3
name: "Orchestration"
parallel: false
tasks:
- id: T11
name: capture-orchestrator
agent: agent-developer
project: app
contract: CC-6
files:
- "src/capture/orchestrator.ts"
- "src/capture/api-client.ts"
- "src/capture/notifications.ts"
- "src/capture/index.ts"
- "src/capture/__tests__/orchestrator.test.ts"
depends_on: [T2, T3, T4, T5, T7, T8]
invariants: ["INV-103-03", "INV-103-07", "INV-103-12", "INV-103-24", "INV-103-31"]
tests: ["TC-NOM-01", "TC-NOM-06"]
estimate: L
- id: T12
name: capture-ingest
agent: agent-developer
project: backend
contract: CC-9
files:
- "src/modules/capture/capture.module.ts"
- "src/modules/capture/capture.controller.ts"
- "src/modules/capture/services/capture-ingest.service.ts"
- "src/modules/capture/dto/create-capture.dto.ts"
- "src/modules/capture/entities/capture-event.entity.ts"
- "src/modules/capture/entities/capture-audit-log.entity.ts"
- "src/modules/capture/__tests__/capture-ingest.service.spec.ts"
- "src/modules/capture/__tests__/capture.controller.spec.ts"
depends_on: [T6, T9, T10]
invariants: ["INV-103-08", "INV-103-10", "INV-103-11", "INV-103-25"]
tests: ["TC-NOM-07", "TC-NOM-08", "TC-ERR-06", "TC-ERR-08", "TC-ERR-10", "TC-ERR-12"]
estimate: XL
- id: T13
name: capture-reconciliation
agent: agent-developer
project: backend
contract: CC-12
files:
- "src/modules/capture/services/capture-reconciliation.service.ts"
- "src/modules/capture/__tests__/capture-reconciliation.service.spec.ts"
depends_on: [T12]
invariants: ["INV-103-11", "INV-103-33", "INV-103-35", "INV-103-36"]
tests: ["TC-INV-07", "TC-INV-08", "TC-INV-11", "TC-INV-14", "TC-ERR-09"]
estimate: L
- id: wave-4
name: "UI + Tests integration + Infra"
parallel: true
tasks:
- id: T14
name: capture-ui
agent: agent-developer
project: app
contract: CC-8
files:
- "src/screens/capture/CaptureScreen.tsx"
- "src/components/capture/CapturePreview.tsx"
- "src/components/capture/CaptureProgress.tsx"
- "src/components/capture/CaptureButton.tsx"
- "src/hooks/useCapture.ts"
- "src/i18n/locales/fr/capture.json"
- "src/i18n/locales/en/capture.json"
- "src/screens/capture/__tests__/CaptureScreen.test.tsx"
depends_on: [T11]
invariants: []
tests: []
estimate: M
- id: T15
name: capture-tests-integration
agent: agent-developer
project: backend
contract: CC-14
files:
- "src/modules/capture/__tests__/capture-ingest.integration.spec.ts"
- "src/modules/capture/__tests__/capture-reconciliation.integration.spec.ts"
- "src/modules/capture/__tests__/capture-idempotence.integration.spec.ts"
depends_on: [T12, T13]
invariants: []
tests: ["TC-INV-04", "TC-INV-05", "TC-INV-07", "TC-INV-11"]
estimate: L
- id: T16
name: capture-s3-config
agent: agent-developer
project: infra
contract: CC-15
files:
- "terraform/modules/s3-captures/main.tf"
- "terraform/modules/s3-captures/variables.tf"
- "terraform/modules/s3-captures/outputs.tf"
- "terraform/s3-captures-module.tf"
depends_on: []
invariants: ["INV-103-33"]
tests: []
estimate: S
summary:
total_tasks: 16
total_files: ~55
projects: [app, backend, infra]
waves: 4
max_parallel_agents: 5
estimated_agent_hours: "T1:XS T2:S T3:M T4:S T5:S T6:S T7:S T8:L T9:M T10:M T11:L T12:XL T13:L T14:M T15:L T16:S"
invariants_covered: 39
test_ids_covered: 48
stubs: ["PD-56 (Merkle)", "PD-55 (TSA/HSM)", "PD-41 (blockchain/notification)"]