Files
roadwave/docs/domains/recommendation/features/interest-gauges/degradation-temporelle.feature
jpgiannetti 5e5fcf4714 refactor(docs): réorganiser la documentation selon principes DDD
Réorganise la documentation du projet selon les principes du Domain-Driven Design (DDD) pour améliorer la cohésion, la maintenabilité et l'alignement avec l'architecture modulaire du backend.

**Structure cible:**
```
docs/domains/
├── README.md (Context Map)
├── _shared/ (Core Domain)
├── recommendation/ (Supporting Subdomain)
├── content/ (Supporting Subdomain)
├── moderation/ (Supporting Subdomain)
├── advertising/ (Generic Subdomain)
├── premium/ (Generic Subdomain)
└── monetization/ (Generic Subdomain)
```

**Changements effectués:**

Phase 1: Création de l'arborescence des 7 bounded contexts
Phase 2: Déplacement des règles métier (01-19) vers domains/*/rules/
Phase 3: Déplacement des diagrammes d'entités vers domains/*/entities/
Phase 4: Déplacement des diagrammes flux/états/séquences vers domains/*/
Phase 5: Création des README.md pour chaque domaine
Phase 6: Déplacement des features Gherkin vers domains/*/features/
Phase 7: Création du Context Map (domains/README.md)
Phase 8: Mise à jour de mkdocs.yml pour la nouvelle navigation
Phase 9: Correction automatique des liens internes (script fix-markdown-links.sh)
Phase 10: Nettoyage de l'ancienne structure (regles-metier/, diagrammes/, features/)

**Configuration des tests:**
- Makefile: godog run docs/domains/*/features/
- scripts/generate-bdd-docs.py: features_dir → docs/domains

**Avantages:**
 Cohésion forte: toute la doc d'un domaine au même endroit
 Couplage faible: domaines indépendants, dépendances explicites
 Navigabilité améliorée: README par domaine = entrée claire
 Alignement code/docs: miroir de backend/internal/
 Onboarding facilité: exploration domaine par domaine
 Tests BDD intégrés: features au plus près des règles métier

Voir docs/REFACTOR-DDD.md pour le plan complet.
2026-02-07 17:15:02 +01:00

297 lines
12 KiB
Gherkin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# language: fr
Fonctionnalité: API - Pas de dégradation temporelle
En tant qu'API backend
Je veux que les jauges n'évoluent que par les actions utilisateur
Afin d'avoir un comportement prévisible sans automatisme caché
Contexte:
Étant donné que l'API RoadWave est disponible
Et que la base de données PostgreSQL est accessible
Scénario: API ne dégrade jamais les jauges automatiquement
Étant donné qu'un utilisateur "user123" a une jauge "Économie" à 80% en base
Et que la colonne updated_at = "2026-01-01T10:00:00Z"
Quand 30 jours s'écoulent sans activité
Et je GET /api/v1/users/user123/interest-gauges le "2026-02-01T10:00:00Z"
Alors le statut de réponse est 200
Et la jauge "Économie" est toujours à 80%
Et aucune dégradation temporelle n'a été appliquée
Et la colonne updated_at n'a pas changé
Scénario: Aucun cron job de dégradation n'existe
Étant donné que le système vérifie les tâches cron planifiées
Quand je liste tous les cron jobs du backend
Alors aucun job nommé "degrade_interest_gauges" n'existe
Et aucun job périodique ne modifie la table interest_gauges
Et aucune ressource CPU n'est consommée pour la dégradation
Scénario: API GET jauges après 6 mois d'inactivité
Étant donné qu'un utilisateur "user123" a les jauges suivantes:
| catégorie | niveau | updated_at |
| Automobile | 75% | 2025-08-01T10:00:00 |
| Voyage | 60% | 2025-08-01T10:00:00 |
| Musique | 45% | 2025-08-01T10:00:00 |
Et qu'il ne se connecte pas pendant 6 mois
Quand je GET /api/v1/users/user123/interest-gauges le "2026-02-01T10:00:00Z"
Alors le statut de réponse est 200
Et les jauges sont exactement les mêmes:
| catégorie | niveau |
| Automobile | 75% |
| Voyage | 60% |
| Musique | 45% |
Et aucune modification n'a été appliquée
Scénario: Évolution par actions utilisateur uniquement
Étant donné qu'un utilisateur "user123" a une jauge "Économie" à 80%
Et qu'il skip 50 contenus "Économie" en 1 an
Quand je calcule l'évolution via les events
Alors la jauge "Économie" descend via les skips:
| action | impact | nouveau_niveau |
| 50 skips × -0.5%| -25% | 55% |
Et la dégradation vient des actions, pas du temps
Et la colonne updated_at reflète la date du dernier skip
Scénario: API POST réinitialiser centres d'intérêt
Étant donné qu'un utilisateur "user123" a des jauges personnalisées:
| catégorie | niveau |
| Automobile | 75% |
| Voyage | 60% |
| Économie | 34% |
| Sport | 88% |
Quand je POST /api/v1/users/user123/interest-gauges/reset
"""json
{
"confirmation": true
}
"""
Alors le statut de réponse est 200
Et la réponse contient:
"""json
{
"message": "Vos centres d'intérêt ont été réinitialisés",
"previous_gauges_saved": true,
"new_gauges": {
"all_categories": 50
}
}
"""
Et en base de données, toutes les jauges de "user123" sont à 50%:
| catégorie | niveau |
| Automobile | 50 |
| Voyage | 50 |
| Économie | 50 |
| Sport | 50 |
| Musique | 50 |
| Technologie | 50 |
| Santé | 50 |
| Politique | 50 |
| Cryptomonnaie | 50 |
| Culture générale | 50 |
| Famille | 50 |
| Amour | 50 |
Scénario: API sauvegarde jauges précédentes avant réinitialisation
Étant donné qu'un utilisateur "user123" a des jauges personnalisées
Quand je POST /api/v1/users/user123/interest-gauges/reset
"""json
{
"confirmation": true
}
"""
Alors le statut de réponse est 200
Et une ligne est insérée dans interest_gauges_snapshots:
| user_id | snapshot_type | snapshot_date | gauges_json |
| user123 | manual_reset | 2026-02-02T14:00:00 | {"Automobile": 75, "Voyage": 60, ...} |
Et l'historique permet de restaurer si besoin
Scénario: API rejette réinitialisation sans confirmation
Quand je POST /api/v1/users/user123/interest-gauges/reset
"""json
{
"confirmation": false
}
"""
Alors le statut de réponse est 400
Et la réponse contient:
"""json
{
"error": "CONFIRMATION_REQUIRED",
"message": "Vous devez confirmer la réinitialisation"
}
"""
Et les jauges ne sont pas modifiées
Scénario: API recommandations après réinitialisation
Étant donné qu'un utilisateur "user123" avait "Économie" à 85%
Et qu'il réinitialise ses jauges (toutes à 50%)
Quand je POST /api/v1/recommendations
"""json
{
"user_id": "user123",
"latitude": 48.8566,
"longitude": 2.3522,
"limit": 10
}
"""
Alors le statut de réponse est 200
Et les recommandations utilisent 50% pour toutes les catégories
Et plus aucun biais "Économie" n'est appliqué
Et la géolocalisation redevient le critère principal
Scénario: Historique d'écoute conservé après réinitialisation
Étant donné qu'un utilisateur "user123" a écouté 500 contenus
Et que la table listening_history contient 500 lignes pour "user123"
Quand je POST /api/v1/users/user123/interest-gauges/reset
Alors le statut de réponse est 200
Et la table listening_history conserve toujours les 500 lignes
Et aucune donnée d'historique n'est supprimée
Et l'utilisateur peut toujours consulter ses anciens contenus écoutés
Scénario: API GET historique après réinitialisation
Étant donné qu'un utilisateur "user123" a réinitialisé ses jauges
Quand je GET /api/v1/users/user123/listening-history
Alors le statut de réponse est 200
Et la réponse contient tous les anciens contenus écoutés
Et l'historique est intact
Scénario: API enregistre timestamp réinitialisation
Étant donné qu'un utilisateur "user123" réinitialise ses jauges
Quand je POST /api/v1/users/user123/interest-gauges/reset
Alors en base de données, la table users est mise à jour:
| user_id | interest_gauges_reset_at | reset_count |
| user123 | 2026-02-02T14:00:00Z | 1 |
Et un compteur permet de tracker les réinitialisations multiples
Scénario: API permet réinitialisations multiples
Étant donné qu'un utilisateur "user123" a déjà réinitialisé une fois
Quand je POST /api/v1/users/user123/interest-gauges/reset une 2ème fois
Alors le statut de réponse est 200
Et le reset_count passe à 2
Et toutes les jauges reviennent à 50%
Scénario: API n'envoie jamais de suggestion de réinitialisation
Étant donné qu'un utilisateur "user123" n'a pas utilisé l'app depuis 1 an
Quand je GET /api/v1/users/user123/notifications
Alors le statut de réponse est 200
Et aucune notification "Réinitialiser vos centres d'intérêt" n'est présente
Et le système ne suggère jamais de réinitialisation automatique
Scénario: API GET statistiques respect historique utilisateur
Étant donné qu'un utilisateur "user123" aime "Cryptomonnaie" depuis 2 ans
Et que sa jauge est à 90%
Et qu'il n'a pas écouté de contenu "Cryptomonnaie" depuis 6 mois
Quand je GET /api/v1/users/user123/interest-gauges
Alors le statut de réponse est 200
Et la jauge "Cryptomonnaie" est toujours à 90%
Et la réponse contient:
"""json
{
"gauges": [
{
"category": "Cryptomonnaie",
"level": 90,
"last_updated": "2025-08-02T10:00:00Z",
"days_since_update": 183,
"preserved": true
}
]
}
"""
Et le système respecte l'historique des goûts
Scénario: API métrique temps écoulé sans modifier la jauge
Étant donné qu'un utilisateur "user123" a une jauge "Sport" à 65%
Et que la dernière modification date de 90 jours
Quand je GET /api/v1/users/user123/interest-gauges/sport
Alors le statut de réponse est 200
Et la réponse contient:
"""json
{
"category": "Sport",
"level": 65,
"last_updated": "2025-11-03T12:00:00Z",
"days_since_update": 90
}
"""
Et la métrique days_since_update est informative uniquement
Et elle ne modifie jamais la jauge
Scénario: Requête SQL n'utilise jamais de calcul temporel
Étant donné que je trace les requêtes SQL du backend
Quand je GET /api/v1/users/user123/interest-gauges
Alors la requête SQL exécutée est:
"""sql
SELECT category, level, updated_at
FROM interest_gauges
WHERE user_id = $1
"""
Et aucune clause WHERE avec date/timestamp n'est présente
Et aucune fonction NOW(), CURRENT_TIMESTAMP, ou DATEDIFF n'est utilisée
Et le calcul est minimal (simple SELECT)
Scénario: API coût CPU minimal - pas de calcul de dates
Étant donné que 10000 utilisateurs consultent leurs jauges simultanément
Quand les requêtes /api/v1/users/{id}/interest-gauges sont exécutées
Alors aucun calcul de date n'est nécessaire
Et aucun appel à time.Now() ou time.Since() n'est fait
Et le coût CPU par requête est < 1ms
Et aucune dégradation de performance liée aux dates
Scénario: API pas de risque de bug fuseau horaire
Étant donné qu'aucune logique temporelle n'existe
Quand un utilisateur change de fuseau horaire (Paris Tokyo)
Alors ses jauges ne sont pas affectées
Et aucun bug de conversion UTC/local ne peut survenir
Et le comportement reste déterministe
Scénario: Audit log réinitialisation manuelle
Étant donné qu'un utilisateur "user123" réinitialise ses jauges
Quand je POST /api/v1/users/user123/interest-gauges/reset
Alors une ligne est insérée dans audit_log:
| user_id | action | timestamp | details |
| user123 | interest_gauges_reset | 2026-02-02T14:00:00 | {"previous_snapshot_id": 42} |
Et l'audit permet de tracer toutes les réinitialisations
Scénario: API empêche réinitialisation trop fréquente
Étant donné qu'un utilisateur "user123" a réinitialisé il y a 10 minutes
Quand je POST /api/v1/users/user123/interest-gauges/reset
Alors le statut de réponse est 429
Et la réponse contient:
"""json
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Vous ne pouvez réinitialiser qu'une fois par heure",
"retry_after_seconds": 3000
}
"""
Scénario: API documentation endpoints réinitialisation
Quand je GET /api/v1/openapi.json
Alors le endpoint POST /api/v1/users/{id}/interest-gauges/reset est documenté:
"""yaml
/users/{id}/interest-gauges/reset:
post:
summary: Réinitialise toutes les jauges à 50%
description: |
Remet toutes les jauges d'intérêt à leur valeur par défaut (50%).
Cette action est manuelle et requiert une confirmation.
Les jauges précédentes sont sauvegardées.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
confirmation:
type: boolean
description: Doit être true
responses:
200:
description: Réinitialisation réussie
400:
description: Confirmation manquante
429:
description: Trop de réinitialisations
"""