docs: migrer schémas BDD de Mermaid vers DBML

Remplace les diagrammes Mermaid par DBML (via kroki-dbml) pour
une meilleure expressivité des schémas de base de données :
- Ajout support notes, contraintes et indexes détaillés
- Migration de tous les schémas d'entités partagées
- Ajout fichier exemple dbml-example.md
- Configuration plugin mkdocs-kroki pour rendu DBML
This commit is contained in:
jpgiannetti
2026-02-12 20:49:02 +01:00
parent ae2fc3ee6f
commit 23fe67470b
16 changed files with 566 additions and 224 deletions

View File

@@ -4,22 +4,37 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o| ACCOUNT_DELETIONS : "demande"
```kroki-dbml
Table users {
id uuid [primary key]
email varchar(255)
status varchar(20)
}
ACCOUNT_DELETIONS {
uuid id PK
uuid user_id FK
string status
string cancellation_token
timestamp requested_at
timestamp effective_at "requested_at + 30j"
timestamp cancelled_at
timestamp deleted_at
string deletion_reason
json deleted_data_summary
}
Table account_deletions {
id uuid [primary key]
user_id uuid [not null, unique, ref: - users.id, note: 'One-to-one: un user ne peut avoir qu une seule demande active']
status deletion_status_enum [not null, default: 'pending']
cancellation_token varchar(64) [unique, note: 'Token dans email pour annuler (expire après 30j)']
requested_at timestamp [not null, default: `now()`]
effective_at timestamp [not null, note: 'Auto-calculated: requested_at + 30 days']
cancelled_at timestamp [note: 'Timestamp annulation via lien email (NULL si non annulé)']
deleted_at timestamp [note: 'Timestamp suppression effective (NULL si pending/cancelled)']
deletion_reason text [note: 'Raison optionnelle fournie par l utilisateur']
deleted_data_summary jsonb [note: 'Résumé des données supprimées (audit trail)']
indexes {
(user_id) [unique]
(status, effective_at) [note: 'Daily cron job: WHERE status = pending AND effective_at < NOW()']
(cancellation_token) [unique]
}
}
Enum deletion_status_enum {
pending [note: 'Grace period actif (30j), compte désactivé, annulation possible']
cancelled [note: 'Utilisateur a annulé via lien email']
completed [note: 'Suppression effective réalisée après 30j']
}
```
## Légende

View File

@@ -4,33 +4,57 @@
## Diagramme
```mermaid
erDiagram
BREACH_INCIDENTS ||--o{ BREACH_AFFECTED_USERS : "impacte"
USERS ||--o{ BREACH_AFFECTED_USERS : "est impacté"
```kroki-dbml
Table breach_incidents {
id uuid [primary key]
severity breach_severity_enum [not null]
description text [not null, note: 'Description détaillée de l incident']
data_categories_affected jsonb [not null, note: 'Array: ["gps", "email", "listening_history"]']
estimated_users_count int [not null, note: 'Estimation nombre users impactés']
detected_at timestamp [not null, default: `now()`, note: 'H+0: Détection initiale']
contained_at timestamp [note: 'Timestamp confinement de la faille']
cnil_notified_at timestamp [note: 'H+48: Notification CNIL si requis']
users_notified_at timestamp [note: 'H+72: Notification users si risque élevé']
mitigation_actions text [note: 'Actions correctives mises en place']
cnil_notification_required boolean [not null, default: false]
user_notification_required boolean [not null, default: false]
BREACH_INCIDENTS {
uuid id PK
string severity "low/medium/high/critical"
text description
json data_categories_affected
int estimated_users_count
timestamp detected_at
timestamp contained_at
timestamp cnil_notified_at
timestamp users_notified_at
text mitigation_actions
boolean cnil_notification_required
boolean user_notification_required
}
indexes {
(severity, detected_at) [note: 'Incidents par gravité et chronologie']
(cnil_notification_required, cnil_notified_at) [note: 'Track CNIL notification compliance']
}
}
BREACH_AFFECTED_USERS {
uuid id PK
uuid breach_id FK
uuid user_id FK
timestamp notified_at
string notification_channel "email/push/sms"
}
Table users {
id uuid [primary key]
}
Table breach_affected_users {
id uuid [primary key]
breach_id uuid [not null, ref: > breach_incidents.id]
user_id uuid [not null, ref: > users.id]
notified_at timestamp [note: 'Timestamp notification user (NULL si pas encore notifié)']
notification_channel notification_channel_enum [note: 'Canal utilisé pour notifier']
indexes {
(breach_id, user_id) [unique, note: 'Un user ne peut être listé qu une fois par incident']
(breach_id, notified_at) [note: 'Track notification progress']
(user_id) [note: 'Historique incidents pour un user']
}
}
Enum breach_severity_enum {
low [note: 'Pas de notification requise (mesures techniques suffisantes)']
medium [note: 'Notification CNIL uniquement']
high [note: 'Notification CNIL + utilisateurs']
critical [note: 'Notification immédiate tous canaux + SMS fondateur']
}
Enum notification_channel_enum {
email [note: 'Email notification']
push [note: 'Push notification mobile']
sms [note: 'SMS (critical only)']
}
```
## Légende

View File

@@ -4,20 +4,33 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ USER_CONSENTS : "donne"
```kroki-dbml
Table users {
id uuid [primary key]
}
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
}
Table user_consents {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
consent_type consent_type_enum [not null]
consent_version varchar(10) [not null, note: 'Format: v1.0, v2.0, etc.']
accepted boolean [not null, note: 'true = opted-in, false = opted-out']
given_at timestamp [not null, default: `now()`]
ip_address inet [not null, note: 'Proof of consent for CNIL audits']
user_agent text [not null, note: 'Device/browser proof']
indexes {
(user_id, consent_type, consent_version) [note: 'Latest consent per type']
(user_id, given_at) [note: 'Consent history timeline']
}
}
Enum consent_type_enum {
geolocation_precise [note: 'Géolocalisation GPS précise (obligatoire pour contenu hyperlocal)']
analytics [note: 'Analytics Matomo (optionnel)']
push_notifications [note: 'Notifications push (optionnel)']
cookies_analytics [note: 'Cookies analytiques (optionnel)']
}
```
## Légende

View File

@@ -4,18 +4,28 @@
## Diagramme
```mermaid
erDiagram
DATA_RETENTION_LOGS {
uuid id PK
string action_type
int users_processed
int users_warned
int users_deleted
json details
timestamp executed_at
bigint execution_duration_ms
}
```kroki-dbml
Table data_retention_logs {
id uuid [primary key]
action_type retention_action_enum [not null]
users_processed int [not null, default: 0, note: 'Nombre total users analysés']
users_warned int [not null, default: 0, note: 'Nombre users notifiés (90j/30j/7j)']
users_deleted int [not null, default: 0, note: 'Nombre users supprimés effectivement']
details jsonb [note: 'Détails: threshold_date, user_ids_deleted, notifications_sent']
executed_at timestamp [not null, default: `now()`, note: 'Timestamp exécution du job cron']
execution_duration_ms bigint [not null, note: 'Durée d exécution en millisecondes']
indexes {
(action_type, executed_at) [note: 'Historique jobs par type']
(executed_at) [note: 'Timeline complète des jobs']
}
}
Enum retention_action_enum {
check_inactive [note: 'Vérification quotidienne comptes inactifs > 5 ans']
send_warnings [note: 'Envoi notifications (90j/30j/7j avant suppression)']
delete_accounts [note: 'Suppression effective comptes inactifs']
}
```
## Légende

View File

@@ -4,26 +4,43 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ DEVICES : "possède"
DEVICES ||--o{ SESSIONS : "a"
```kroki-dbml
Table users {
id uuid [primary key]
}
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
}
Table devices {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
device_name varchar(255) [note: 'User-defined device name']
os varchar(50) [note: 'iOS, Android, Windows, macOS, Linux']
browser varchar(50) [note: 'Safari, Chrome, Firefox, etc.']
device_type device_type_enum [not null, note: 'mobile, tablet, desktop, car']
is_trusted boolean [not null, default: false, note: 'Bypass 2FA for 30 days if true']
trusted_until timestamp [note: 'NULL if not trusted, expires after 30 days']
first_seen_at timestamp [not null, default: `now()`]
last_seen_at timestamp [not null, default: `now()`]
last_ip inet [not null]
last_city varchar(100)
last_country_code char(2)
indexes {
(user_id, last_seen_at) [note: 'List user devices by recent activity']
(user_id, is_trusted) [note: 'Find trusted devices for user']
}
}
Table sessions {
id uuid [primary key]
device_id uuid [ref: > devices.id]
}
Enum device_type_enum {
mobile [note: 'Smartphone Android/iOS']
tablet [note: 'Tablette']
desktop [note: 'Ordinateur']
car [note: 'Système embarqué (CarPlay/Android Auto)']
}
```
## Légende

View File

@@ -4,22 +4,43 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ DATA_EXPORTS : "demande"
```kroki-dbml
Table users {
id uuid [primary key]
}
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
}
Table data_exports {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
status export_status_enum [not null, default: 'pending']
export_url varchar(512) [note: 'S3/CDN signed URL (NULL until generated)']
size_bytes bigint [note: 'File size in bytes (NULL until generated)']
format export_format_enum [not null, default: 'json']
requested_at timestamp [not null, default: `now()`]
generated_at timestamp [note: 'When export file was created (NULL if pending/generating)']
expires_at timestamp [note: 'Auto-calculated: generated_at + 7 days']
downloaded_at timestamp [note: 'First download timestamp (NULL if not yet downloaded)']
indexes {
(user_id, requested_at) [note: 'User export history']
(status, requested_at) [note: 'Background worker queue (WHERE status = pending)']
(expires_at) [note: 'Daily cleanup job (DELETE WHERE expires_at < NOW())']
}
}
Enum export_status_enum {
pending [note: 'Demande en file d attente']
generating [note: 'Génération en cours (worker background)']
ready [note: 'Export disponible au téléchargement']
downloaded [note: 'Export téléchargé par l utilisateur']
expired [note: 'Export expiré (supprimé automatiquement)']
}
Enum export_format_enum {
json [note: 'Machine-readable (données brutes)']
html [note: 'Human-readable (page web stylée)']
zip [note: 'Archive complète (JSON + HTML + audio files)']
}
```
## Légende

View File

@@ -4,18 +4,37 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ INTEREST_GAUGES : "possède"
```kroki-dbml
Table users {
id uuid [primary key]
}
INTEREST_GAUGES {
uuid id PK
uuid user_id FK
string category
decimal score
timestamp last_updated
int interactions_count
}
Table interest_gauges {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
category interest_category_enum [not null]
score decimal(5,2) [not null, default: 0, note: 'Range: 0.00 to 100.00']
last_updated timestamp [not null, default: `now()`]
interactions_count int [not null, default: 0, note: 'Total interactions for this category']
indexes {
(user_id, category) [unique, note: 'One gauge per user per category']
(user_id, score) [note: 'Order categories by score for recommendations']
}
}
Enum interest_category_enum {
automobile [note: 'Voitures, mécanique, course automobile']
travel [note: 'Voyages, tourisme, découverte']
music [note: 'Musique, concerts, artistes']
news [note: 'Actualités, politique, économie']
sport [note: 'Sports, événements sportifs']
culture [note: 'Cinéma, livres, expositions']
food [note: 'Gastronomie, restaurants, recettes']
tech [note: 'Technologie, innovation, gadgets']
history [note: 'Histoire, patrimoine, musées']
nature [note: 'Nature, randonnée, écologie']
}
```
## Légende

View File

@@ -4,22 +4,37 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ LOCATION_HISTORY : "génère"
```kroki-dbml
Table users {
id uuid [primary key]
}
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
}
Table location_history {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
location geography [note: 'PostGIS geography type: POINT with SRID 4326 (WGS84)']
geohash varchar(12) [note: 'Precision 5 geohash (~5km²) after anonymization']
anonymized boolean [not null, default: false, note: 'true after 24h auto-anonymization']
context location_context_enum [not null]
speed_kmh float [note: 'GPS speed in km/h (NULL if stationary)']
accuracy_meters float [not null, note: 'GPS accuracy radius in meters']
created_at timestamp [not null, default: `now()`]
anonymized_at timestamp [note: 'When precise location was replaced by geohash']
indexes {
(user_id, created_at) [note: 'User location timeline']
(created_at, anonymized) [note: 'Daily anonymization job (WHERE anonymized = false AND created_at < NOW() - 24h)']
(location) [type: gist, note: 'PostGIS spatial index for proximity queries']
(geohash) [note: 'Analytics queries on anonymized data']
}
}
Enum location_context_enum {
listening [note: 'Position pendant écoute de contenu']
search [note: 'Position lors d une recherche']
background [note: 'Tracking en arrière-plan']
manual [note: 'Position partagée manuellement']
}
```
## Légende

View File

@@ -4,34 +4,45 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ PARENTAL_CONSENTS : "a"
PARENTAL_CONSENTS ||--|| PARENTAL_CONTROLS : "configure"
```kroki-dbml
Table users {
id uuid [primary key]
birthdate date [not null]
}
PARENTAL_CONSENTS {
uuid id PK
uuid user_id FK "Ado 13-15 ans"
string parent_email
string validation_token
boolean validated
timestamp token_expires_at
timestamp validated_at
inet parent_ip
string parent_user_agent
timestamp revoked_at
string revocation_reason
}
Table parental_consents {
id uuid [primary key]
user_id uuid [not null, unique, ref: > users.id, note: 'Ado 13-15 ans (1 consent par user max)']
parent_email varchar(255) [not null, note: 'Email du parent pour validation']
validation_token varchar(64) [unique, note: 'Token de validation envoyé par email (expire 7j)']
validated boolean [not null, default: false, note: 'true après clic parent sur lien email']
token_expires_at timestamp [not null, note: 'validation_token expire après 7 jours']
validated_at timestamp [note: 'Timestamp de validation parent (NULL si non validé)']
parent_ip inet [note: 'IP du parent lors de la validation']
parent_user_agent text [note: 'User agent parent (preuve validation)']
revoked_at timestamp [note: 'Révocation du consentement parental']
revocation_reason text [note: 'Raison de la révocation (optionnel)']
PARENTAL_CONTROLS {
uuid id PK
uuid parental_consent_id FK
boolean gps_enabled
boolean messaging_enabled
boolean content_16plus_enabled
json weekly_digest_config
timestamp updated_at
}
indexes {
(user_id) [unique, note: 'Un seul consentement parental actif par user']
(validation_token) [unique, note: 'Lookup rapide pour validation lien email']
(validated, token_expires_at) [note: 'Cleanup des tokens expirés non validés']
}
}
Table parental_controls {
id uuid [primary key]
parental_consent_id uuid [not null, unique, ref: - parental_consents.id, note: 'One-to-one relationship']
gps_enabled boolean [not null, default: false, note: 'Autoriser GPS précis (false = GeoIP uniquement)']
messaging_enabled boolean [not null, default: false, note: 'Autoriser messagerie privée']
content_16plus_enabled boolean [not null, default: false, note: 'Autoriser contenu 16+']
weekly_digest_config jsonb [note: 'Config notifications hebdo parent (email, contenu, format)']
updated_at timestamp [not null, default: `now()`]
indexes {
(parental_consent_id) [unique]
}
}
```
## Légende

View File

@@ -4,29 +4,40 @@
## Diagramme
```mermaid
erDiagram
PRIVACY_POLICY_VERSIONS ||--o{ USER_POLICY_ACCEPTANCES : "acceptée par"
USERS ||--o{ USER_POLICY_ACCEPTANCES : "accepte"
```kroki-dbml
Table privacy_policy_versions {
id uuid [primary key]
version varchar(10) [not null, unique, note: 'Format: v1.0, v2.0, etc.']
content_markdown text [not null, note: 'Source: docs/legal/politique-confidentialite.md (versionné Git)']
major_change boolean [not null, default: false, note: 'true = popup obligatoire pour tous les users']
changelog text [not null, note: 'Résumé des changements pour communication']
effective_date timestamp [not null, note: 'Date d entrée en vigueur de cette version']
created_at timestamp [not null, default: `now()`]
PRIVACY_POLICY_VERSIONS {
uuid id PK
string version "v1.0, v2.0, etc."
text content_markdown
boolean major_change
text changelog
timestamp effective_date
timestamp created_at
}
indexes {
(version) [unique]
(effective_date) [note: 'Order versions chronologically']
}
}
USER_POLICY_ACCEPTANCES {
uuid id PK
uuid user_id FK
uuid policy_version_id FK
boolean accepted
timestamp accepted_at
inet ip_address
}
Table users {
id uuid [primary key]
}
Table user_policy_acceptances {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
policy_version_id uuid [not null, ref: > privacy_policy_versions.id]
accepted boolean [not null, note: 'true = accepté, false = refusé (compte gelé)']
accepted_at timestamp [not null, default: `now()`]
ip_address inet [not null, note: 'IP de l utilisateur lors de l acceptation (preuve CNIL)']
indexes {
(user_id, policy_version_id) [unique, note: 'Un user ne peut accepter qu une fois une version']
(user_id, accepted_at) [note: 'Historique acceptations user']
(policy_version_id) [note: 'Count acceptances par version']
}
}
```
## Légende

View File

@@ -4,26 +4,67 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ REPORTS : "signale"
CONTENTS ||--o{ REPORTS : "reçoit"
USERS ||--o{ REPORTS : "modère"
```kroki-dbml
Table users {
id uuid [primary key]
username varchar(50)
}
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
}
Table contents {
id uuid [primary key]
title varchar(255)
user_id uuid [not null]
}
Table reports {
id uuid [primary key]
content_id uuid [not null, ref: > contents.id, note: 'Content being reported']
reporter_id uuid [not null, ref: > users.id, note: 'User who filed the report']
moderator_id uuid [ref: > users.id, note: 'Moderator assigned to review (NULL if pending)']
category report_category_enum [not null]
status report_status_enum [not null, default: 'pending']
comment text [note: 'Reporter explanation (mandatory for "other" category)']
evidence_url varchar(512) [note: 'Screenshot or additional proof URL']
reported_at timestamp [not null, default: `now()`]
reviewed_at timestamp [note: 'When moderator reviewed the report']
moderator_notes text [note: 'Internal moderator notes']
action_taken report_action_enum [note: 'Action decided by moderator']
indexes {
(content_id, status) [note: 'Find all reports for a content']
(status, reported_at) [note: 'Queue for moderators (pending first)']
(reporter_id) [note: 'User report history (detect abuse)']
(moderator_id) [note: 'Reports assigned to moderator']
}
}
Enum report_category_enum {
spam [note: 'Contenu publicitaire non sollicité']
hate_speech [note: 'Discours haineux, discrimination']
violence [note: 'Violence explicite']
sexual_content [note: 'Contenu sexuel inapproprié']
misinformation [note: 'Désinformation, fake news']
copyright [note: 'Violation de droits d auteur']
wrong_age_rating [note: 'Classification d âge incorrecte']
other [note: 'Autre raison (commentaire obligatoire)']
}
Enum report_status_enum {
pending [note: 'En attente de revue']
under_review [note: 'En cours d examen par modérateur']
actioned [note: 'Action prise (contenu retiré/édité)']
dismissed [note: 'Signalement rejeté (contenu valide)']
duplicate [note: 'Doublon d un signalement existant']
}
Enum report_action_enum {
content_removed [note: 'Contenu supprimé']
content_edited [note: 'Métadonnées modifiées (âge, tags)']
warning_sent [note: 'Avertissement au créateur']
strike_issued [note: 'Strike ajouté au créateur']
account_suspended [note: 'Compte créateur suspendu']
no_action [note: 'Aucune action (signalement infondé)']
}
```
## Légende

View File

@@ -4,27 +4,43 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ SESSIONS : "possède"
DEVICES ||--o{ SESSIONS : "associé"
```kroki-dbml
Table users {
id uuid [primary key]
email varchar(255) [not null, unique]
username varchar(50) [not null, unique]
}
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
}
Table devices {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
device_name varchar(255)
device_type varchar(50)
}
Table sessions {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
device_id uuid [ref: > devices.id]
access_token_hash varchar(64) [not null, note: 'SHA256 hash, never stored in clear']
refresh_token_hash varchar(64) [not null, note: 'SHA256 hash, auto-rotated']
access_token_expires_at timestamp [not null, note: 'Lifetime: 15 minutes']
refresh_token_expires_at timestamp [not null, note: 'Lifetime: 30 days (rolling)']
ip_address inet [not null]
user_agent text [not null]
city varchar(100)
country_code char(2)
created_at timestamp [not null, default: `now()`]
last_activity_at timestamp [not null, default: `now()`]
revoked_at timestamp [note: 'NULL if active, timestamp if manually revoked']
indexes {
(user_id, revoked_at) [note: 'Find active sessions for user']
(device_id)
(refresh_token_hash) [unique, note: 'Detect replay attacks']
(last_activity_at) [note: 'Auto-cleanup inactive sessions']
}
}
```
## Légende

View File

@@ -4,20 +4,44 @@
## Diagramme
```mermaid
erDiagram
USERS ||--o{ USER_PROFILE_HISTORY : "modifie"
```kroki-dbml
Table users {
id uuid [primary key]
email varchar(255)
username varchar(50)
bio text
}
USER_PROFILE_HISTORY {
uuid id PK
uuid user_id FK
string field_name "email/username/bio/etc."
text old_value
text new_value
string change_reason "user_edit/admin_correction/gdpr_request"
inet ip_address
timestamp changed_at
}
Table user_profile_history {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
field_name profile_field_enum [not null, note: 'Champ modifié (email, username, bio, etc.)']
old_value text [note: 'Valeur avant modification (NULL si création)']
new_value text [not null, note: 'Nouvelle valeur']
change_reason change_reason_enum [not null]
ip_address inet [not null, note: 'IP de l origine du changement']
changed_at timestamp [not null, default: `now()`]
indexes {
(user_id, changed_at) [note: 'Timeline modifications user (ordre chronologique)']
(field_name, changed_at) [note: 'Track modifications par type de champ']
(user_id, field_name) [note: 'Historique d un champ spécifique']
}
}
Enum profile_field_enum {
email [note: 'Re-vérification requise après changement']
username [note: 'Limite: 1 changement/30j']
bio [note: 'Biographie utilisateur']
avatar_url [note: 'URL de l avatar']
date_of_birth [note: 'Date de naissance']
}
Enum change_reason_enum {
user_edit [note: 'Modification self-service utilisateur']
admin_correction [note: 'Correction par admin (via backoffice)']
gdpr_request [note: 'Suite demande RGPD formelle (droit de rectification)']
}
```
## Légende

View File

@@ -0,0 +1,95 @@
# Exemple DBML avec Kroki
Ce fichier montre comment utiliser DBML dans la documentation MkDocs avec le plugin Kroki.
## Syntaxe de base
Pour créer un diagramme de base de données DBML, utilisez un bloc de code avec la balise `kroki-dbml` :
## Exemple : Schéma utilisateurs et contenus
```kroki-dbml
Table users {
id uuid [primary key]
email varchar(255) [not null, unique]
username varchar(50) [not null, unique]
password_hash varchar(255) [not null]
created_at timestamp [not null, default: `now()`]
updated_at timestamp [not null, default: `now()`]
indexes {
(email) [unique]
(username) [unique]
}
}
Table contents {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
title varchar(255) [not null]
description text
audio_url varchar(512) [not null]
location geography(POINT, 4326) [note: 'PostGIS geography type']
duration_seconds int [not null]
category content_category [not null]
status content_status [not null, default: 'draft']
created_at timestamp [not null, default: `now()`]
published_at timestamp
indexes {
(user_id)
(status)
(location) [type: gist, note: 'Spatial index']
(created_at)
}
}
Table interest_gauges {
id uuid [primary key]
user_id uuid [not null, ref: > users.id]
category varchar(50) [not null]
score decimal(5,2) [not null, default: 0, note: 'Score 0-100']
last_updated timestamp [not null, default: `now()`]
indexes {
(user_id, category) [unique]
}
}
Enum content_category {
"automobile"
"travel"
"music"
"culture"
"sport"
"education"
}
Enum content_status {
"draft"
"published"
"archived"
"moderated"
}
```
## Avantages de DBML
- ✅ **Syntaxe claire** : Plus lisible que Mermaid pour les schémas BDD
- ✅ **Types PostGIS** : Peut documenter les types spéciaux (geography, geometry)
- ✅ **Index et contraintes** : Documentation complète des index et contraintes
- ✅ **Relations** : Relations explicites entre tables
- ✅ **Enums** : Support natif des types énumérés
- ✅ **Notes** : Annotations directement dans le schéma
## Utilisation dans votre projet
Pour documenter vos schémas de base de données dans RoadWave :
1. Créez vos fichiers `.md` dans `docs/domains/<domain>/`
2. Ajoutez des blocs `kroki-dbml` pour les schémas
3. Le rendu sera automatique lors de `make docs-serve`
## Référence DBML
Consultez la [documentation DBML officielle](https://dbml.dbdiagram.io/docs/) pour la syntaxe complète.