Aller au contenu

PD-52 — Retour d'expérience (REX)


Navigation User Story | Document | | | ---------- | -- | | [Spécification](PD-52-specification.md) | | | [Plan d'implémentation](PD-52-plan.md) | | | [Tests](PD-52-tests.md) | | | [Critères d'acceptation](PD-52-acceptability.md) | | | **Retour d'expérience** | *(ce document)* | [Retour a blockchain](../PD-189-epic.md) - [Index User Story](index.md)

1. Résumé exécutif

Objectif initial : Configurer l'infrastructure Ethereum Layer 2 (Polygon Amoy testnet + Arbitrum Sepolia testnet) avec custody mode S2 (AWS KMS), RPC providers primaires/secondaires, et endpoints de health check pour monitoring.

Résultat obtenu : Module blockchain NestJS complet (src/modules/blockchain/) avec : - Mode custody S2 (KMS AWS eu-west-3) opérationnel - RPC providers configurés (Polygon + Arbitrum) avec fallback automatique - Tests unitaires et d'intégration (61 tests PASS, coverage 92.7%) - Health checks blockchain intégrés au monitoring global - Déploiement dev validé (smoke-test: API /health → HTTP 200)

Verdict d'acceptabilité : ACCEPTÉ (Gate 8 GO, score 8.0/10)

État des tests contractuels : 61/61 PASS (TC-NOM-, TC-ERR-, TC-CTX-, TC-SEC-, TC-VAL-*)

Pipeline GitLab : - Backend : 2325347149 (SUCCESS) - Infra : 2325331081 (SUCCESS) - Smoke-test dev : PASSED


2. Points fluides

Architecture modulaire claire

  • Le découpage en modules (RpcProviderService, CustodyService, S2KmsStrategy, BlockchainModule) a facilité l'implémentation et les tests isolés.
  • La séparation custody/providers a permis d'introduire des stratégies alternatives sans impacter le code existant.

Gestion multi-réseaux propre

  • La configuration RPC primaire/secondaire avec fallback automatique a été implémentée de manière générique.
  • L'abstraction RpcProviderService permet l'ajout futur d'autres L2 (Optimism, Base) sans refactoring majeur.

Tests exhaustifs

  • Les 61 tests couvrent tous les critères d'acceptation définis (custody mode, RPC health, error handling).
  • Les mocks ethers.js ont permis de tester les scénarios d'erreur RPC sans dépendre du testnet.

Codes d'erreur normatifs

  • La table des codes (CUSTODY_MODE_INVALID, RPC_PROVIDER_UNAVAILABLE, INVALID_NETWORK) était stable.
  • Le mapping spec → code → test était direct et vérifiable.

Intégration AWS KMS fonctionnelle

  • L'intégration avec AWS KMS s'est avérée stable avec la clé 4d05bb01-2aa1-4f33-9e14-5355b1317f35.
  • API synchrone, signature ECDSA secp256k1 performante (~50ms par signature).

3. Points difficiles

Problème majeur : Configuration Ansible incomplète

Contexte : Après Gate 8 GO, le déploiement dev a échoué à plusieurs reprises avec des erreurs non anticipées dans le plan d'implémentation.

Erreurs rencontrées :

  1. DATABASE_PASSWORD vs DB_PASSWORD (2 pipelines en échec)
  2. Template Ansible env.j2 générait DATABASE_PASSWORD
  3. Backend NestJS attendait DB_PASSWORD (convention PD-14)
  4. Symptôme : PostgreSQL SCRAM error "password must be a string"
  5. Résolution : Renommage des variables dans le template Ansible
  6. Commit : ba76728 (fix: use DB_* prefix for database env vars)

  7. AWS credentials manquants (1 pipeline en échec)

  8. Template Ansible ne configurait pas AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
  9. Backend S2 custody mode ne pouvait pas accéder au KMS AWS
  10. Symptôme : [CUSTODY_MODE_INVALID] Failed to get address from KMS
  11. Résolution : Ajout des variables AWS dans env.j2 et création de aws.yml
  12. Commit : cb5f603 (fix: add AWS credentials for S2 custody mode)

  13. .env.development versionné dans Git (conflit Ansible/Git)

  14. Le fichier .env.development était tracké dans Git ET généré par Ansible
  15. Symptôme : Git pull écrasait la configuration Ansible après déploiement
  16. Résolution : Suppression du fichier de Git, ajout dans .gitignore
  17. Nouvelle règle : Infra gère TOUS les .env, backend n'en contient AUCUN

Impact : 5 pipelines GitLab nécessaires au total (au lieu de 1 prévu) pour obtenir un déploiement fonctionnel.

Absence de tests de déploiement avant Gate 8

  • Le plan d'implémentation et l'acceptabilité étaient focalisés sur le code backend.
  • La configuration Ansible (templates, variables Vault) n'a pas été testée avant le déploiement réel.
  • Aucun smoke-test local n'avait validé que le backend démarrait avec les variables d'environnement générées par Ansible.

NODE_ENV mapping non documenté

  • La différence entre env_name=dev (Ansible) et NODE_ENV=development (Node.js) n'était pas explicite.
  • Résolution : Ajout d'un mapping systématique dans les templates Jinja2 :
    {{ 'development' if env_name == 'dev' else 'production' if env_name == 'prod' else env_name }}
    

4. Hypothèses révélées tardivement

H-06 : Séparation stricte backend/infra pour les .env

Initialement implicite : Le backend et l'infra gèrent chacun leurs fichiers de configuration.

Réalité découverte : Le backend contenait un .env.development versionné qui entrait en conflit avec la génération Ansible.

Résolution : - Suppression complète de tous les .env* du repo backend (même .env.example) - Documentation de la règle : "Infra manages ALL .env files, backend repo contains NONE" - Ajout dans .gitignore : .env.development, .env.test, etc.

H-07 : AWS credentials requis pour S2 custody mode

Initialement implicite : Le mode custody S2 nécessite AWS KMS, donc les credentials AWS.

Omission : Le plan d'implémentation ne mentionnait pas l'ajout des variables AWS dans le template Ansible.

Résolution : - Création de ansible/inventory/dev/group_vars/all/aws.yml - Fetch des credentials depuis Vault kv/app/aws-storage - Injection dans .env.development via template env.j2

H-08 : Conventions de nommage variables database

Initialement implicite : PD-14 (TypeORM config) avait standardisé le préfixe DB_*.

Dérive : Le template Ansible utilisait DATABASE_* (probablement hérité d'une ancienne convention).

Résolution : Alignement sur PD-14 avec préfixe DB_* partout (Ansible + backend).


5. Invariants complexes

INV-CUST-01 : Isolation des clés KMS

Énoncé : Chaque environnement (dev/test/prod) doit utiliser une clé KMS AWS distincte.

Difficulté : Valider que la clé KMS dev (4d05bb01-2aa1-4f33-9e14-5355b1317f35) n'est jamais utilisée en prod.

Couverture : - Tests unitaires avec mock KMS vérifient l'isolation logique - Tests d'intégration (hors scope PD-52) nécessaires pour valider les ACL IAM

Recommandation : Ajouter un test d'intégration qui tente d'utiliser une clé KMS cross-environment et vérifie que l'accès est refusé.

INV-RPC-02 : Fallback RPC sans perte de transaction

Énoncé : Si le RPC primaire échoue, le fallback secondaire doit reprendre sans perte de transaction en cours.

Difficulté : Tester ce scénario nécessite de simuler une panne RPC au milieu d'une transaction ethers.js.

Couverture : - Tests unitaires avec mock vérifient le switch primaire→secondaire - Scenario "transaction en vol" non couvert (complexité élevée, impact faible car ethers.js gère le retry automatiquement)

Recommandation : Documenter que le retry est délégué à ethers.js, pas géré par RpcProviderService.


6. Écarts résolus post-Gate 8

ECT-01 : Template Ansible utilise DATABASE_* au lieu de DB_*

Détection : Pipeline backend 2324769251 (failed), logs journald Résolution : Édition de ansible/roles/api/templates/env.j2 Validation : Pipeline backend 2325146655 (deploy success, smoke-test failed pour autre raison)

ECT-02 : AWS credentials absents du template Ansible

Détection : Pipeline backend 2325146655 (smoke-test failed), logs [CUSTODY_MODE_INVALID] Résolution : Création de aws.yml + ajout AWS_* dans env.j2 Validation : Pipeline backend 2325347149 (smoke-test success)

ECT-03 : .env.development versionné dans Git

Détection : Conflit Git/Ansible détecté lors du déploiement Résolution : git rm .env.development, ajout dans .gitignore Validation : Git ne touche plus jamais aux fichiers .env


7. Recommandations d'amélioration

Recommandation R-01 : Tests de déploiement avant Gate 8

Problème : Les erreurs de configuration Ansible n'ont été détectées qu'après Gate 8 GO.

Solution proposée : 1. Ajouter une phase de test de déploiement dans l'étape 7 (acceptabilité) 2. Lancer le pipeline infra + backend sur un environnement de staging avant Gate 8 3. Vérifier que le smoke-test passe avant de considérer l'acceptabilité comme complète

Impact attendu : Réduction du nombre d'itérations post-Gate 8 de 5 à 1-2 max.

Recommandation R-02 : Checklist variables d'environnement

Problème : Les variables AWS manquantes n'ont pas été anticipées dans le plan.

Solution proposée : 1. Créer une checklist "Variables d'environnement" dans le template de plan 2. Pour chaque nouveau module backend, lister explicitement : - Variables requises (ex: AWS_ACCESS_KEY_ID) - Source Vault (ex: kv/app/aws-storage) - Fichier Ansible à modifier (ex: aws.yml, env.j2)

Impact attendu : Détection précoce des dépendances de configuration.

Recommandation R-03 : Validation des templates Ansible

Problème : Les templates Ansible ne sont pas testés automatiquement.

Solution proposée : 1. Ajouter un job GitLab CI ansible-lint sur le repo infra 2. Ajouter des tests Molecule pour valider la génération des .env 3. Comparer les variables générées avec les variables attendues par le backend (via schema validation)

Impact attendu : Détection des incohérences avant déploiement.

Recommandation R-04 : Documentation séparation backend/infra

Problème : La règle "backend ne contient aucun .env" n'était pas documentée.

Solution proposée : 1. Ajouter un fichier DEPLOYMENT.md dans le backend avec la règle explicite 2. Documenter le workflow complet : Ansible génère → systemd charge → backend démarre 3. Préciser que .env.example est également interdit (car il crée de la confusion)

Impact attendu : Éviter les régressions futures (développeur ajoutant un .env local).

Recommandation R-05 : Smoke-test local avant push

Problème : Aucun test local ne validait que le backend démarre avec les variables Ansible.

Solution proposée : 1. Ajouter un script scripts/local-smoke-test.sh qui : - Génère un .env.development via un playbook Ansible local - Lance le backend avec ce .env - Vérifie que /health répond 200 2. Exécuter ce script dans le hook pre-push Git

Impact attendu : Feedback immédiat pour le développeur avant CI/CD.


8. Métriques de workflow

Gate iterations

  • Gate 3 : 2 itérations (spec review → corrections ECT)
  • Gate 5 : 2 itérations (plan review → ajout code contracts)
  • Gate 8 : 1 itération (GO dès la première revue)
  • Post-Gate 8 : 5 pipelines (au lieu de 1) pour déploiement opérationnel

Temps total

  • Développement : ~12h (étapes 1-6)
  • Tests + Reviews : ~4h (étape 7)
  • Déploiement + Debug : ~3h (post-Gate 8, non prévu initialement)
  • Total : ~19h (vs 16h estimé au plan)

Déviations

  • DIV-01 : Template Ansible DATABASE_* vs DB_*
  • DIV-02 : AWS credentials manquants
  • DIV-03 : .env.development versionné dans Git

Score final

  • Gate 8 : 8.0/10 (conformity: 8.0, test_coverage: 8.5, security: 8.0, maintainability: 7.5)
  • Smoke-test dev : PASSED (après corrections post-Gate 8)

9. Conclusion

PD-52 a permis de mettre en place l'infrastructure Ethereum L2 avec succès, mais a révélé des faiblesses dans la validation de la configuration Ansible avant déploiement.

Points positifs : - Architecture backend robuste et testable (coverage 92.7%) - Intégration AWS KMS fonctionnelle - RPC providers avec fallback automatique opérationnels

Points négatifs : - 5 pipelines nécessaires au lieu de 1 (coût temps + CI/CD) - Écarts de configuration non détectés avant Gate 8 - Absence de tests de déploiement dans l'acceptabilité

Actions prioritaires pour les prochaines stories : 1. Implémenter R-01 : Tests de déploiement avant Gate 8 2. Implémenter R-02 : Checklist variables d'environnement dans le plan 3. Implémenter R-03 : Validation automatique des templates Ansible

Verdict final : SUCCÈS avec apprentissages process. Le module blockchain est opérationnel et conforme aux exigences fonctionnelles, mais le workflow de gouvernance doit intégrer davantage de validation infrastructure.


Date de clôture : 2026-02-13 Auteur : Claude Sonnet 4.5 Relecteur : — Statut : CLOS