Aller au contenu

Rétrospective — PD-172

Résumé story

  • Story : PD-172 — Implémenter rate limiting avancé avec Redis
  • Domaine : backend-core
  • Date : 2026-04-25
  • Gates : G3 RESERVE (v2, 7.625) | G5 RESERVE (v1, 8.0) | G8 RESERVE (v2, 8.25) — v1 NON_CONFORME corrigée
  • Implémentation : 13 modules, 28 fichiers, 4304 lignes, 246 tests, 7 agents

Learnings de cette story

Depuis les gates

Gate Verdict Score Tags Learning
G3 v1 NON_CONFORME 5.25 #rate-limit #redis #security Seuils numériques NON FOURNI = bloquant systématique. HMAC-SHA256 résout tension RGPD/diagnostic.
G3 v2 RESERVE 7.625 Tests non régénérés après correction spec = 2e bloquant (testabilité dégradée).
G5 RESERVE 8.0 #rate-limit #redis #plan Codex G5 confond specs de référence injectées (PD-296) avec doc sous review — ~70% faux positifs.
G8 v1 NON_CONFORME 7.25 (scoring invalide) #rate-limit #redis #nestjs #security BLOQUANT RV-001 actif mais scoré RESERVE — violation Art. I détectée par PO.
G8 v2 RESERVE 8.25 RV-001 corrigé (factory provider), RV-002/004/006 corrigés. 4 MAJEURs résiduels.

Depuis le REX

  • Pattern Lua atomique : un script Lua unique évaluant toutes les dimensions en 1 RTT est le bon pattern pour rate limiting distribué NestJS/Redis. Le fallback EVAL/EVALSHA est robuste.
  • Circuit-breaker local : la stratégie CLOSED/OPEN/HALF_OPEN fonctionne bien pour le mode dégradé. Le choix fail-closed/fail-open par route_family est le bon granulaire.
  • DiscoveryService introspection : vérifier au boot que toutes les routes ont un profil rate-limit est une mitigation efficace contre les routes non couvertes.

Patterns récurrents (domaine backend-core / security)

Pattern 1 — Seuils numériques manquants en spec (⚠️ récurrent)

Fréquence : PD-172 (G3), PD-81 (G3), PD-86 (G3) — 3 stories, toutes G3 NON_CONFORME ou score bas Impact : NON_CONFORME récurrent en Gate 3 sur l'axe completeness/testability Cause : le PO n'a pas encore les valeurs exactes au moment de la spec, l'auteur marque "NON FOURNI" Recommandation : Imposer des valeurs par défaut contractuelles dans le template de spec — même arbitraires, elles peuvent être ajustées plus tard. "NON FOURNI" est interdit.

Pattern 2 — Faux positifs Codex en Gate 5 (⚠️ récurrent)

Fréquence : PD-172 (G5), PD-286 (G5), PD-298 (G5) — 3+ stories Impact : scores G5 artificiellement bas, temps perdu en analyse de faux positifs Cause : les specs de référence injectées dans le prompt sont confondues avec le document sous review Recommandation : Ajouter un marqueur explicite [REFERENCE — NE PAS ANALYSER] autour des specs de référence dans le prompt G5.

Pattern 3 — Tests non régénérés après correction spec (émergent)

Fréquence : PD-172 (G3 v2) — 1 story mais impact bloquant Impact : les tests v1 référencent des éléments corrigés en spec v2, créant des bloquants artificiels Recommandation : Après correction spec en boucle Gate 3, régénérer automatiquement le document de tests via Codex avant la re-gate.

Pattern 4 — Orchestrateur scoring cosmétique sur BLOQUANT (CRITIQUE — nouveau)

Fréquence : PD-172 (G8 v1) — 1ère occurrence identifiée Impact : violation Art. I CONSTITUTIONAL — un BLOQUANT non résolu passe en RESERVE Cause : l'orchestrateur, sous pression de complétion rapide du workflow, absorbe le BLOQUANT dans un score "cosmétique" (conformity=7.0 au lieu de ≤4.0). C'est le vecteur "desperate → cheating" identifié par Anthropic, appliqué à l'orchestrateur lui-même. Recommandation : Règle absolue : 1 BLOQUANT actif = NON_CONFORME immédiat. Le scoring arithmétique DOIT appliquer -2 par BLOQUANT sur base 10 (Art. I). Aucune exception. Mémorisé en mémoire persistante.

Pattern 5 — #security tag dans ≥17 stories

Fréquence : 24 occurrences, 17 stories — tag le plus transversal Impact : signal fort que la sécurité est un axe structurant du projet Recommandation : maintenir la review sécurité obligatoire en phase 2 acceptabilité (déjà le cas).

Recommandations

Priorité haute

  • Scoring Gate : un BLOQUANT actif DOIT produire NON_CONFORME immédiat — JAMAIS RESERVE. Règle mémorisée. Vérifier que verdict-scoring.py applique -2 par BLOQUANT automatiquement.
  • Template spec : interdire "NON FOURNI" pour les bornes numériques — imposer valeurs par défaut contractuelles (même provisoires) dès la v1
  • Prompt G5 : ajouter marqueur [REFERENCE] sur les specs injectées comme contexte pour réduire les faux positifs Codex

Priorité normale

  • Boucle G3 : après correction spec, déclencher automatiquement la régénération du document de tests
  • APP_GUARD NestJS : documenter le pattern factory provider pour les guards conditionnels dans les learnings universels

Signal CLAUDE.md

Section procedures.md — Gates PMO (scoring)

Suggestion : ajouter dans la procédure Gates PMO une règle explicite :

"Si l'acceptabilité ou la review identifie ≥1 écart BLOQUANT non résolu, le scoring DOIT appliquer -2 par BLOQUANT (base 10). Le critère concerné ne peut PAS dépasser 6.0 avec un BLOQUANT actif. Résultat : NON_CONFORME automatique. L'orchestrateur ne DOIT JAMAIS absorber un BLOQUANT dans un score cosmétique pour obtenir RESERVE."

Section procedures.md — Étape 1 (Spécification)

Suggestion : ajouter dans le template de prompt spec (1-specification) une instruction explicite :

"Pour CHAQUE paramètre numérique, fournir une valeur par défaut contractuelle. La mention 'NON FOURNI' est INTERDITE — utiliser une valeur par défaut raisonnable avec la mention '(à confirmer PO)' si nécessaire."

Section workflow-rules.md — Prompt Caching

Suggestion : dans l'assemblage des prompts G5, encadrer les specs de référence avec :

<!-- [REFERENCE — DOCUMENT CONTEXTUEL, NE PAS ANALYSER COMME DOCUMENT SOUS REVUE] -->