PD-22 — Retour d'expérience¶
EPIC de référence : PD-186 — BACKEND CORE
1. Résumé exécutif¶
Objectif : Implémenter un module de configuration NestJS avec validation Joi stricte, chargement multi-sources (fichiers .env, process.env, Vault) et gestion sécurisée des secrets.
Résultat : Module livré et fonctionnel avec 6 écarts identifiés lors de la revue d'acceptabilité, tous résolus par corrections de code (E-01, E-02, E-04) ou clarifications de spécification (E-03, E-05, E-06).
Verdict final : ✅ ACCEPTÉ — Conformité spec atteinte après itérations correctives.
2. Points fluides¶
- Architecture modulaire : La structure
loaders/,validators/,utils/proposée dans le plan a été respectée et facilite la maintenance. - Validation Joi : Le schéma complet (~350 lignes) couvre toutes les variables avec contraintes strictes (
abortEarly: false,allowUnknown: false). - Masquage des secrets : Implémentation robuste avec
SECRET_PLACEHOLDERet fonctionmaskSecrets()appliquée systématiquement. - Codes d'erreur stables : L'enum
ConfigErrorCodeavec 8 codes couvre tous les cas d'erreur de manière déterministe. - Immutabilité :
Object.freeze()récursif correctement implémenté dansConfigService. - Tests unitaires : Couverture complète des loaders, validators et utilitaires avec mocks appropriés.
- Journalisation des defaults : Mécanisme
trackedDefault()fonctionnel pour tracer les valeurs par défaut appliquées.
3. Points difficiles¶
| Obstacle | Contexte | Impact |
|---|---|---|
Signature loadEnvFile incohérente (E-02) | La fonction attendait un chemin complet mais recevait environnement + basePath, causant une reconstruction de chemin invalide | Fichiers .env.<APP_ENV> non chargés, ordre N2 non respecté |
| Fail-fast Vault non implémenté (E-04) | readSecrets retournait {} au lieu de throw, et shouldUseVault=false ne déclenchait qu'un warning | Erreurs Vault détectées tardivement comme MISSING_VARIABLE au lieu de CONFIG_SOURCE_MISSING |
| Ambiguïté process.env filtering (E-03) | Spec §4.4 parlait de "rejet strict" mais les variables système (PATH, HOME) ne peuvent pas être rejetées | Confusion entre variables applicatives et variables système |
| Variables CLOUDHSM manquantes dans spec (E-05) | Le namespace CLOUDHSM_ était autorisé (§10.1) mais les 6 variables n'étaient pas listées dans §10.2 | Incohérence spec/code, écart d'acceptabilité |
| Exigences d'exploitation mélangées (E-06) | Rétention logs 7 jours et accès Ops/SecOps listés dans §10.3 mais hors périmètre code applicatif | Écart identifié à tort comme défaut d'implémentation |
4. Hypothèses révélées tardivement¶
| Hypothèse | Découverte | Conséquence |
|---|---|---|
| Vault obligatoire sur tous les environnements | Confirmé en cours de revue : Vault requis dès l'environnement dev | Modification du comportement fail-fast pour exiger Vault même quand shouldUseVault est false |
| Variables système dans process.env | process.env contient PATH, HOME, USER, etc. qui ne relèvent pas de la configuration applicative | Clarification spec : filtrage par namespace est intentionnel, pas un bug |
| CloudHSM intégré au projet | Découvert via recherche codebase : modules HSM, lambdas monitoring, EPICs PD-36/37/40 | Variables CLOUDHSM_* légitimes, ajoutées à la spec §10.2 |
5. Invariants complexes¶
| Invariant | Complexité | Remarque |
|---|---|---|
| Invariant 7 : Secrets exclusivement via Vault | Élevée | Nécessite validation pré-Vault pour détecter secrets interdits, puis fail-fast si Vault indisponible. Double vérification requise. |
| Invariant 4 : Rejet strict variables inconnues | Moyenne | Tension entre rejet strict et nécessité de filtrer les variables système. Résolu par filtrage namespace avant validation Joi. |
| Invariant 6 : Ordre de chargement immuable | Moyenne | 4 sources (defaults → .env → process.env → Vault) avec priorité croissante. Bug E-02 montrait la fragilité de cette chaîne. |
6. Dette technique¶
| Élément | Nature | Justification |
|---|---|---|
| Tests d'intégration env-file.loader | Dette acceptée puis résolue | Tests initialement mockés, intégration avec fichiers réels ajoutée après E-02 |
Option skipVault dans forRootAsync | Compromis technique | Permet les tests unitaires sans Vault mais contourne l'invariant 7. Usage restreint à APP_ENV=test. |
| Fichiers config legacy | Non supprimés | database.config.ts, captcha.config.ts, email.config.ts coexistent avec le nouveau ConfigModule |
7. Risques résiduels¶
| Risque | Probabilité | Impact | Mitigation |
|---|---|---|---|
| Désynchronisation SECRET_KEYS / Vault | Faible | Majeur | Secret ajouté dans Vault mais pas dans config.constants.ts = pas de détection hors Vault |
| Latence Vault au démarrage | Moyenne | Mineur | Pas de cache token, chaque démarrage requiert authentification AppRole |
| Tests passent avec skipVault | Faible | Moyen | Un bug Vault pourrait passer inaperçu si les tests n'exercent pas le chemin réel |
8. Améliorations processus¶
| Suggestion | Bénéfice attendu |
|---|---|
| Revue spec/code en parallèle | Les écarts E-03, E-05, E-06 auraient été détectés plus tôt si spec et code avaient été revus ensemble |
| Tests d'intégration obligatoires pour loaders | L'écart E-02 (loadEnvFile) n'a pas été détecté par les tests unitaires mockés |
| Checklist explicite "variables système" | Ajouter dans le plan d'implémentation la gestion explicite des variables hors namespace |
| Validation croisée spec §10.1 vs §10.2 | Vérifier que chaque namespace autorisé a ses variables listées |
9. Enseignements clés¶
-
Les mocks peuvent masquer des bugs d'intégration — L'écart E-02 (signature loadEnvFile) n'a été détecté qu'en revue d'acceptabilité car les tests unitaires mockaient la fonction.
-
Clarifier le périmètre code vs infrastructure — Les exigences de rétention logs (E-06) relèvent de l'exploitation, pas du code applicatif. Cette distinction doit être explicite dans la spec.
-
Vérifier la cohérence interne de la spec — Le namespace CLOUDHSM_ était autorisé (§10.1) mais aucune variable n'était listée (§10.2). Ce type d'incohérence génère des faux positifs en acceptabilité.
-
Le fail-fast doit être explicite et testé — L'écart E-04 montrait que
readSecretsretournait{}silencieusement. Le comportement fail-fast doit être vérifié par des tests dédiés. -
Les variables système sont un cas particulier — process.env contient des variables système (PATH, HOME) qui ne peuvent pas être rejetées. Cette réalité technique doit être documentée dans la spec.
Document généré le 2025-12-29 Version : 1.0