From e63603551d139205b98cfba415304084a9ac05e7 Mon Sep 17 00:00:00 2001 From: jpgiannetti Date: Sat, 7 Feb 2026 21:38:02 +0100 Subject: [PATCH] =?UTF-8?q?docs(shared):=20ajouter=20documentation=20compl?= =?UTF-8?q?=C3=A8te=20entit=C3=A9s,=20=C3=A9tats=20et=20s=C3=A9quences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Entités: 7 nouveaux schémas (sessions, devices, consents, location-history, interest-gauges, reports, exports) - États: 5 diagrammes lifecycles (compte, contenu, session, signalement, export) - Séquences: 6 flows (auth, refresh token, modération, signalement, export, suppression) - Renommage: modele-global.md → entities-overview.md - MkDocs: organisation hiérarchique par catégories Format concis: diagrammes Mermaid + règles essentielles uniquement --- docs/TECHNICAL.md | 3 +- docs/domains/_shared/entities/consents.md | 40 ++++ docs/domains/_shared/entities/devices.md | 45 ++++ .../_shared/entities/entities-overview.md | 216 ++++++++++++++++++ docs/domains/_shared/entities/exports.md | 52 +++++ .../_shared/entities/interest-gauges.md | 45 ++++ .../_shared/entities/location-history.md | 47 ++++ .../domains/_shared/entities/modele-global.md | 69 ------ docs/domains/_shared/entities/reports.md | 60 +++++ docs/domains/_shared/entities/sessions.md | 45 ++++ .../_shared/sequences/account-deletion.md | 48 ++++ .../_shared/sequences/authentication-flow.md | 42 ++++ .../_shared/sequences/content-moderation.md | 44 ++++ .../_shared/sequences/content-report.md | 51 +++++ docs/domains/_shared/sequences/data-export.md | 49 ++++ .../_shared/sequences/token-refresh.md | 38 +++ .../_shared/states/content-lifecycle.md | 39 ++++ .../_shared/states/export-lifecycle.md | 38 +++ .../_shared/states/report-lifecycle.md | 32 +++ .../_shared/states/session-lifecycle.md | 29 +++ .../_shared/states/user-account-lifecycle.md | 31 +++ mkdocs.yml | 81 ++++--- 22 files changed, 1047 insertions(+), 97 deletions(-) create mode 100644 docs/domains/_shared/entities/consents.md create mode 100644 docs/domains/_shared/entities/devices.md create mode 100644 docs/domains/_shared/entities/entities-overview.md create mode 100644 docs/domains/_shared/entities/exports.md create mode 100644 docs/domains/_shared/entities/interest-gauges.md create mode 100644 docs/domains/_shared/entities/location-history.md delete mode 100644 docs/domains/_shared/entities/modele-global.md create mode 100644 docs/domains/_shared/entities/reports.md create mode 100644 docs/domains/_shared/entities/sessions.md create mode 100644 docs/domains/_shared/sequences/account-deletion.md create mode 100644 docs/domains/_shared/sequences/authentication-flow.md create mode 100644 docs/domains/_shared/sequences/content-moderation.md create mode 100644 docs/domains/_shared/sequences/content-report.md create mode 100644 docs/domains/_shared/sequences/data-export.md create mode 100644 docs/domains/_shared/sequences/token-refresh.md create mode 100644 docs/domains/_shared/states/content-lifecycle.md create mode 100644 docs/domains/_shared/states/export-lifecycle.md create mode 100644 docs/domains/_shared/states/report-lifecycle.md create mode 100644 docs/domains/_shared/states/session-lifecycle.md create mode 100644 docs/domains/_shared/states/user-account-lifecycle.md diff --git a/docs/TECHNICAL.md b/docs/TECHNICAL.md index a54412c..a9557b3 100644 --- a/docs/TECHNICAL.md +++ b/docs/TECHNICAL.md @@ -30,8 +30,7 @@ | **Modération** | Architecture modération | [ADR-023](adr/023-architecture-moderation.md) | | **Monitoring** | Prometheus + Grafana | [ADR-024](adr/024-monitoring-observabilite.md) | | **Secrets** | Vault + sealed secrets | [ADR-025](adr/025-securite-secrets.md) | -| **Notifications géo** | Push + geofencing | [ADR-017](adr/017-notifications-geolocalisees.md) | -| **Notifications push** | FCM + APNS | [ADR-018](adr/018-notifications-push.md) | +| **Notifications** | Push géolocalisées (FCM/APNS + geofencing) | [ADR-017](adr/017-notifications-geolocalisees.md) | --- diff --git a/docs/domains/_shared/entities/consents.md b/docs/domains/_shared/entities/consents.md new file mode 100644 index 0000000..73997f4 --- /dev/null +++ b/docs/domains/_shared/entities/consents.md @@ -0,0 +1,40 @@ +# User Consents + +📖 Consentements RGPD avec historique et versioning + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ USER_CONSENTS : "donne" + + USER_CONSENTS { + uuid id PK + uuid user_id FK + string consent_type + string consent_version + boolean accepted + timestamp given_at + inet ip_address + string user_agent + } +``` + +## Légende + +**Types de consentement** : +- `geolocation_precise` : Géolocalisation GPS précise (obligatoire pour contenu hyperlocal) +- `analytics` : Analytics Matomo (optionnel) +- `push_notifications` : Notifications push (optionnel) +- `cookies_analytics` : Cookies analytiques (optionnel) + +**Versioning** : +- Chaque changement de CGU/politique = nouvelle version +- Historique complet conservé (preuve légale) +- Format version : `v1.0`, `v2.0`, etc. + +**Conformité RGPD** : +- Granularité : fonctionnel / analytique / marketing +- Consentement libre et éclairé +- Révocable à tout moment +- Historique = preuve en cas de contrôle CNIL diff --git a/docs/domains/_shared/entities/devices.md b/docs/domains/_shared/entities/devices.md new file mode 100644 index 0000000..dcd8fd9 --- /dev/null +++ b/docs/domains/_shared/entities/devices.md @@ -0,0 +1,45 @@ +# Devices + +📖 Appareils de confiance et gestion multi-device + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ DEVICES : "possède" + DEVICES ||--o{ SESSIONS : "a" + + DEVICES { + uuid id PK + uuid user_id FK + string device_name + string os + string browser + string device_type + boolean is_trusted + timestamp trusted_until + timestamp first_seen_at + timestamp last_seen_at + inet last_ip + string last_city + string last_country_code + } +``` + +## Légende + +**Types d'appareil** : +- `mobile` : Smartphone Android/iOS +- `tablet` : Tablette +- `desktop` : Ordinateur +- `car` : Système embarqué (CarPlay/Android Auto) + +**Appareil de confiance** : +- Option "Ne plus demander sur cet appareil" → bypass 2FA pendant **30 jours** +- Révocable depuis paramètres compte +- Liste des appareils de confiance visible + +**Sécurité** : +- Détection automatique nouveau device → notification push + email +- Localisation suspecte (pays différent) → alerte +- Révocation individuelle ou globale possible diff --git a/docs/domains/_shared/entities/entities-overview.md b/docs/domains/_shared/entities/entities-overview.md new file mode 100644 index 0000000..ea03df7 --- /dev/null +++ b/docs/domains/_shared/entities/entities-overview.md @@ -0,0 +1,216 @@ +# Modèle de données - Entités globales + +📖 Entités de base utilisées dans tous les domaines métier + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ CONTENTS : "crée" + USERS ||--o{ SUBSCRIPTIONS : "s'abonne à" + USERS ||--o{ LISTENING_HISTORY : "écoute" + USERS ||--o{ SESSIONS : "possède" + USERS ||--o{ DEVICES : "possède" + USERS ||--o{ USER_CONSENTS : "donne" + USERS ||--o{ LOCATION_HISTORY : "génère" + USERS ||--o{ INTEREST_GAUGES : "possède" + USERS ||--o{ REPORTS : "signale" + USERS ||--o{ DATA_EXPORTS : "demande" + + CONTENTS ||--o{ LISTENING_HISTORY : "écouté" + CONTENTS }o--|| USERS : "créé par" + CONTENTS ||--o{ REPORTS : "reçoit" + + DEVICES ||--o{ SESSIONS : "a" + + USERS { + uuid id PK + string email UK + string pseudo UK + date birthdate + string role + string account_status + timestamp created_at + timestamp last_login_at + boolean email_verified + boolean kyc_verified + string phone_number + int trust_score + timestamp deletion_requested_at + timestamp inactivity_notified_at + } + + CONTENTS { + uuid id PK + uuid creator_id FK + string title + string audio_url + string status + string moderation_status + string age_rating + string geo_type + point geo_location + string[] tags + int duration_seconds + timestamp published_at + int reports_count + text moderation_notes + } + + SUBSCRIPTIONS { + uuid id PK + uuid subscriber_id FK + uuid creator_id FK + timestamp subscribed_at + } + + LISTENING_HISTORY { + uuid id PK + uuid user_id FK + uuid content_id FK + uuid creator_id FK + boolean is_subscribed + decimal completion_rate + int last_position_seconds + string source + boolean auto_like + timestamp listened_at + } + + SESSIONS { + uuid id PK + uuid user_id FK + uuid device_id FK + string access_token_hash + string refresh_token_hash + timestamp access_token_expires_at + timestamp refresh_token_expires_at + inet ip_address + string user_agent + string city + string country_code + timestamp created_at + timestamp last_activity_at + timestamp revoked_at + } + + DEVICES { + uuid id PK + uuid user_id FK + string device_name + string os + string browser + string device_type + boolean is_trusted + timestamp trusted_until + timestamp first_seen_at + timestamp last_seen_at + } + + USER_CONSENTS { + uuid id PK + uuid user_id FK + string consent_type + string consent_version + boolean accepted + timestamp given_at + } + + LOCATION_HISTORY { + uuid id PK + uuid user_id FK + geography location + string geohash + boolean anonymized + string context + timestamp created_at + timestamp anonymized_at + } + + INTEREST_GAUGES { + uuid id PK + uuid user_id FK + string category + decimal score + timestamp last_updated + int interactions_count + } + + REPORTS { + uuid id PK + uuid content_id FK + uuid reporter_id FK + uuid moderator_id FK + string category + string status + text comment + timestamp reported_at + timestamp reviewed_at + text moderator_notes + string action_taken + } + + DATA_EXPORTS { + uuid id PK + uuid user_id FK + string status + string export_url + bigint size_bytes + string format + timestamp requested_at + timestamp generated_at + timestamp expires_at + } +``` + +## Légende + +**Entités de base** : + +- **USERS** : Utilisateurs plateforme + - Rôles : `listener`, `creator`, `moderator`, `admin` + - Account status : `active`, `suspended`, `grace_period`, `deleted` + - Trust score : 0-100 (anti-spam, accès fonctionnalités avancées) + +- **CONTENTS** : Contenus audio + - Status : `draft`, `pending_review`, `published`, `moderated`, `deleted` + - Moderation status : `pending_review`, `approved`, `rejected` + - Geo-type : `geo_ancre` (70% geo), `geo_contextuel` (50% geo), `geo_neutre` (20% geo) + - Age rating : `all`, `13+`, `16+`, `18+` + +- **SUBSCRIPTIONS** : Abonnements créateurs + - Utilisé pour filtrer recommandations et calculer engagement + +- **LISTENING_HISTORY** : Historique écoutes + - Source : `recommendation`, `search`, `direct_link`, `profile`, `history`, `live_notification`, `audio_guide` + - Utilisé pour scoring recommandation et statistiques créateur + +**Entités authentification & sécurité** : + +- **SESSIONS** : Sessions utilisateur OAuth2/OIDC ([détails](sessions.md)) + - Access token : 15 min, Refresh token : 30 jours (rotatif) + +- **DEVICES** : Appareils de confiance ([détails](devices.md)) + - Types : `mobile`, `tablet`, `desktop`, `car` + - Appareils de confiance : bypass 2FA pendant 30 jours + +**Entités RGPD & conformité** : + +- **USER_CONSENTS** : Consentements RGPD avec versioning ([détails](consents.md)) + - Types : `geolocation_precise`, `analytics`, `push_notifications` + +- **LOCATION_HISTORY** : Historique GPS avec anonymisation 24h ([détails](location-history.md)) + - Geohash précision 5 (~5km²) après 24h + +- **DATA_EXPORTS** : Exports de données utilisateur ([détails](exports.md)) + - Portabilité RGPD Article 20, délai 48h max + +**Entités recommandation & modération** : + +- **INTEREST_GAUGES** : Jauges de centres d'intérêt ([détails](interest-gauges.md)) + - Score 0-100 par catégorie (automobile, travel, music, etc.) + - Algorithme : 70% géo + 30% intérêts + +- **REPORTS** : Signalements de contenu ([détails](reports.md)) + - Catégories : `spam`, `hate_speech`, `violence`, `sexual_content`, `misinformation`, etc. + - Workflow modération avec priorisation diff --git a/docs/domains/_shared/entities/exports.md b/docs/domains/_shared/entities/exports.md new file mode 100644 index 0000000..d446b0b --- /dev/null +++ b/docs/domains/_shared/entities/exports.md @@ -0,0 +1,52 @@ +# Data Exports + +📖 Exports de données utilisateur (portabilité RGPD Article 20) + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ DATA_EXPORTS : "demande" + + DATA_EXPORTS { + uuid id PK + uuid user_id FK + string status + string export_url + bigint size_bytes + string format + timestamp requested_at + timestamp generated_at + timestamp expires_at + timestamp downloaded_at + } +``` + +## Légende + +**Formats d'export** : +- `json` : Machine-readable (données brutes) +- `html` : Human-readable (page web stylée) +- `zip` : Archive complète (JSON + HTML + audio files) + +**Contenu de l'export** : +- Profil utilisateur (email, pseudo, date inscription, bio) +- Historique d'écoute (titres, dates, durées) +- Contenus créés (audio + métadonnées) +- Abonnements et likes +- Centres d'intérêt (jauges) +- Historique consentements RGPD + +**Statuts** : +- `pending` : Demande en file d'attente +- `generating` : Génération en cours (worker background) +- `ready` : Export disponible au téléchargement +- `downloaded` : Export téléchargé par l'utilisateur +- `expired` : Export expiré (supprimé automatiquement) + +**Règles** : +- Génération asynchrone (worker background) +- Délai max : **48h** (conformité RGPD) +- Conservation : **7 jours** après génération +- Limite : **1 export/mois** (anti-abus) +- Notification par email avec lien de téléchargement diff --git a/docs/domains/_shared/entities/interest-gauges.md b/docs/domains/_shared/entities/interest-gauges.md new file mode 100644 index 0000000..8881ecc --- /dev/null +++ b/docs/domains/_shared/entities/interest-gauges.md @@ -0,0 +1,45 @@ +# Interest Gauges + +📖 Jauges de centres d'intérêt dynamiques pour recommandation personnalisée + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ INTEREST_GAUGES : "possède" + + INTEREST_GAUGES { + uuid id PK + uuid user_id FK + string category + decimal score + timestamp last_updated + int interactions_count + } +``` + +## Légende + +**Catégories** : +- `automobile` : Voitures, mécanique, course automobile +- `travel` : Voyages, tourisme, découverte +- `music` : Musique, concerts, artistes +- `news` : Actualités, politique, économie +- `sport` : Sports, événements sportifs +- `culture` : Cinéma, livres, expositions +- `food` : Gastronomie, restaurants, recettes +- `tech` : Technologie, innovation, gadgets +- `history` : Histoire, patrimoine, musées +- `nature` : Nature, randonnée, écologie + +**Score** : +- Échelle : **0-100** +- Augmentation : +2% par like, +5% par abonnement créateur +- Diminution : -1% par skip rapide (<30s), -5% par signalement +- Calcul combiné : Distance GPS + matching intérêts + +**Algorithme recommandation** : +- **70% géolocalisation** : Proximité GPS +- **30% centres d'intérêt** : Score jauges +- Boost si créateur suivi : +0.3 au score final +- Limite : 6 contenus/heure pour éviter spam diff --git a/docs/domains/_shared/entities/location-history.md b/docs/domains/_shared/entities/location-history.md new file mode 100644 index 0000000..534fe55 --- /dev/null +++ b/docs/domains/_shared/entities/location-history.md @@ -0,0 +1,47 @@ +# Location History + +📖 Historique de géolocalisation avec anonymisation automatique + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ LOCATION_HISTORY : "génère" + + LOCATION_HISTORY { + uuid id PK + uuid user_id FK + geography location + string geohash + boolean anonymized + string context + float speed_kmh + float accuracy_meters + timestamp created_at + timestamp anonymized_at + } +``` + +## Légende + +**Anonymisation progressive** : +- Données précises conservées **24h** (recommandation personnalisée) +- Après 24h : conversion en **geohash précision 5** (~5km²) +- Coordonnées originales supprimées définitivement +- Job quotidien PostGIS automatique + +**Exceptions** : +- Historique personnel visible (liste trajets) : conservation intégrale tant que compte actif +- Analytics globales : uniquement geohash anonyme +- Suppression complète si suppression du compte + +**Contexte** : +- `listening` : Position pendant écoute de contenu +- `search` : Position lors d'une recherche +- `background` : Tracking en arrière-plan +- `manual` : Position partagée manuellement + +**Conformité RGPD** : +- Vraie anonymisation (CNIL compliant) +- Permet analytics agrégées (heatmaps trafic) +- PostGIS natif, 0€ diff --git a/docs/domains/_shared/entities/modele-global.md b/docs/domains/_shared/entities/modele-global.md deleted file mode 100644 index a073d96..0000000 --- a/docs/domains/_shared/entities/modele-global.md +++ /dev/null @@ -1,69 +0,0 @@ -# Modèle de données - Entités globales - -📖 Entités de base utilisées dans tous les domaines métier - -## Diagramme - -```mermaid -erDiagram - USERS ||--o{ CONTENTS : "crée" - USERS ||--o{ SUBSCRIPTIONS : "s'abonne à" - USERS ||--o{ LISTENING_HISTORY : "écoute" - - CONTENTS ||--o{ LISTENING_HISTORY : "écouté" - CONTENTS }o--|| USERS : "créé par" - - USERS { - uuid id PK - string email UK - string pseudo UK - date birthdate - string role - timestamp created_at - boolean email_verified - } - - CONTENTS { - uuid id PK - uuid creator_id FK - string title - string audio_url - string status - string age_rating - string geo_type - point geo_location - string[] tags - int duration_seconds - timestamp published_at - boolean is_moderated - } - - SUBSCRIPTIONS { - uuid id PK - uuid subscriber_id FK - uuid creator_id FK - timestamp subscribed_at - } - - LISTENING_HISTORY { - uuid id PK - uuid user_id FK - uuid content_id FK - uuid creator_id FK - boolean is_subscribed - decimal completion_rate - int last_position_seconds - string source - boolean auto_like - timestamp listened_at - } -``` - -## Légende - -**Entités de base** : - -- **USERS** : Utilisateurs plateforme - Rôles : `listener`, `creator`, `moderator`, `admin` -- **CONTENTS** : Contenus audio - Status : `draft`, `pending_review`, `published`, `moderated`, `deleted` - Geo-type : `geo_ancre` (70% geo), `geo_contextuel` (50% geo), `geo_neutre` (20% geo) - Age rating : `all`, `13+`, `16+`, `18+` -- **SUBSCRIPTIONS** : Abonnements créateurs - Utilisé pour filtrer recommandations et calculer engagement -- **LISTENING_HISTORY** : Historique écoutes - Source : `recommendation`, `search`, `direct_link`, `profile`, `history`, `live_notification`, `audio_guide` - Utilisé pour scoring recommandation et statistiques créateur diff --git a/docs/domains/_shared/entities/reports.md b/docs/domains/_shared/entities/reports.md new file mode 100644 index 0000000..eb6c23f --- /dev/null +++ b/docs/domains/_shared/entities/reports.md @@ -0,0 +1,60 @@ +# Reports + +📖 Signalements de contenu et workflow de modération + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ REPORTS : "signale" + CONTENTS ||--o{ REPORTS : "reçoit" + USERS ||--o{ REPORTS : "modère" + + REPORTS { + uuid id PK + uuid content_id FK + uuid reporter_id FK + uuid moderator_id FK + string category + string status + text comment + string evidence_url + timestamp reported_at + timestamp reviewed_at + text moderator_notes + string action_taken + } +``` + +## Légende + +**Catégories de signalement** : +- `spam` : Contenu publicitaire non sollicité +- `hate_speech` : Discours haineux, discrimination +- `violence` : Violence explicite +- `sexual_content` : Contenu sexuel inapproprié +- `misinformation` : Désinformation, fake news +- `copyright` : Violation de droits d'auteur +- `wrong_age_rating` : Classification d'âge incorrecte +- `other` : Autre raison (commentaire obligatoire) + +**Statuts** : +- `pending` : En attente de revue +- `under_review` : En cours d'examen par modérateur +- `actioned` : Action prise (contenu retiré/édité) +- `dismissed` : Signalement rejeté (contenu valide) +- `duplicate` : Doublon d'un signalement existant + +**Actions possibles** : +- `content_removed` : Contenu supprimé +- `content_edited` : Métadonnées modifiées (âge, tags) +- `warning_sent` : Avertissement au créateur +- `strike_issued` : Strike ajouté au créateur +- `account_suspended` : Compte créateur suspendu +- `no_action` : Aucune action (signalement infondé) + +**Workflow modération** : +- **3 premiers contenus** : Modération préalable obligatoire +- **Après validation** : Modération a posteriori (signalements) +- **Priorisation** : Nombre de signalements (>3 = urgent) +- **Délai de traitement** : <48h pour signalements critiques diff --git a/docs/domains/_shared/entities/sessions.md b/docs/domains/_shared/entities/sessions.md new file mode 100644 index 0000000..aaaae4a --- /dev/null +++ b/docs/domains/_shared/entities/sessions.md @@ -0,0 +1,45 @@ +# Sessions + +📖 Gestion des sessions utilisateur et tokens d'authentification OAuth2/OIDC + +## Diagramme + +```mermaid +erDiagram + USERS ||--o{ SESSIONS : "possède" + DEVICES ||--o{ SESSIONS : "associé" + + SESSIONS { + uuid id PK + uuid user_id FK + uuid device_id FK + string access_token_hash + string refresh_token_hash + timestamp access_token_expires_at + timestamp refresh_token_expires_at + inet ip_address + string user_agent + string city + string country_code + timestamp created_at + timestamp last_activity_at + timestamp revoked_at + } +``` + +## Légende + +**Durées de vie** : +- Access token : **15 minutes** +- Refresh token : **30 jours** (rotatif) +- Inactivité : Déconnexion automatique après **30 jours** + +**Sécurité** : +- Tokens stockés en **SHA256** (jamais en clair) +- Rotation automatique des refresh tokens +- Détection replay attack + +**Multi-device** : +- Sessions simultanées **illimitées** +- Révocation individuelle ou globale possible +- Alertes si connexion depuis nouveau device ou pays différent diff --git a/docs/domains/_shared/sequences/account-deletion.md b/docs/domains/_shared/sequences/account-deletion.md new file mode 100644 index 0000000..5f18bfd --- /dev/null +++ b/docs/domains/_shared/sequences/account-deletion.md @@ -0,0 +1,48 @@ +# Séquence - Suppression de compte + +## Diagramme + +```mermaid +sequenceDiagram + participant U as Utilisateur + participant API as Backend API + participant DB as PostgreSQL + participant E as Email + participant J as Job Quotidien + + U->>API: DELETE /account (demande suppression) + API->>DB: UPDATE account_status=grace_period + API->>DB: UPDATE deletion_requested_at=NOW() + API->>DB: UPDATE sessions.revoked_at=NOW() (toutes) + API->>DB: UPDATE contents (cachés, non diffusés) + API->>E: Email avec lien annulation (30j) + API-->>U: Compte désactivé + + alt Utilisateur change d'avis + U->>API: GET /account/cancel-deletion (lien email) + API->>DB: UPDATE account_status=active + API->>DB: UPDATE deletion_requested_at=NULL + API->>DB: Réactivation contenus + API->>E: Email confirmation annulation + API-->>U: Compte réactivé + else Après 30 jours + J->>DB: SELECT users WHERE grace_period > 30j + J->>DB: UPDATE account_status=deleted + J->>DB: Anonymisation données (email, pseudo...) + J->>DB: UPDATE contents.creator="Utilisateur supprimé" + J->>DB: DELETE listening_history, location_history, sessions + J->>DB: Conservation contenus anonymisés + J-->>DB: Suppression complète + end +``` + +## Légende + +**Grace period** : 30 jours pour annuler +**Annulation** : Via lien email unique +**Anonymisation** : +- Données perso supprimées (email, pseudo, GPS...) +- Contenus conservés anonymes (intérêt communauté) +- Irréversible après 30j + +**Alternative** : Purge auto inactivité 5 ans (notifications 90j/30j/7j avant) diff --git a/docs/domains/_shared/sequences/authentication-flow.md b/docs/domains/_shared/sequences/authentication-flow.md new file mode 100644 index 0000000..34ca193 --- /dev/null +++ b/docs/domains/_shared/sequences/authentication-flow.md @@ -0,0 +1,42 @@ +# Séquence - Authentification + +## Diagramme + +```mermaid +sequenceDiagram + participant U as Utilisateur + participant A as App Mobile + participant Z as Zitadel + participant API as Backend API + participant DB as PostgreSQL + + U->>A: Saisie email/password + A->>Z: POST /oauth/token (email, password) + Z->>Z: Validation credentials + Z-->>A: access_token (15min) + refresh_token (30j) + + A->>API: GET /api/user/profile (Bearer token) + API->>Z: Validation JWT + Z-->>API: Token valide + user_id + API->>DB: SELECT user WHERE id = ? + DB-->>API: Données utilisateur + API-->>A: Profil utilisateur + + A->>DB: INSERT session (hash tokens, IP, device) + A->>U: Connexion réussie +``` + +## Légende + +**Acteurs** : +- Zitadel : Gère l'authentification OAuth2/OIDC +- Backend API : Valide les tokens et accède aux données + +**Tokens** : +- Access token : 15 min (JWT), utilisé pour chaque requête API +- Refresh token : 30 jours, permet renouvellement access token + +**Sécurité** : +- Tokens stockés hashés (SHA256) en DB +- Device fingerprinting (OS, navigateur, IP) +- Notification si nouveau device diff --git a/docs/domains/_shared/sequences/content-moderation.md b/docs/domains/_shared/sequences/content-moderation.md new file mode 100644 index 0000000..e76fb3b --- /dev/null +++ b/docs/domains/_shared/sequences/content-moderation.md @@ -0,0 +1,44 @@ +# Séquence - Modération de contenu + +## Diagramme + +```mermaid +sequenceDiagram + participant C as Créateur + participant API as Backend API + participant DB as PostgreSQL + participant Q as Queue + participant M as Modérateur + participant N as Notification + + C->>API: POST /contents (3 premiers contenus) + API->>DB: INSERT content (status=pending_review) + API->>Q: Ajout file modération + API-->>C: Contenu soumis + + Q->>M: Notification nouveau contenu + M->>API: GET /moderation/contents/pending + API-->>M: Liste contenus à modérer + + M->>M: Écoute + vérification + + alt Validation + M->>API: POST /moderation/approve/{id} + API->>DB: UPDATE status=published + API->>N: Email + push créateur + N-->>C: Contenu publié ✓ + else Rejet + M->>API: POST /moderation/reject/{id} (motif) + API->>DB: UPDATE status=rejected + API->>DB: INSERT strike (si grave) + API->>N: Email créateur (motif) + N-->>C: Contenu rejeté + motif + end +``` + +## Légende + +**Modération préalable** : 3 premiers contenus uniquement +**Après validation** : Publication directe (modération a posteriori via signalements) +**Délai** : 48h maximum +**Strike** : +1 si violation grave diff --git a/docs/domains/_shared/sequences/content-report.md b/docs/domains/_shared/sequences/content-report.md new file mode 100644 index 0000000..f3dca1c --- /dev/null +++ b/docs/domains/_shared/sequences/content-report.md @@ -0,0 +1,51 @@ +# Séquence - Signalement de contenu + +## Diagramme + +```mermaid +sequenceDiagram + participant U as Utilisateur + participant API as Backend API + participant DB as PostgreSQL + participant M as Modérateur + participant C as Créateur + participant N as Notification + + U->>API: POST /reports (content_id, category, comment) + API->>DB: INSERT report (status=pending) + API->>DB: UPDATE contents.reports_count++ + + alt Priorité haute (3+ reports) + API->>N: Alerte modérateurs + end + + API-->>U: Signalement enregistré + + M->>API: GET /moderation/reports/pending + API-->>M: Reports triés par priorité + + M->>API: PUT /reports/{id} (status=under_review) + M->>M: Écoute contenu + contexte + + alt Violation confirmée + M->>API: POST /moderation/action (action_taken) + API->>DB: UPDATE content.status=moderated + API->>DB: UPDATE report.status=actioned + API->>DB: INSERT strike (créateur) + API->>N: Notification créateur + signaleur + N-->>C: Contenu retiré (motif + appel) + N-->>U: Action prise + else Infondé + M->>API: PUT /reports/{id} (status=dismissed) + API->>DB: UPDATE report + API->>N: Notification signaleur + N-->>U: Signalement rejeté + end +``` + +## Légende + +**Priorité haute** : 3+ signalements ou catégories critiques (hate_speech, violence) +**Délai** : < 24h priorité haute, < 48h normale +**Anti-abus** : > 5 dismissed → warning signaleur +**Appel** : Créateur peut contester 7j après moderation diff --git a/docs/domains/_shared/sequences/data-export.md b/docs/domains/_shared/sequences/data-export.md new file mode 100644 index 0000000..a3216b4 --- /dev/null +++ b/docs/domains/_shared/sequences/data-export.md @@ -0,0 +1,49 @@ +# Séquence - Export de données RGPD + +## Diagramme + +```mermaid +sequenceDiagram + participant U as Utilisateur + participant API as Backend API + participant DB as PostgreSQL + participant W as Worker + participant S as OVH Storage + participant E as Email + + U->>API: POST /exports (demande) + API->>DB: Vérification limite (1/mois) + API->>DB: INSERT export (status=pending) + API->>W: Job asynchrone + API-->>U: Export en préparation + + W->>DB: Collecte données (profil, écoutes, contenus...) + W->>W: Génération JSON + HTML + + loop Contenus audio + W->>DB: SELECT audio_url + W->>W: Copie fichier + end + + W->>W: Création ZIP + W->>S: Upload fichier + S-->>W: URL signée (7j) + + W->>DB: UPDATE export (status=ready, url, size) + W->>E: Email avec lien download + E-->>U: Export prêt (expire 7j) + + U->>S: GET /export-signed-url + S-->>U: Téléchargement ZIP + + Note over DB: Job quotidien + DB->>S: DELETE exports expirés (> 7j) +``` + +## Légende + +**Conformité RGPD** : Délai max 48h (Article 20) +**Format** : ZIP (JSON machine-readable + HTML human-readable + audio) +**Limite** : 1 export/mois +**Expiration** : 7 jours calendaires +**Sécurité** : URL signée unique diff --git a/docs/domains/_shared/sequences/token-refresh.md b/docs/domains/_shared/sequences/token-refresh.md new file mode 100644 index 0000000..6ac3585 --- /dev/null +++ b/docs/domains/_shared/sequences/token-refresh.md @@ -0,0 +1,38 @@ +# Séquence - Refresh Token + +## Diagramme + +```mermaid +sequenceDiagram + participant A as App Mobile + participant Z as Zitadel + participant DB as PostgreSQL + + Note over A: Access token expiré (15min) + + A->>Z: POST /oauth/token (refresh_token) + Z->>DB: Vérification hash refresh_token + + alt Token valide + Z->>Z: Génération nouveaux tokens + Z->>DB: Update session (nouveau hash) + Z->>DB: Invalidation ancien refresh_token + Z-->>A: Nouveaux tokens + Note over DB: Rotation complète + else Token invalide ou rejoué + Z->>DB: Révocation toutes sessions user + Z-->>A: 401 Unauthorized + Note over A: Reconnexion requise + end +``` + +## Légende + +**Rotation** : +- Nouveau refresh_token à chaque refresh +- Ancien token invalidé immédiatement +- Prévient replay attack + +**Sécurité** : +- Si ancien token réutilisé → révocation globale +- Logs sécurité + notification utilisateur diff --git a/docs/domains/_shared/states/content-lifecycle.md b/docs/domains/_shared/states/content-lifecycle.md new file mode 100644 index 0000000..56707cd --- /dev/null +++ b/docs/domains/_shared/states/content-lifecycle.md @@ -0,0 +1,39 @@ +# Cycle de vie - Contenu + +## Diagramme + +```mermaid +stateDiagram-v2 + [*] --> Draft: Création + + Draft --> PendingReview: Soumission (3 premiers contenus) + Draft --> Published: Soumission (si > 3 validés) + + PendingReview --> Published: Validation modérateur + PendingReview --> Rejected: Refus modérateur + + Published --> Moderated: Signalement validé + Published --> Deleted: Suppression + + Rejected --> Draft: Édition corrections + Rejected --> Deleted: Abandon + + Moderated --> Published: Appel accepté + Moderated --> Deleted: Suppression définitive + + Deleted --> [*] +``` + +## Règles + +| État | Valeur | Description | +|------|--------|-------------| +| Draft | `draft` | Brouillon non visible | +| Pending Review | `pending_review` | Modération préalable (3 premiers, < 48h) | +| Published | `published` | Diffusé et visible | +| Moderated | `moderated` | Retiré après signalement | +| Rejected | `rejected` | Refusé par modération (éditable) | +| Deleted | `deleted` | Supprimé (fichiers conservés 30j) | + +**Modération** : Préalable pour 3 premiers contenus, puis a posteriori (signalements) +**Appel** : Possible 7j après moderation diff --git a/docs/domains/_shared/states/export-lifecycle.md b/docs/domains/_shared/states/export-lifecycle.md new file mode 100644 index 0000000..2f73c43 --- /dev/null +++ b/docs/domains/_shared/states/export-lifecycle.md @@ -0,0 +1,38 @@ +# Cycle de vie - Export de données + +## Diagramme + +```mermaid +stateDiagram-v2 + [*] --> Pending: Demande export + + Pending --> Generating: Worker démarre + + Generating --> Ready: Génération OK (< 48h) + Generating --> Failed: Erreur (retry 3x) + + Ready --> Downloaded: Téléchargement + Ready --> Expired: Délai 7j écoulé + + Downloaded --> Expired: Délai 7j écoulé + + Failed --> Pending: Retry manuel + + Expired --> [*] + Failed --> [*] +``` + +## Règles + +| État | Valeur | Description | +|------|--------|-------------| +| Pending | `pending` | File d'attente (< 5 min) | +| Generating | `generating` | Worker background actif (< 48h RGPD) | +| Ready | `ready` | Disponible, lien email valide 7j | +| Downloaded | `downloaded` | Téléchargé (reste 7j) | +| Expired | `expired` | Supprimé automatiquement | +| Failed | `failed` | Échec après retry 3x | + +**Format** : ZIP (JSON + HTML + audio files) +**Limite** : 1 export/mois +**Sécurité** : URL signée, token unique 7j diff --git a/docs/domains/_shared/states/report-lifecycle.md b/docs/domains/_shared/states/report-lifecycle.md new file mode 100644 index 0000000..e429240 --- /dev/null +++ b/docs/domains/_shared/states/report-lifecycle.md @@ -0,0 +1,32 @@ +# Cycle de vie - Signalement + +## Diagramme + +```mermaid +stateDiagram-v2 + [*] --> Pending: Signalement créé + + Pending --> UnderReview: Prise en charge + Pending --> Duplicate: Doublon détecté + + UnderReview --> Actioned: Violation confirmée + UnderReview --> Dismissed: Infondé + + Actioned --> [*] + Dismissed --> [*] + Duplicate --> [*] +``` + +## Règles + +| État | Valeur | Description | +|------|--------|-------------| +| Pending | `pending` | En attente (< 48h, < 24h si priorité haute) | +| Under Review | `under_review` | En cours d'examen | +| Actioned | `actioned` | Contenu retiré/modifié + strike | +| Dismissed | `dismissed` | Signalement rejeté | +| Duplicate | `duplicate` | Doublon (même contenu < 7j) | + +**Priorité haute** : 3+ signalements ou catégories `hate_speech`, `violence` +**Actions** : Contenu retiré, strike, suspension selon gravité +**Anti-abus** : > 5 dismissed → warning, limite 3 signalements/jour diff --git a/docs/domains/_shared/states/session-lifecycle.md b/docs/domains/_shared/states/session-lifecycle.md new file mode 100644 index 0000000..abdfea9 --- /dev/null +++ b/docs/domains/_shared/states/session-lifecycle.md @@ -0,0 +1,29 @@ +# Cycle de vie - Session + +## Diagramme + +```mermaid +stateDiagram-v2 + [*] --> Active: Connexion + + Active --> Active: Refresh token + Active --> Expired: Inactivité 30j + Active --> Revoked: Déconnexion manuelle + Active --> Revoked: Changement mot de passe + Active --> Revoked: Replay attack + + Expired --> [*] + Revoked --> [*] +``` + +## Règles + +| État | Condition | Description | +|------|-----------|-------------| +| Active | `revoked_at IS NULL` | Access token 15min, Refresh token 30j | +| Expired | `refresh_token_expires_at < NOW()` | Inactivité 30j | +| Revoked | `revoked_at IS NOT NULL` | Révoquée manuellement | + +**Rotation** : Refresh token rotatif (nouveau à chaque refresh) +**Sécurité** : Tokens hashés SHA256, révocation globale si replay attack +**Nettoyage** : Suppression sessions expirées/révoquées > 7j/30j diff --git a/docs/domains/_shared/states/user-account-lifecycle.md b/docs/domains/_shared/states/user-account-lifecycle.md new file mode 100644 index 0000000..a280382 --- /dev/null +++ b/docs/domains/_shared/states/user-account-lifecycle.md @@ -0,0 +1,31 @@ +# Cycle de vie - Compte utilisateur + +## Diagramme + +```mermaid +stateDiagram-v2 + [*] --> Active: Inscription validée + + Active --> Suspended: Strikes 3/4/5 + Active --> GracePeriod: Demande suppression + Active --> Deleted: Inactivité 5 ans + + Suspended --> Active: Fin suspension / Appel + Suspended --> Deleted: Suspension définitive + + GracePeriod --> Active: Annulation < 30j + GracePeriod --> Deleted: Après 30j + + Deleted --> [*] +``` + +## Règles + +| État | Valeur | Durée/Condition | +|------|--------|-----------------| +| Active | `active` | Compte fonctionnel | +| Suspended | `suspended` | Strike 3: 7j, Strike 4: 30j, Strike 5: définitif | +| Grace Period | `grace_period` | 30j avant suppression, annulable | +| Deleted | `deleted` | Données anonymisées, irréversible | + +**Purge inactivité** : 5 ans sans connexion (notifications 90j/30j/7j avant) diff --git a/mkdocs.yml b/mkdocs.yml index c460b14..d7c0fee 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -63,31 +63,37 @@ nav: - Architecture Technique: TECHNICAL.md - Architecture Decision Records (ADR): - 'Vue d''ensemble': adr/README.md - - 'ADR-001: Langage Backend': adr/001-langage-backend.md - - 'ADR-002: Protocole Streaming': adr/002-protocole-streaming.md - - 'ADR-003: Codec Audio': adr/003-codec-audio.md - - 'ADR-004: CDN': adr/004-cdn.md - - 'ADR-005: Base de données': adr/005-base-de-donnees.md - - 'ADR-006: Chiffrement': adr/006-chiffrement.md - - 'ADR-007: Tests BDD': adr/007-tests-bdd.md - - 'ADR-008: Authentification': adr/008-authentification.md - - 'ADR-009: Solution Paiement': adr/009-solution-paiement.md - - 'ADR-010: Architecture Backend': adr/010-architecture-backend.md - - 'ADR-011: ORM et Accès Données': adr/011-orm-acces-donnees.md - - 'ADR-012: Frontend Mobile': adr/012-frontend-mobile.md - - 'ADR-013: Stratégie Tests': adr/013-strategie-tests.md - - 'ADR-014: Organisation en Monorepo': adr/014-organisation-monorepo.md - - 'ADR-015: Hébergement': adr/015-hebergement.md - - 'ADR-016: Service Emailing': adr/016-service-emailing.md - - 'ADR-017: Notifications Géolocalisées': adr/017-notifications-geolocalisees.md - - 'ADR-018: Librairies Go': adr/018-librairies-go.md - - 'ADR-019: Géolocalisation par IP': adr/019-geolocalisation-ip.md - - 'ADR-020: Librairies Flutter': adr/020-librairies-flutter.md - - 'ADR-021: Solution de Cache': adr/021-solution-cache.md - - 'ADR-022: CI/CD Monorepo': adr/022-strategie-cicd-monorepo.md - - 'ADR-023: Architecture Modération': adr/023-architecture-moderation.md - - 'ADR-024: Monitoring & Observabilité': adr/024-monitoring-observabilite.md - - 'ADR-025: Sécurité & Secrets': adr/025-securite-secrets.md + - 'Core Architecture': + - 'ADR-001: Langage Backend': adr/001-langage-backend.md + - 'ADR-010: Architecture Backend': adr/010-architecture-backend.md + - 'ADR-011: ORM et Accès Données': adr/011-orm-acces-donnees.md + - 'ADR-012: Frontend Mobile': adr/012-frontend-mobile.md + - 'ADR-014: Organisation en Monorepo': adr/014-organisation-monorepo.md + - 'Data & Infrastructure': + - 'ADR-005: Base de données': adr/005-base-de-donnees.md + - 'ADR-021: Solution de Cache': adr/021-solution-cache.md + - 'ADR-015: Hébergement': adr/015-hebergement.md + - 'ADR-019: Géolocalisation par IP': adr/019-geolocalisation-ip.md + - 'Streaming & Content': + - 'ADR-002: Protocole Streaming': adr/002-protocole-streaming.md + - 'ADR-003: Codec Audio': adr/003-codec-audio.md + - 'ADR-004: CDN': adr/004-cdn.md + - 'Security & Auth': + - 'ADR-006: Chiffrement': adr/006-chiffrement.md + - 'ADR-008: Authentification': adr/008-authentification.md + - 'ADR-025: Sécurité & Secrets': adr/025-securite-secrets.md + - 'Testing & Quality': + - 'ADR-007: Tests BDD': adr/007-tests-bdd.md + - 'ADR-013: Stratégie Tests': adr/013-strategie-tests.md + - 'ADR-022: CI/CD Monorepo': adr/022-strategie-cicd-monorepo.md + - 'Features & Operations': + - 'ADR-009: Solution Paiement': adr/009-solution-paiement.md + - 'ADR-016: Service Emailing': adr/016-service-emailing.md + - 'ADR-017: Notifications Géolocalisées': adr/017-notifications-geolocalisees.md + - 'ADR-018: Librairies Go': adr/018-librairies-go.md + - 'ADR-020: Librairies Flutter': adr/020-librairies-flutter.md + - 'ADR-023: Architecture Modération': adr/023-architecture-moderation.md + - 'ADR-024: Monitoring & Observabilité': adr/024-monitoring-observabilite.md - Domaines DDD: - 'Context Map': domains/README.md - 'Core Domain': @@ -98,7 +104,30 @@ nav: - Gestion Erreurs: domains/_shared/rules/gestion-erreurs.md - 'Annexe Post-MVP': domains/_shared/rules/ANNEXE-POST-MVP.md - Entités: - - Modèle Global: domains/_shared/entities/modele-global.md + - "Vue d'ensemble": domains/_shared/entities/entities-overview.md + - 'Auth & Sécurité': + - Sessions: domains/_shared/entities/sessions.md + - Devices: domains/_shared/entities/devices.md + - 'RGPD & Conformité': + - Consentements: domains/_shared/entities/consents.md + - Historique GPS: domains/_shared/entities/location-history.md + - Exports Données: domains/_shared/entities/exports.md + - 'Recommandation & Modération': + - Jauges Intérêt: domains/_shared/entities/interest-gauges.md + - Signalements: domains/_shared/entities/reports.md + - 'États (Lifecycles)': + - Compte Utilisateur: domains/_shared/states/user-account-lifecycle.md + - Contenu: domains/_shared/states/content-lifecycle.md + - Session: domains/_shared/states/session-lifecycle.md + - Signalement: domains/_shared/states/report-lifecycle.md + - Export Données: domains/_shared/states/export-lifecycle.md + - Séquences: + - Authentification: domains/_shared/sequences/authentication-flow.md + - Refresh Token: domains/_shared/sequences/token-refresh.md + - Modération Contenu: domains/_shared/sequences/content-moderation.md + - Signalement: domains/_shared/sequences/content-report.md + - Export Données: domains/_shared/sequences/data-export.md + - Suppression Compte: domains/_shared/sequences/account-deletion.md - 'Supporting Subdomains': - '🎯 Recommendation': - Vue d'ensemble: domains/recommendation/README.md