PD-47 — Retour d'experience (REX)¶
1. Resume executif¶
| Metrique | Valeur |
|---|---|
| Objectif initial | Sauvegarde PostgreSQL chiffree avec PITR et tracabilite probatoire |
| Resultat obtenu | Conforme — 11 services NestJS, 347 tests, coverage 90.39% |
| Verdict final | GO (Gate 8 v1 : 8.5/10) |
| Tests contractuels | 347/347 passes (11 suites) |
Story cross-repo (backend + infra) couvrant 4 flux : sauvegarde logique quotidienne (F1), archivage WAL continu (F2), basebackup hebdomadaire (F3), restauration PITR staging (F4). 9 invariants, 9 criteres d'acceptation, 13 agents de generation.
2. Metriques de convergence¶
2.1 Temps et iterations¶
| Etape | Duree estimee | Duree reelle | Iterations | Ecart |
|---|---|---|---|---|
| 0 - Besoin | 30 min | 160 min | 1 | +433% |
| 1 - Specification | 2h | 3 min | 1 | -97% |
| 2 - Tests | 1h | 3 min | 1 | -95% |
| 3 - Gate spec | 1h | 34 min | 2 | -43% |
| 4 - Plan | 1h | 16 min | 1 | -73% |
| 5 - Gate plan | 1h | 71 min | 2 | +18% |
| 6 - Implementation | 4h | 6h49 | 1 | +71% |
| 7 - Acceptabilite | 2h | 41 min | 1 | -66% |
| 8 - Gate acceptabilite | 1h | 35 min | 1 | -42% |
| 9 - REX | 30 min | 30 min | 1 | 0% |
| TOTAL | ~14h | ~13.4h | 12 | -4% |
2.2 Scores de convergence par gate¶
| Gate | Score v1 | Score final | Delta | Iterations |
|---|---|---|---|---|
| Gate 3 | 6.0/10 | 9.06/10 | +3.06 | 2 |
| Gate 5 | 5.5/10 | 8.19/10 | +2.69 | 2 |
| Gate 8 | 8.5/10 | 8.5/10 | 0 | 1 |
Double NON_CONFORME Gate 3 + Gate 5 v1. Convergence forte (+3.06 et +2.69 respectivement). Gate 8 GO en v1.
2.3 Ecarts par categorie¶
| Categorie d'ecart | Gate 3 | Gate 5 | Gate 8 | Total |
|---|---|---|---|---|
| ECT (completude/testabilite) | 13 | 10 | 1 | 24 |
| DIV (divergence spec/impl) | 0 | 3 | 1 | 4 |
| AMB (ambiguite) | 4 | 1 | 0 | 5 |
| SEC (securite) | 1 | 2 | 2 | 5 |
| PERF (performance) | 0 | 0 | 0 | 0 |
| TOTAL ecarts | 18 | 16 | 4 | 38 |
Dominance ECT (63%) : la specification initiale manquait de nombreux details de format, de bornes et de testabilite. Les corrections E-01 a E-18 ont couvert les lacunes de completude.
3. Points fluides¶
- Gate 8 GO en v1 : malgre la complexite (13 agents, 11 services), l'implementation a converge directement sans iteration supplementaire a la gate de cloture.
- Coverage 90.39% : bien au-dessus du seuil de 80%, refletant la qualite des tests generes par les agents.
- Quality gates toutes vertes : ESLint 0 erreurs, TypeScript 0 erreurs, Prettier conforme, 347/347 tests.
- Architecture modulaire propre : 11 services avec separation nette des responsabilites (orchestration, chiffrement, journal, watchdog, reconciliation).
- Etapes 1-2 tres rapides : specification et tests generes par ChatGPT en < 3 min chacun, qualite suffisante pour une correction limitee en Gate 3.
4. Points difficiles¶
- Etape 0 disproportionnee (2h40 vs 30 min estime) : la definition du besoin pour une story infra/storage complexe a necessite de nombreux aller-retours avec le PO sur le perimetre exact (WAL, PITR, chiffrement double couche, watchdog independant).
- Double NON_CONFORME v1 : Gate 3 (6.0/10) et Gate 5 (5.5/10) toutes deux NON_CONFORME en premiere iteration. 18 corrections spec + 16 corrections plan avant convergence.
- Pause overnight entre Gate 5 v1 et v2 : la correction du plan a necessite une session de 3 min de travail actif le soir (v1) puis 47 min le lendemain matin (correction + v2). Pas de perte de convergence.
- Step 6 le plus long (6h49) : 13 agents de generation + synthese + correction de 6 erreurs TypeScript + corrections tests pour obtenir 347/347.
- Sonar CE task FAILED : Elasticsearch indexing du serveur Sonar en erreur, masquant le Quality Gate reel. 0 issues backup module mais le QG global est en ERROR (pre-existant, autres modules).
5. Hypotheses revelees tardivement¶
- H-TECH-01 (pg_receivewal sur OVH) : identifiee des l'etape 4 (plan) mais non levee. Le flux F2 WAL continu depend de la disponibilite d'un slot de replication sur le PostgreSQL OVH Cloud Database. Tests E2E WAL conditionnes (SKIP si non leve). Impact : RPO < 5 min non garanti sans cette hypothese.
- H-TECH-05 (Vault Transit aes256-gcm96) : confirmee comme critique — pas de fallback si Vault indisponible (fail-closed). Decouverte a l'etape 5 que le fallback HKDF local initial violait INV-47-03 et INV-47-09 → supprime.
- H-TECH-06 (coexistence BullMQ scheduler) : potentiel conflit de scheduling entre le cron backup et les queues BullMQ metier existantes. Non confirme mais documente comme risque.
6. Invariants complexes¶
- INV-47-01 (cleartext TTL 300s) — TC-INV-01 : timer strict non configurable. Risque de declenchement premature si pg_dump est lent sur base > 10 GB. Mitigation : timer commence APRES fin d'export.
- INV-47-05 (journal append-only + dedup) — TC-INV-05 : combinaison INSERT-only (RLS bloque UPDATE/DELETE) + UPSERT ON CONFLICT DO NOTHING pour deduplication par backup_id. Garantie try/finally pour ecriture meme en echec precoce.
- INV-47-06 (watchdog independant) — TC-INV-06 : decouplage complet via queue BullMQ
backup-relaunch. Le watchdog ne depend pas du process orchestrateur. Complexite : si le process NestJS entier crash, le watchdog NestJS crash aussi → fallback Ansible cron documente. - INV-47-09 (envelope encryption) — TC-INV-09 : DEK ephemere en memoire, wrappee par K_backup via Vault Transit, zeroisee explicitement post-usage. Source de verite : DB (champ wrappedDek), copie redondante en metadata S3.
7. Dette technique¶
- Coherence donnees post-restauration (Q-47-03) — impact: moyen. Le jeu contractuel de tables/compteurs pour valider la coherence apres PITR n'est pas defini. Implementation minimale (count tables + derniere transaction).
- Granularite journal WAL (Q-47-02) — impact: faible. Implementation 1 evenement par segment WAL. Lotissement ulterieur possible si performance insuffisante.
- Politique lifecycle versions S3 (Q-47-04) — impact: faible. Ambiguite sur suppression des versions non courantes vs conservation legale. A clarifier hors scope code.
- backup-relaunch.consumer.ts non teste unitairement — impact: faible. Consumer BullMQ minimal, couvert par tests d'integration. Coverage 0% sur ce fichier.
- backup-encryption.service.ts a 67% coverage — impact: faible. Methodes Vault init (AppRole, verifyTransitKey) non testees unitairement, testees en integration.
8. Risques residuels¶
| Risque | Type | Probabilite | Impact | Mitigation |
|---|---|---|---|---|
| H-TECH-01 non levee (pg_receivewal OVH) | tech | elevee | eleve | Tests E2E WAL SKIP, fallback OVH backup natif non auditable |
| Sonar CE task infra FAILED | ops | moyenne | moyen | 0 issues module backup, QG global pre-existant ERROR |
| Crash complet process NestJS → watchdog down | ops | faible | eleve | Fallback Ansible cron independant documente |
| Vault Transit indisponible | ops | faible | eleve | Fail-closed (pas de fallback), incident operationnel infra |
| Base > 50 GB → SLA backup depasse | metier | faible | moyen | Chiffrement streaming documente comme evolution |
8bis. Matrice de delegation inter-PD¶
| Story | Direction | Statut | Nature de la dependance | Probleme rencontre |
|---|---|---|---|---|
| PD-5 | ← depend de | DONE | Storage Vault Lock, Deep Archive, S3 bucket policies | RAS — learnings injectes a l'etape 0 |
| PD-264 | ← depend de | DONE | Atomicite multi-composant (DB sync + async BullMQ) | RAS — pattern reutilise pour §5.6 crash scenarios |
| PD-8 | ← depend de | DONE | Vault PostgreSQL backend, AppRole cross-role | RAS — pattern auth Vault reutilise pour K_backup |
Aucune dependance sortante identifiee. Story autonome.
8ter. Bugs de tests¶
| Pattern incorrect | Pattern correct | Cause | Cout |
|---|---|---|---|
| 6 erreurs TypeScript post-generation agents | Fix synthese phase 6c | Types incompatibles entre services generes par agents differents | ~30 min |
| tests=ko apres synthese | Corrections tests + relance | Mocks incomplets pour services backup interconnectes | ~100 min |
8quater. Corrections post-Gate 8¶
Aucune correction post-Gate 8 necessaire. Gate 8 GO v1.
9. Patterns recurrents detectes¶
9.1 Patterns confirmes (deja vus dans d'autres stories)¶
- Machine a etats explicite avec transitions autorisees/interdites — PD-47 BackupStateService (INV-47-07), 16eme occurrence (PD-82, PD-250, PD-264, PD-251, PD-277, PD-276, PD-275, PD-279, PD-280, PD-278, PD-282, PD-265, PG-02, PG-03, PG-04, PD-47)
- Guard de securite fail-closed obligatoire — PD-47 Vault Transit indisponible = backup echoue (pas de fallback). 13eme occurrence.
- Atomicite multi-composant : transaction ACID synchrone + post-commit async — PD-47 §5.6 crash pre/post-commit + reconciliation. 10eme occurrence.
- Format non contractualise dans spec v1 bloque en Gate 3 — 18 corrections E-01 a E-18, majorite ECT. 17eme occurrence.
- Stubs inter-PD acceptes en Gate 8 si documentes avec story destination — backup-relaunch.consumer.ts STUB documente PD-47 scope. 13eme occurrence.
- Faux positifs LLM systematiques en reviews — Reviews code/tests/securite ont produit des ecarts non applicables (auth/authz sur module sans endpoint HTTP). 14eme occurrence.
- Double NON_CONFORME Gate 3+5 v1 = indicateur complexite conceptuelle elevee — PD-47 confirme le pattern. 4eme occurrence (PD-280, PD-278, PD-282, PD-47).
9.2 Nouveaux patterns identifies¶
- Module sans endpoint HTTP → faux positifs securite auth/authz — Le module backup n'expose aucun controleur HTTP (execution via Cron + BullMQ uniquement). La review securite a signale auth/authz comme MAJEUR alors que non applicable. A surveiller dans les prochaines stories infra/jobs.
- Sonar CE task infra failure masquant le Quality Gate reel — Le serveur Sonar a un probleme d'indexation Elasticsearch qui fait echouer le CE task. Le QG ERROR est pre-existant (autres modules) mais masque l'evaluation reelle du module backup (0 issues). Pattern a surveiller si recurrence.
- Story cross-repo (backend + infra) avec 13+ agents — Premiere story infra avec flux multi-agents complet. La decomposition a produit 13 taches (T1-T13) dont une relancee (T13-v2). Le cout d'implementation (6h49) est le plus eleve du projet pour une story medium.
10. Ameliorations du workflow¶
10.1 Ameliorations des prompts/templates¶
| Fichier | Amelioration suggeree | Priorite |
|---|---|---|
templates/prompts/1 Specification.md | Ajouter checklist obligatoire pour stories infra/backup : RPO, RTO, chiffrement, journal append-only, watchdog | haute |
templates/prompts/7c Review Security.md | Ajouter detection project_type (backend API vs cron/BullMQ) pour desactiver criteres auth/authz non pertinents | haute |
templates/prompts/1 Specification.md | Exiger la specification du code de rejet vs etat machine (FAILED_FORMAT vs status enum) pour eviter confusion | moyenne |
templates/prompts/4 Plan d'implementation.md | Ajouter section obligatoire "Hypotheses techniques a lever AVANT implementation" avec actions de levee | moyenne |
10.2 Ameliorations des agents¶
| Agent | Amelioration suggeree | Justification |
|---|---|---|
config/agents step 7c | Injecter le type de module (HTTP controller / Cron / BullMQ worker) pour filtrer les criteres de securite | Faux positifs auth/authz sur module sans endpoint HTTP |
config/agents step 6 | Pour stories avec 10+ composants, pre-generer les interfaces TypeScript partagees avant de lancer les agents en parallele | 6 erreurs TS post-synthese dues a des types incompatibles entre agents |
10.3 Ameliorations du processus¶
- Lever les hypotheses techniques AVANT Gate 5 : H-TECH-01 (pg_receivewal OVH) aurait du etre testee entre l'etape 4 et l'etape 5. Le plan a ete valide avec un risque majeur non leve.
- Detecter les stories cross-repo des l'etape 0 : PD-47 touche backend + infra mais l'epic est dans infra. La complexite de coordination inter-repo devrait etre signalee dans le besoin.
- Corriger l'infrastructure Sonar : le CE task FAILED Elasticsearch rend la Phase 1.5 Sonar non fiable. Action infra necessaire.
11. Enseignements cles¶
-
Envelope encryption Vault Transit fail-closed — Quand un service crypto externe (Vault Transit) est la seule source de cles, ne JAMAIS implementer de fallback local. Un fallback viole la separation des cles (INV-47-03) et l'envelope encryption (INV-47-09). L'indisponibilite de Vault est un incident infra, pas un contournement applicatif.
-
Journal append-only avec garantie try/finally — Pour tout journal d'audit probatoire, wrapper l'execution complete dans un try/finally qui garantit l'ecriture d'au moins un evenement (status=FAILED avec code erreur), meme en echec precoce (avant upload, avant chiffrement). Sans cela, un crash pre-upload produit une execution sans trace.
-
Watchdog independant via queue BullMQ — Le decouplage d'un watchdog de son orchestrateur par une queue de messages (pas d'injection directe) est le pattern correct. Le watchdog produit un job de relance dans la queue ; un consommateur separe injecte l'orchestrateur. Ainsi le watchdog reste reellement independant.
-
Hash SHA3-256 sur le clair AVANT chiffrement — Pour une verification d'integrite de bout en bout, le hash doit etre calcule sur le clair compresse (pas sur le ciphertext, pas sur le clair non compresse). La verification post-upload necessite un GetObject + dechiffrement + recalcul SHA3-256 (pas de confiance sur l'ETag S3 qui est MD5).
-
Double NON_CONFORME v1 = complexite conceptuelle — Quand Gate 3 ET Gate 5 sont NON_CONFORME en v1, c'est un indicateur fiable de complexite conceptuelle elevee. Les corrections sont massives (18 + 16 ecarts) mais la convergence est forte (+3.06 et +2.69). Le processus fonctionne : les gates detectent, les corrections convergent.
12. Metriques cumulatives (auto-calculees)¶
| Metrique | Cette story | Moyenne projet | Tendance |
|---|---|---|---|
| Temps total | 13.4h | 6.1h | ↑ |
| Iterations gates | 5 | 5.4 | ↓ |
| Ecarts totaux | 38 | 21.9 | ↑ |
| Score convergence moyen | 8.58/10 | 8.47/10 | ↑ |