PD-19 — Retour d'expérience (REX)¶
1. Résumé exécutif¶
| Métrique | Valeur |
|---|---|
| Objectif initial | Configurer CORS, security headers et rate limiting global |
| Résultat obtenu | Conforme — 12/12 invariants couverts |
| Verdict final | GO (Gate 8) |
| Tests contractuels | 61/61 passés |
2. Métriques de convergence¶
2.1 Temps et itérations¶
| Étape | Durée estimée | Durée réelle | Itérations | Écart |
|---|---|---|---|---|
| 0 - Besoin | 30 min | 30 min | 1 | 0% |
| 1 - Spécification | 2h | 2h | 1 | 0% |
| 2 - Tests | 1h | 1h | 1 | 0% |
| 3 - Gate spec | 1h | 3h | 2 | +200% |
| 4 - Plan | 1h | 1.5h | 1 | +50% |
| 5 - Gate plan | 1h | 2h | 2 | +100% |
| 6 - Implémentation | 4h | 5h | 1 | +25% |
| 7 - Acceptabilité | 2h | 2h | 2 | 0% |
| 8 - Gate acceptabilité | 1h | 1.5h | 1 | +50% |
| 9 - REX | 30 min | 30 min | 1 | 0% |
| TOTAL | ~14h | ~18.5h | 13 | +32% |
2.2 Scores de convergence par gate¶
| Gate | Score v1 | Score final | Delta | Itérations |
|---|---|---|---|---|
| Gate 3 | 5.25/10 | 7.50/10 | +2.25 | 2 |
| Gate 5 | 7.75/10 | 8.50/10 | +0.75 | 2 |
| Gate 8 | 8.0/10 | 8.0/10 | 0 | 1 |
2.3 Écarts par catégorie¶
| Catégorie d'écart | Gate 3 | Gate 5 | Gate 8 | Total |
|---|---|---|---|---|
| ECT (complétude/testabilité) | 7 | 0 | 2 | 9 |
| DIV (divergence spec/impl) | 5 | 1 | 0 | 6 |
| AMB (ambiguïté) | 2 | 2 | 0 | 4 |
| SEC (sécurité) | 1 | 0 | 1 | 2 |
| PERF (performance) | 0 | 0 | 0 | 0 |
| TOTAL écarts | 15 | 3 | 3 | 21 |
3. Points fluides¶
Ce qui a bien fonctionné : - Extension de l'existant : Helmet v7.1.0, CORS natif, RateLimitService Redis — aucune nouvelle dépendance requise - ConfigModule avec validation Joi : fail-fast naturel, multi-env sans modification de code - Pattern middleware NestJS : séparation claire des responsabilités (SecurityHeaders → CORS → RateLimit) - Code contracts YAML : contrat d'interface explicite accélérant l'implémentation et les tests - Correction automatique Gate 3→v2 : delta +2.25 en une itération (prompt de correction complet)
4. Points difficiles¶
Obstacles rencontrés : - Spec v1 rejetée : 4 paramètres contractuels critiques absents (socle headers, CORS, seuils limitation, eIDAS) - 8 règles non testables : critères d'acceptation non mesurables — score testability 4/10 - Trust proxy et X-Forwarded-For : vulnérabilité XFF bypass identifiée en review sécurité (SEC-01 HIGH) - Validation IPv6 permissive : regex insuffisante (SEC-02 HIGH) - Headers sur erreurs : res.on('finish') nécessaire pour garantir les headers sur 404/500/429
5. Hypothèses révélées tardivement¶
Hypothèses non explicites découvertes en cours de workflow : - eIDAS non testable HTTP — découverte à l'étape 3 : les exigences de valeur probatoire (signature, horodatage qualifié) ne sont pas observables au niveau HTTP pur → exclusion explicite du périmètre - Rétention 90 jours = infra — découverte à l'étape 5 : la rétention des logs de sécurité est une configuration infrastructure (ELK/Loki lifecycle) et non applicative - Vary: Origin obligatoire — découverte à l'étape 8 : header nécessaire pour éviter les problèmes de cache CORS multi-origines
6. Invariants complexes¶
Invariants difficiles à implémenter ou sensibles aux régressions : - INV-01 (socle headers) + INV-11 (headers sur erreurs) — TC-NOM-05, TC-ERR-02 : garantir les headers même sur les exceptions non gérées via res.on('finish') plutôt que dans le middleware - INV-06 (résolution IP) — TC-INT-01 : chaîne de proxy de confiance avec Express trust proxy et validation de X-Forwarded-For - INV-07 (format 429) — TC-ERR-04 : corps JSON exact {"error":"rate_limited","message":"Too many requests","retryAfter":<seconds>}
7. Dette technique¶
Compromis acceptés et non bloquants : - ECT-01 (indépendance métier) — impact: faible : preuve par analyse code, pas par test explicite ; à documenter dans architecture - ECT-02 (format logs) — impact: faible : format JSON UTC couvert par configuration du transport (Winston/Pino), pas de test unitaire dédié - ECT-04 (Vary: Origin) — impact: faible : implémenté via res.setHeader() au lieu de res.vary() ; amélioration cosmétique future - TC-NOM-06 absent — impact: moyen : pas de test explicite de la journalisation ; couvert par tests d'intégration implicites
8. Risques résiduels¶
| Risque | Type | Probabilité | Impact | Mitigation |
|---|---|---|---|---|
| Redis indisponible → fail-open | tech | faible | moyen | Monitoring alerting + fallback in-memory (dégradé) |
| X-Forwarded-For forgé hors trust chain | sec | faible | moyen | Validation stricte TRUSTED_PROXIES |
| Cache preflight trop long (600s prod) | ops | faible | faible | Ajustable via configuration |
| RGPD rétention IP 90 jours | legal | moyen | moyen | Base légale intérêt légitime + politique protection données |
9. Patterns récurrents détectés¶
9.1 Patterns confirmés (déjà vus dans d'autres stories)¶
- Fail-fast config sécurité — aussi dans PD-22 (config Vault), PD-240 (account deletion)
- Validation croisée LLM — ChatGPT review / Claude implémentation — pattern standard du workflow
- Rate limiting Redis atomique — aussi dans PD-238 (MFA), guards auth existants
- Code contracts YAML — standard depuis PD-19
9.2 Nouveaux patterns identifiés¶
- res.on('finish') pour headers universels — à surveiller : garantit les headers même sur exceptions non catchées
- Trust proxy Express + TRUSTED_PROXIES env — pattern à documenter pour tous les rate limitings
- CORS contractuel sans wildcard — origines explicites par environnement, pas de
*même en dev
10. Améliorations du workflow¶
10.1 Améliorations des prompts/templates¶
| Fichier | Amélioration suggérée | Priorité |
|---|---|---|
docs/prompts/1 Specification.md | Ajouter checklist : "tous les paramètres contractuels ont des valeurs explicites et testables" | haute |
docs/prompts/3 Spécification – Review.md | Ajouter critère : "chaque invariant a au moins un observable mesurable" | moyenne |
docs/templates/PD-XX-tests.md | Ajouter section "Règles non testables (justification)" | moyenne |
10.2 Améliorations des agents¶
| Agent | Amélioration suggérée | Justification |
|---|---|---|
| agent-adversarial | Ajouter check XFF/trust proxy dans review sécurité | SEC-01 identifié tardivement |
| agent-metier | Clarifier la frontière périmètre testable HTTP vs eIDAS | Éviter les ambiguïtés eIDAS |
10.3 Améliorations du processus¶
- Synchroniser PD-XX-tests.md après correction spec : le document de tests v1 n'a pas été mis à jour après la correction spec v2 (DIV-02 Gate 3 v2)
- Ajouter ticket suivi pour réserves infra : la rétention 90 jours (DIV-04 Gate 5) nécessite un ticket infra séparé
11. Enseignements clés¶
-
Paramètres contractuels explicites dès la spec — Les critères d'acceptation non mesurables (socle headers sans liste, CORS sans origines) sont les premières causes de rejet Gate 3. Définir les valeurs exactes dès l'étape 1.
-
Headers sur erreurs = res.on('finish') — Les security headers doivent être appliqués même sur les réponses d'erreur. Le pattern
res.on('finish')garantit cette couverture là où les middlewares classiques échouent. -
Trust proxy est une surface d'attaque — La résolution IP via X-Forwarded-For sans validation de la chaîne de confiance permet le bypass du rate limiting. Configurer
trust proxyde manière restrictive. -
Faux positifs reviews LLM = lecture partielle — Les 2 faux positifs Gate 5 (credentials/exposedHeaders "absents") étaient causés par la lecture de résumés plutôt que des documents complets. Injecter les documents inline.
-
Rétention logs = configuration infra — La rétention de 90 jours (INV-09) n'est pas codée dans l'application mais dans la configuration du système de logging (ELK lifecycle). Documenter comme prérequis déploiement.
12. Métriques cumulatives¶
| Métrique | Cette story | Moyenne projet | Tendance |
|---|---|---|---|
| Temps total | 18.5h | 16h | ↑ |
| Itérations gates | 5 | 4.5 | → |
| Écarts totaux | 21 | 18 | ↑ |
| Score convergence moyen | 7.75/10 | 7.9/10 | → |
Document produit par le workflow de gouvernance IA — Étape 9 (Claude mode créatif) Date : 2026-02-10