capitalisation: triage 95_a_capitaliser + création domaine infra

Triage des 27 propositions du buffer de capitalisation (skill
capitalisation-triage), avec vérification des doublons contre la base.

Intégré dans knowledge/ (23 entrées):
- backend: redis (compensation incrBy non-atomique), nestjs (injection
  cassée sous tsx watch; guard write mode dégradé), async (test rollback
  pipeline multi-fichiers), contracts (idempotence POST), auth (disclosure
  comptes soft-deleted), prisma (index partial soft-delete), llm-providers
  (nouveau: OAuth vs API key, prompt caching).
- frontend: tests (garde-fous parking Later), navigation (fichiers
  non-route sous src/app Expo Router), general (type client vs payload
  backend), state (fallback catch-all mapping DB→UI).
- workflow: story-tracking (statut BMAD vs narratif obsolète).
- product: general (nouveau: doc feature store sans UI).
- infra: NOUVEAU DOMAINE (traefik, tailscale, docker, docker-networking,
  reverse-proxy-paths, sidecar tailscale) + 00_INDEX.md.

Autres:
- 90_debug_et_postmortem.md: post-mortem réseau Docker partagé hors compose.
- Rejeté 3 doublons (types enum contracts, getter PrismaService, $transaction).
- Buffer 95_a_capitaliser.md purgé et restauré à son état initial.
- _projects.conf: MAJ statuts epics + ajout app-rl799.
This commit is contained in:
MaksTinyWorkshop
2026-06-25 10:31:22 +02:00
parent 1c876309f1
commit ef24d85d57
31 changed files with 1042 additions and 27 deletions
+39 -3
View File
@@ -2,10 +2,10 @@
title: Backend — Risques & vigilance : Auth
domain: backend
bucket: risques
tags: [auth, guards, request-user, sessions, admin]
tags: [auth, guards, request-user, sessions, admin, enumeration, soft-delete]
applies_to: [implementation, review, debug]
severity: high
validated_on: 2026-04-07
validated_on: 2026-06-25
source_projects: [app-alexandrie, RL799_V2]
---
@@ -458,4 +458,40 @@ Quand on prévoit de supprimer un flag auth profondément câblé :
**Anti-pattern** : déprécier en douceur en gardant le flag avec un commentaire `// @deprecated` sans supprimer les usages. Le code mort s'accumule, les futurs devs hésitent à le nettoyer ("pourquoi c'est encore là ?"), la dépréciation ne se finit jamais.
- Contexte technique : auth / refactor schema — RL799_V2 28-04-2026
- Contexte technique : auth / refactor schema — RL799_V2 28-04-2026
---
<a id="risque-disclosure-comptes-soft-deleted-login"></a>
## Information disclosure sur comptes soft-deleted dans `login()`
### Risques
- Retourner un code d'erreur distinct (ex : `ACCOUNT_DELETED`) pour les comptes supprimés dans `login()` permet l'**énumération** : un attaquant distingue « compte supprimé » de « identifiants invalides » par email.
- Complément du pattern anti-énumération (cf. `pattern-...anti-énumération` dans `patterns/auth.md`) appliqué au cas soft-delete.
### Symptômes
- `login()` lève `ACCOUNT_DELETED` au lieu de `INVALID_CREDENTIALS` pour un compte soft-deleted
- L'existence (et le statut) d'un compte fuite via la réponse d'authentification
### Bonnes pratiques / mitigations
```typescript
// ❌ DANGEREUX — révèle l'existence d'un compte supprimé
if (user.deletedAt !== null) {
throw new UnauthorizedException({ error: { code: 'ACCOUNT_DELETED' } });
}
// ✅ CORRECT — même code que des identifiants invalides
if (user.deletedAt !== null) {
throw new UnauthorizedException({
error: { code: 'INVALID_CREDENTIALS', message: 'Email ou mot de passe invalide.' },
});
}
```
- **Règle** : dans `login()`, toujours répondre `INVALID_CREDENTIALS` pour un compte soft-deleted — jamais un code spécifique.
- **Nuance** : un code `ACCOUNT_DELETED` reste acceptable dans un flux `exchange()` OAuth, où le provider a déjà confirmé l'identité (pas d'énumération possible côté attaquant).
- Contexte technique : auth / soft-delete / anti-énumération — app-alexandrie 13-04-2026