- Body SolidWorks v1 → 02_PRODUITS_PHYSIQUES/Microphone/Conception/ - Studio Mic KiCAD (DIYPerks) → 02_PRODUITS_PHYSIQUES/R&D_References/DIY/ - cleanup_ports.sh → 04_INFRA_DEPLOIEMENT/ - mockup_jeu_ux → 11_RECHERCHE_&_LAB/ - Printables → 12_DOCUMENTATION/Imprimables/ - Screenshots, ideas, one.html → _BROUILLON/ - all-talas (23Go) → 13_ARCHIVES/ - Supprimé all-talas.zip (20Go doublon), lock files LibreOffice - Nettoyé .gitignore - Remote → Forgejo (10.0.20.105:3000) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9391 lines
181 KiB
HTML
9391 lines
181 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Intercalaire 3 - APPS & SERVICES</title>
|
||
<style>
|
||
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; max-width: 900px; margin: 0 auto; padding: 20px; color: #333; }
|
||
h1 { border-bottom: 2px solid #2c3e50; padding-bottom: 10px; color: #2c3e50; font-size: 2.5em; }
|
||
h2 { color: #34495e; margin-top: 1.5em; border-bottom: 1px solid #eee; padding-bottom: 5px; }
|
||
h3 { color: #7f8c8d; }
|
||
pre { background: #f8f9fa; padding: 15px; border-radius: 5px; overflow-x: auto; font-size: 0.9em; border: 1px solid #e9ecef; }
|
||
code { font-family: Consolas, Monaco, monospace; background: #f8f9fa; padding: 2px 4px; border-radius: 3px; }
|
||
table { border-collapse: collapse; width: 100%; margin-bottom: 1.5em; }
|
||
th, td { border: 1px solid #dee2e6; padding: 10px; text-align: left; }
|
||
th { background-color: #f8f9fa; font-weight: bold; }
|
||
.doc-header { background-color: #ecf0f1; padding: 15px; border-radius: 5px; margin-bottom: 20px; margin-top: 40px; border-left: 5px solid #3498db; }
|
||
.doc-header h2 { margin: 0; border: none; padding: 0; color: #2980b9; }
|
||
.doc-path { font-family: monospace; font-size: 0.9em; color: #7f8c8d; }
|
||
|
||
@media print {
|
||
body { max-width: 100%; padding: 0; margin: 1cm; font-size: 11pt; }
|
||
.page-break { page-break-before: always; }
|
||
pre, code { white-space: pre-wrap; word-wrap: break-word; font-size: 10pt; border: none; background: transparent; }
|
||
a { text-decoration: none; color: black; }
|
||
h1 { font-size: 24pt; }
|
||
h2 { font-size: 18pt; }
|
||
h3 { font-size: 14pt; }
|
||
.doc-header { border: 1px solid #ccc; background-color: transparent; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>Intercalaire 3 : APPS & SERVICES</h1>
|
||
<p><em>Généré le 4 Avril 2026 - Projet Talas</em></p>
|
||
<hr>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/APIs_&_Rust_Modules/README.md</div>
|
||
</div>
|
||
|
||
<h1>APIs & Modules Rust – Performances & Interop</h1>
|
||
<p>Ce dossier contient les spécifications API de Talas (REST/gRPC), ainsi que les <strong>modules Rust haute performance</strong> pour le streaming audio, le traitement en ligne, et le rendu.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Créer une interopérabilité robuste entre les différents services.</li>
|
||
<li>Offrir un moteur Rust performant pour les traitements audio.</li>
|
||
<li>Structurer une API claire, documentée, et évolutive.</li>
|
||
</ul>
|
||
<h2>Contenu :</h2>
|
||
<ul>
|
||
<li><code>API_Specs/</code> : OpenAPI, gRPC Protobuf, GraphQL schemas</li>
|
||
<li><code>Rust_Engines/</code> : streaming, encodage, plugins</li>
|
||
<li><code>Benchmarks/</code> : perfs sur FLAC, Opus, WebRTC</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Ces modules peuvent être exposés comme services REST ou microservices via gRPC.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 ROUTES_API.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/APIs_&_Rust_Modules/ROUTES_API.md</div>
|
||
</div>
|
||
|
||
<h1>Référence Complète des Routes API Veza</h1>
|
||
<blockquote>
|
||
<p>Inventaire exhaustif de tous les endpoints REST et WebSocket.
|
||
Source : <code>veza-backend-api/internal/api/routes_*.go</code> et <code>veza-stream-server/src/routes/api.rs</code>
|
||
~500+ endpoints au total.</p>
|
||
</blockquote>
|
||
<h2>Conventions</h2>
|
||
<ul>
|
||
<li><strong>Base URL</strong> : <code>/api/v1</code></li>
|
||
<li><strong>Auth</strong> : JWT RS256 via cookie HTTP-only ou header <code>Authorization: Bearer <token></code></li>
|
||
<li><strong>CSRF</strong> : Token Redis obligatoire sur tous les POST/PUT/DELETE protégés</li>
|
||
<li><strong>Rate limiting</strong> : Global (1000 req/s), par IP (100 req/s), par endpoint (variable)</li>
|
||
<li><strong>Réponses</strong> : JSON, pagination par <code>?page=N&limit=N</code></li>
|
||
</ul>
|
||
<h3>Légende des badges</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Badge</th>
|
||
<th>Signification</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓</td>
|
||
<td>Public (pas d'auth)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒</td>
|
||
<td>Auth requise</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑</td>
|
||
<td>Auth + admin + MFA</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨</td>
|
||
<td>Auth + rôle content_creator</td>
|
||
</tr>
|
||
<tr>
|
||
<td>⚡</td>
|
||
<td>Rate limité spécifiquement</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>1. Authentification (<code>/auth</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_auth.go</code></p>
|
||
<h3>Endpoints publics</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
<th>Notes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/register</code></td>
|
||
<td>Inscription</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/login</code></td>
|
||
<td>Connexion</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/login/2fa</code></td>
|
||
<td>Connexion avec 2FA</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/refresh</code></td>
|
||
<td>Rafraîchir le token</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/verify-email</code></td>
|
||
<td>Vérification email</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/resend-verification</code></td>
|
||
<td>Renvoyer email vérification</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/auth/check-username</code></td>
|
||
<td>Disponibilité pseudo</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/password/reset-request</code></td>
|
||
<td>Demande reset mot de passe</td>
|
||
<td>⚡ Rate limité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/auth/password/reset</code></td>
|
||
<td>Reset mot de passe</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/auth/oauth/providers</code></td>
|
||
<td>Liste des providers OAuth</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/auth/oauth/:provider</code></td>
|
||
<td>Initier OAuth</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/auth/oauth/:provider/callback</code></td>
|
||
<td>Callback OAuth</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints protégés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/logout</code></td>
|
||
<td>Déconnexion</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/auth/me</code></td>
|
||
<td>Info utilisateur courant</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/stream-token</code></td>
|
||
<td>Générer token streaming</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/2fa/setup</code></td>
|
||
<td>Configurer 2FA</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/2fa/verify</code></td>
|
||
<td>Vérifier 2FA</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/2fa/disable</code></td>
|
||
<td>Désactiver 2FA</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/auth/2fa/status</code></td>
|
||
<td>Statut 2FA</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/auth/passkeys</code></td>
|
||
<td>Lister Passkeys/WebAuthn</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/passkeys/register/begin</code></td>
|
||
<td>Début enregistrement passkey</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/auth/passkeys/register/finish</code></td>
|
||
<td>Fin enregistrement passkey</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/auth/passkeys/:id</code></td>
|
||
<td>Renommer passkey</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/auth/passkeys/:id</code></td>
|
||
<td>Supprimer passkey</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/auth/login-history</code></td>
|
||
<td>Historique connexions</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>2. Utilisateurs (<code>/users</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_users.go</code></p>
|
||
<h3>Endpoints publics</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users</code></td>
|
||
<td>Lister les utilisateurs</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/:id</code></td>
|
||
<td>Profil utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/by-username/:username</code></td>
|
||
<td>Profil par pseudo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/search</code></td>
|
||
<td>Recherche utilisateurs</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/:id/reposts</code></td>
|
||
<td>Reposts de l'utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/:id/gear</code></td>
|
||
<td>Profil équipement public</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints protégés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/suggestions</code></td>
|
||
<td>Suggestions de follow</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/settings</code></td>
|
||
<td>Paramètres utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/users/settings</code></td>
|
||
<td>Modifier paramètres</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/users/:id</code></td>
|
||
<td>Modifier profil (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/:id</code></td>
|
||
<td>Supprimer utilisateur (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/:id/completion</code></td>
|
||
<td>Complétion profil</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/users/me/presence</code></td>
|
||
<td>Mettre à jour présence</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/:id/presence</code></td>
|
||
<td>Voir la présence</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/:id/follow</code></td>
|
||
<td>Suivre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/:id/follow</code></td>
|
||
<td>Ne plus suivre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/:id/block</code></td>
|
||
<td>Bloquer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/:id/block</code></td>
|
||
<td>Débloquer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/:id/roles</code></td>
|
||
<td>Assigner rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/:id/roles/:roleId</code></td>
|
||
<td>Révoquer rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/:id/avatar</code></td>
|
||
<td>Upload avatar</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/:id/avatar</code></td>
|
||
<td>Supprimer avatar</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/:id/likes</code></td>
|
||
<td>Pistes likées</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/users/me/password</code></td>
|
||
<td>Changer mot de passe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/me/export</code></td>
|
||
<td>Export JSON (sync, fallback)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/me/export</code></td>
|
||
<td>Export RGPD (async)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/me/exports</code></td>
|
||
<td>Lister exports</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/me/exports/:id/download</code></td>
|
||
<td>Télécharger export</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/users/me/exports/:id</code></td>
|
||
<td>Statut export</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/users/me</code></td>
|
||
<td>Supprimer compte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/users/me/privacy/opt-out</code></td>
|
||
<td>CCPA Do Not Sell</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>3. Rôles (<code>/roles</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_users.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/roles</code></td>
|
||
<td>Lister les rôles</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/roles/:id</code></td>
|
||
<td>Détail d'un rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/roles</code></td>
|
||
<td>Créer un rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/roles/:id</code></td>
|
||
<td>Modifier un rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/roles/:id</code></td>
|
||
<td>Supprimer un rôle</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>4. Pistes audio (<code>/tracks</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_tracks.go</code></p>
|
||
<h3>Endpoints publics</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks</code></td>
|
||
<td>Lister les pistes (auth optionnelle)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/search</code></td>
|
||
<td>Recherche de pistes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/suggested-tags</code></td>
|
||
<td>Suggestions de tags</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id</code></td>
|
||
<td>Détail piste (auth optionnelle)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/lyrics</code></td>
|
||
<td>Paroles</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/stats</code></td>
|
||
<td>Statistiques</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/waveform</code></td>
|
||
<td>Forme d'onde</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/history</code></td>
|
||
<td>Historique</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/download</code></td>
|
||
<td>Téléchargement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/shared/:token</code></td>
|
||
<td>Piste partagée</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/repost</code></td>
|
||
<td>Statut repost (auth optionnelle)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/comments</code></td>
|
||
<td>Commentaires</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints HLS (publics)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/hls/info</code></td>
|
||
<td>Info stream HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/hls/status</code></td>
|
||
<td>Statut stream HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/hls/master.m3u8</code></td>
|
||
<td>Playlist master HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/hls/:bitrate/playlist.m3u8</code></td>
|
||
<td>Playlist qualité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/tracks/:id/hls/:bitrate/:segment</code></td>
|
||
<td>Segment HLS</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints protégés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/tracks</code></td>
|
||
<td>Upload piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/recommendations</code></td>
|
||
<td>Recommandations</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/tracks/:id</code></td>
|
||
<td>Modifier piste (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/tracks/:id/lyrics</code></td>
|
||
<td>Modifier paroles (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/tracks/:id</code></td>
|
||
<td>Supprimer piste (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/:id/status</code></td>
|
||
<td>Statut upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/initiate</code></td>
|
||
<td>Initier upload chunked</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/chunk</code></td>
|
||
<td>Upload chunk</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/complete</code></td>
|
||
<td>Finaliser upload chunked</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/quota/:id</code></td>
|
||
<td>Quota upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/resume/:uploadId</code></td>
|
||
<td>Reprendre upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/batch/delete</code></td>
|
||
<td>Suppression batch</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/batch/update</code></td>
|
||
<td>Mise à jour batch</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/like</code></td>
|
||
<td>Liker</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/tracks/:id/like</code></td>
|
||
<td>Unliker</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/:id/likes</code></td>
|
||
<td>Likes de la piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/repost</code></td>
|
||
<td>Reposter</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/tracks/:id/repost</code></td>
|
||
<td>Annuler repost</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/share</code></td>
|
||
<td>Créer partage</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/tracks/share/:id</code></td>
|
||
<td>Révoquer partage</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/versions/:versionId/restore</code></td>
|
||
<td>Restaurer version</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/play</code></td>
|
||
<td>Enregistrer lecture</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/stems</code></td>
|
||
<td>Upload stem</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/:id/stems</code></td>
|
||
<td>Lister stems</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/:id/stems/:name/download</code></td>
|
||
<td>Télécharger stem</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Commentaires</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/tracks/:id/comments</code></td>
|
||
<td>Créer commentaire</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/comments/:id</code></td>
|
||
<td>Supprimer commentaire</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>5. Playlists (<code>/playlists</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_playlists.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/playlists/shared/:token</code></td>
|
||
<td>Playlist partagée</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists</code></td>
|
||
<td>Mes playlists</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists</code></td>
|
||
<td>Créer playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists/import</code></td>
|
||
<td>Importer playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/search</code></td>
|
||
<td>Recherche</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/recommendations</code></td>
|
||
<td>Recommandations</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/favoris</code></td>
|
||
<td>Playlist favoris</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id</code></td>
|
||
<td>Détail playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id/analytics</code></td>
|
||
<td>Stats playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/playlists/:id</code></td>
|
||
<td>Modifier (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/playlists/:id</code></td>
|
||
<td>Supprimer (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists/:id/tracks</code></td>
|
||
<td>Ajouter piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/playlists/:id/tracks/:track_id</code></td>
|
||
<td>Retirer piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/playlists/:id/tracks/reorder</code></td>
|
||
<td>Réordonner</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists/:id/collaborators</code></td>
|
||
<td>Ajouter collaborateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id/collaborators</code></td>
|
||
<td>Lister collaborateurs</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/playlists/:id/collaborators/:userId</code></td>
|
||
<td>Modifier permission</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/playlists/:id/collaborators/:userId</code></td>
|
||
<td>Retirer collaborateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists/:id/share</code></td>
|
||
<td>Créer lien de partage</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id/export/json</code></td>
|
||
<td>Export JSON</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id/export/csv</code></td>
|
||
<td>Export CSV</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/playlists/:id/export/m3u</code></td>
|
||
<td>Export M3U</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/playlists/:id/duplicate</code></td>
|
||
<td>Dupliquer</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>6. Chat & Conversations (<code>/chat</code>, <code>/conversations</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>router.go</code>, <code>routes_core.go</code></p>
|
||
<h3>Chat</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/chat/ws</code></td>
|
||
<td>WebSocket chat</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/chat/token</code></td>
|
||
<td>Obtenir token chat</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/chat/stats</code></td>
|
||
<td>Stats chat</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/chat/rooms/:roomId/messages/:messageId/reactions</code></td>
|
||
<td>Ajouter réaction</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/chat/rooms/:roomId/messages/:messageId/reactions</code></td>
|
||
<td>Retirer réaction</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/chat/rooms/:roomId/messages/search</code></td>
|
||
<td>Recherche messages</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/chat/rooms/:roomId/attachments</code></td>
|
||
<td>Upload pièce jointe</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Conversations</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/conversations</code></td>
|
||
<td>Mes conversations</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/conversations</code></td>
|
||
<td>Créer conversation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/conversations/join/:token</code></td>
|
||
<td>Rejoindre par token</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/conversations/:id</code></td>
|
||
<td>Détail conversation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/conversations/:id</code></td>
|
||
<td>Modifier conversation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/conversations/:id</code></td>
|
||
<td>Supprimer conversation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/conversations/:id/leave</code></td>
|
||
<td>Quitter</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/conversations/:id/members</code></td>
|
||
<td>Lister membres</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/conversations/:id/members</code></td>
|
||
<td>Ajouter membre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/conversations/:id/members/:userId</code></td>
|
||
<td>Exclure membre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PATCH</td>
|
||
<td><code>/conversations/:id/members/:userId</code></td>
|
||
<td>Modifier rôle membre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/conversations/:id/participants</code></td>
|
||
<td>Ajouter participant</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/conversations/:id/participants/:userId</code></td>
|
||
<td>Retirer participant</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/conversations/:id/invitations</code></td>
|
||
<td>Créer invitation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/conversations/:id/history</code></td>
|
||
<td>Historique</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>7. Social (<code>/social</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_social.go</code></p>
|
||
<h3>Endpoints publics</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/social/feed</code></td>
|
||
<td>Feed (auth optionnelle)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/social/explore</code></td>
|
||
<td>Explorer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/social/trending</code></td>
|
||
<td>Tendances</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/social/posts/user/:user_id</code></td>
|
||
<td>Posts utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/social/groups</code></td>
|
||
<td>Lister groupes</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints protégés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/social/groups/mine</code></td>
|
||
<td>Mes groupes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/social/groups/:id</code></td>
|
||
<td>Détail groupe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/posts</code></td>
|
||
<td>Créer post</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/like</code></td>
|
||
<td>Toggle like</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/comments</code></td>
|
||
<td>Ajouter commentaire</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups</code></td>
|
||
<td>Créer groupe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups/:id/join</code></td>
|
||
<td>Rejoindre groupe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/social/groups/:id/leave</code></td>
|
||
<td>Quitter groupe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups/:id/request</code></td>
|
||
<td>Demande adhésion</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/social/groups/:id/requests</code></td>
|
||
<td>Demandes en attente</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups/:id/requests/:request_id/approve</code></td>
|
||
<td>Approuver</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups/:id/requests/:request_id/reject</code></td>
|
||
<td>Rejeter</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/social/groups/:id/invite</code></td>
|
||
<td>Inviter membre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/social/groups/:id/members/:user_id/role</code></td>
|
||
<td>Modifier rôle</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>8. Découverte (<code>/discover</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_discover.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/discover/genres</code></td>
|
||
<td>Lister genres</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/discover/genre/:genre</code></td>
|
||
<td>Pistes par genre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/discover/tag/:tag</code></td>
|
||
<td>Pistes par tag</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/discover/playlists/editorial</code></td>
|
||
<td>Playlists éditoriales</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/discover/genre/:genre/follow</code></td>
|
||
<td>Suivre genre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/discover/genre/:genre/follow</code></td>
|
||
<td>Ne plus suivre genre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/discover/tag/:tag/follow</code></td>
|
||
<td>Suivre tag</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/discover/tag/:tag/follow</code></td>
|
||
<td>Ne plus suivre tag</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>9. Recherche (<code>/search</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_search.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/search</code></td>
|
||
<td>Recherche unifiée (pistes, users, playlists)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/search/suggestions</code></td>
|
||
<td>Suggestions</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Backend : Elasticsearch (fallback PostgreSQL full-text).</p>
|
||
<hr />
|
||
<h2>10. Feed (<code>/feed</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_feed.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/feed</code></td>
|
||
<td>Feed chronologique des pistes</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>11. File d'attente (<code>/queue</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_queue.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/queue</code></td>
|
||
<td>Ma file d'attente</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/queue</code></td>
|
||
<td>Mettre à jour</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/queue/items</code></td>
|
||
<td>Ajouter item</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/queue/items/:id</code></td>
|
||
<td>Retirer item</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/queue</code></td>
|
||
<td>Vider la file</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/queue/session</code></td>
|
||
<td>Créer session collaborative</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/queue/session/:token</code></td>
|
||
<td>Supprimer session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/queue/session/:token/items</code></td>
|
||
<td>Ajouter à session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/queue/session/:token/items/:id</code></td>
|
||
<td>Retirer de session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/queue/session/:token</code></td>
|
||
<td>Voir session (auth optionnelle)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>12. Marketplace (<code>/marketplace</code>, <code>/sell</code>, <code>/commerce</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_marketplace.go</code></p>
|
||
<h3>Marketplace (publics)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/marketplace/products</code></td>
|
||
<td>Lister produits</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/marketplace/products/:id</code></td>
|
||
<td>Détail produit</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/marketplace/products/:id/preview</code></td>
|
||
<td>Prévisualiser</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/marketplace/products/:id/reviews</code></td>
|
||
<td>Avis</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Marketplace (protégés)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/marketplace/products</code></td>
|
||
<td>Créer produit</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/marketplace/products/:id/preview</code></td>
|
||
<td>Upload preview</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/marketplace/products/:id</code></td>
|
||
<td>Modifier (ownership)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/marketplace/products/:id/images</code></td>
|
||
<td>Modifier images</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/orders</code></td>
|
||
<td>Mes commandes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/orders/:id</code></td>
|
||
<td>Détail commande</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/orders/:id/invoice</code></td>
|
||
<td>Facture</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/marketplace/orders/:id/refund</code></td>
|
||
<td>Remboursement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/marketplace/orders</code></td>
|
||
<td>Créer commande</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/download/:product_id</code></td>
|
||
<td>URL téléchargement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/licenses/mine</code></td>
|
||
<td>Mes licences</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/marketplace/products/:id/reviews</code></td>
|
||
<td>Laisser avis</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/marketplace/wishlist</code></td>
|
||
<td>Wishlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/marketplace/wishlist</code></td>
|
||
<td>Ajouter à wishlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/marketplace/wishlist/:productId</code></td>
|
||
<td>Retirer de wishlist</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Vendeur (<code>/sell</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/stats</code></td>
|
||
<td>Stats ventes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/stats/evolution</code></td>
|
||
<td>Évolution stats</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/stats/top-products</code></td>
|
||
<td>Top produits</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/sales</code></td>
|
||
<td>Historique ventes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/sell/connect/onboard</code></td>
|
||
<td>Onboarding Stripe Connect</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/connect/callback</code></td>
|
||
<td>Callback Stripe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/balance</code></td>
|
||
<td>Solde</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/transfers</code></td>
|
||
<td>Transferts</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/marketplace-balance</code></td>
|
||
<td>Solde marketplace</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/payouts</code></td>
|
||
<td>Historique versements</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/sell/payouts/request</code></td>
|
||
<td>Demander versement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 POST</td>
|
||
<td><code>/sell/kyc/start</code></td>
|
||
<td>Démarrer KYC</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒🎨 GET</td>
|
||
<td><code>/sell/kyc/status</code></td>
|
||
<td>Statut KYC</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Commerce (<code>/commerce</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/commerce/cart</code></td>
|
||
<td>Panier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/commerce/promo/:code</code></td>
|
||
<td>Valider code promo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/commerce/cart/items</code></td>
|
||
<td>Ajouter au panier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/commerce/cart/items/:id</code></td>
|
||
<td>Retirer du panier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/commerce/cart/checkout</code></td>
|
||
<td>Payer</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Support</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/support/tickets</code></td>
|
||
<td>Soumettre ticket</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>13. Webhooks (<code>/webhooks</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_webhooks.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/webhooks/hyperswitch</code></td>
|
||
<td>Webhook paiement (vérif. signature)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/webhooks</code></td>
|
||
<td>Enregistrer webhook</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/webhooks</code></td>
|
||
<td>Lister webhooks</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/webhooks/:id</code></td>
|
||
<td>Supprimer webhook</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/webhooks/stats</code></td>
|
||
<td>Stats webhooks</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/webhooks/:id/test</code></td>
|
||
<td>Tester webhook</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/webhooks/:id/regenerate-key</code></td>
|
||
<td>Régénérer clé API</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>14. Analytics (<code>/analytics</code>, <code>/creator/analytics</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_analytics.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/creator/stats</code></td>
|
||
<td>Stats créateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/creator/charts</code></td>
|
||
<td>Graphiques</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/creator/export</code></td>
|
||
<td>Export</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics</code></td>
|
||
<td>Analytics globales</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/analytics/events</code></td>
|
||
<td>Enregistrer événement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/tracks/:id</code></td>
|
||
<td>Analytics piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/traffic-sources</code></td>
|
||
<td>Sources de trafic</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/analytics/device-breakdown</code></td>
|
||
<td>Répartition appareils</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/dashboard</code></td>
|
||
<td>Dashboard créateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/plays</code></td>
|
||
<td>Évolution lectures</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/sales</code></td>
|
||
<td>Ventes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/discovery</code></td>
|
||
<td>Sources découverte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/geographic</code></td>
|
||
<td>Géographie</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/audience</code></td>
|
||
<td>Audience</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/live/:streamId</code></td>
|
||
<td>Métriques live</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/tracks</code></td>
|
||
<td>Pistes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/export</code></td>
|
||
<td>Export analytics</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/heatmap/:trackId</code></td>
|
||
<td>Heatmap piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/compare</code></td>
|
||
<td>Comparaison périodes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/marketplace</code></td>
|
||
<td>Analytics marketplace</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creator/analytics/alerts</code></td>
|
||
<td>Alertes métriques</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/creator/analytics/alerts</code></td>
|
||
<td>Créer alerte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/creator/analytics/alerts/preferences</code></td>
|
||
<td>Préférences alertes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/creator/analytics/alerts/:alertId</code></td>
|
||
<td>Supprimer alerte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/creator/analytics/alerts/check</code></td>
|
||
<td>Vérifier alertes</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>15. Modération (<code>/admin/moderation</code>, <code>/reports</code>, <code>/strikes</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_moderation.go</code></p>
|
||
<h3>Admin</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/queue</code></td>
|
||
<td>File de modération</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/moderation/reports/:id/process</code></td>
|
||
<td>Traiter signalement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/moderation/reports/:id/assign</code></td>
|
||
<td>Assigner signalement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/spam</code></td>
|
||
<td>Détections spam</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/fingerprints</code></td>
|
||
<td>Empreintes en attente</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/moderation/fingerprints/:trackId/review</code></td>
|
||
<td>Vérifier empreinte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/users/:userId/strikes</code></td>
|
||
<td>Strikes utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/appeals</code></td>
|
||
<td>Appels en attente</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/moderation/appeals/:strikeId/resolve</code></td>
|
||
<td>Résoudre appel</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/moderation/stats</code></td>
|
||
<td>Stats modération</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Utilisateur</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/reports</code></td>
|
||
<td>Signaler contenu</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/me/strikes</code></td>
|
||
<td>Mes strikes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/strikes/:strikeId/appeal</code></td>
|
||
<td>Faire appel</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>16. Administration plateforme (<code>/admin/platform</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_admin_platform.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/platform/metrics</code></td>
|
||
<td>Métriques plateforme</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/platform/users</code></td>
|
||
<td>Recherche utilisateurs</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/platform/users/:userId</code></td>
|
||
<td>Détail utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 PUT</td>
|
||
<td><code>/admin/platform/users/:userId/role</code></td>
|
||
<td>Modifier rôle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/platform/users/:userId/suspend</code></td>
|
||
<td>Suspendre</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/platform/users/:userId/unsuspend</code></td>
|
||
<td>Réactiver</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/platform/content</code></td>
|
||
<td>Recherche contenu</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/platform/content/:id/hide</code></td>
|
||
<td>Masquer contenu</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/platform/content/:id/restore</code></td>
|
||
<td>Restaurer contenu</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/platform/payments</code></td>
|
||
<td>Aperçu paiements</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/platform/orders/:id/refund</code></td>
|
||
<td>Rembourser commande</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>17. Live streaming (<code>/live</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_live.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/live/streams</code></td>
|
||
<td>Lister streams live</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/live/streams/:id</code></td>
|
||
<td>Détail stream</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/live/streams/me</code></td>
|
||
<td>Mes streams</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/live/streams/me/key</code></td>
|
||
<td>Clé de stream</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/live/streams/me/key/regenerate</code></td>
|
||
<td>Régénérer clé</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/live/streams</code></td>
|
||
<td>Créer live</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/live/streams/:id</code></td>
|
||
<td>Modifier live</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/live/callback/publish</code></td>
|
||
<td>Callback RTMP (secret)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/live/callback/publish_done</code></td>
|
||
<td>Callback fin RTMP</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>18. Co-écoute (<code>/co-listening</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_co_listening.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/co-listening/sessions</code></td>
|
||
<td>Créer session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/co-listening/sessions/:id</code></td>
|
||
<td>Détail session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/co-listening/sessions/:id</code></td>
|
||
<td>Terminer session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/co-listening/ws</code></td>
|
||
<td>WebSocket co-écoute (JWT en query)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>19. Inventaire / Équipement (<code>/inventory</code>, <code>/users/:id/gear</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_gear.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/users/:id/gear</code></td>
|
||
<td>Profil équipement public</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/inventory/gear</code></td>
|
||
<td>Lister mon équipement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/inventory/gear</code></td>
|
||
<td>Ajouter équipement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/inventory/gear/:id</code></td>
|
||
<td>Détail équipement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/inventory/gear/:id</code></td>
|
||
<td>Modifier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/inventory/gear/:id</code></td>
|
||
<td>Supprimer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/inventory/gear/:id/images</code></td>
|
||
<td>Upload image</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/inventory/gear/:id/images/:img_id</code></td>
|
||
<td>Supprimer image</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/inventory/gear/:id/documents</code></td>
|
||
<td>Upload document</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/inventory/gear/:id/documents</code></td>
|
||
<td>Lister documents</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/inventory/gear/:id/documents/:docId</code></td>
|
||
<td>Supprimer document</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/inventory/gear/:id/repairs</code></td>
|
||
<td>Ajouter réparation</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/inventory/gear/:id/repairs</code></td>
|
||
<td>Lister réparations</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/inventory/gear/:id/repairs/:repairId</code></td>
|
||
<td>Supprimer réparation</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>20. Cloud personnel (<code>/cloud</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_cloud.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/cloud/shared/:token</code></td>
|
||
<td>Fichier partagé</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/folders</code></td>
|
||
<td>Lister dossiers</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/folders</code></td>
|
||
<td>Créer dossier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/cloud/folders/:id</code></td>
|
||
<td>Renommer dossier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/cloud/folders/:id</code></td>
|
||
<td>Supprimer dossier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/files</code></td>
|
||
<td>Lister fichiers</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/files</code></td>
|
||
<td>Upload fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/files/:id</code></td>
|
||
<td>Détail fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/cloud/files/:id</code></td>
|
||
<td>Supprimer fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/files/:id/stream</code></td>
|
||
<td>Streamer fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/files/:id/publish</code></td>
|
||
<td>Publier comme piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/files/:id/versions</code></td>
|
||
<td>Lister versions</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/files/:id/versions</code></td>
|
||
<td>Créer version</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/files/:id/restore/:version</code></td>
|
||
<td>Restaurer version</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/cloud/files/:id/share</code></td>
|
||
<td>Partager fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/cloud/quota</code></td>
|
||
<td>Quota stockage</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>21. Abonnements (<code>/subscriptions</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_subscription.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/subscriptions/plans</code></td>
|
||
<td>Lister forfaits</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/subscriptions/plans/:id</code></td>
|
||
<td>Détail forfait</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/subscriptions/me</code></td>
|
||
<td>Mon abonnement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/subscriptions/subscribe</code></td>
|
||
<td>S'abonner</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/subscriptions/cancel</code></td>
|
||
<td>Annuler</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/subscriptions/reactivate</code></td>
|
||
<td>Réactiver</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/subscriptions/billing-cycle</code></td>
|
||
<td>Changer cycle</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/subscriptions/invoices</code></td>
|
||
<td>Factures</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/subscriptions/history</code></td>
|
||
<td>Historique</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>22. Distribution (<code>/distributions</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_distribution.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/distributions/submit</code></td>
|
||
<td>Soumettre distribution</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/distributions</code></td>
|
||
<td>Lister distributions</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/distributions/:id</code></td>
|
||
<td>Détail</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/distributions/:id/status-history</code></td>
|
||
<td>Historique statut</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/distributions/:id/remove</code></td>
|
||
<td>Retirer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tracks/:id/distributions</code></td>
|
||
<td>Distributions d'une piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creators/me/external-royalties</code></td>
|
||
<td>Royalties externes</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>23. Éducation (<code>/courses</code>, <code>/enrollments</code>, <code>/lessons</code>, <code>/certificates</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_education.go</code></p>
|
||
<h3>Endpoints publics</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/courses</code></td>
|
||
<td>Cours publiés</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/courses/:id</code></td>
|
||
<td>Détail cours</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/courses/:id/lessons</code></td>
|
||
<td>Leçons du cours</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/courses/:id/reviews</code></td>
|
||
<td>Avis</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/courses/slug/:slug</code></td>
|
||
<td>Cours par slug</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/certificates/:code</code></td>
|
||
<td>Vérifier certificat</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Endpoints protégés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses</code></td>
|
||
<td>Créer cours</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/courses/:id</code></td>
|
||
<td>Modifier cours</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/courses/:id</code></td>
|
||
<td>Supprimer cours</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/publish</code></td>
|
||
<td>Publier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/archive</code></td>
|
||
<td>Archiver</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/lessons</code></td>
|
||
<td>Créer leçon</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/courses/:id/lessons/:lesson_id</code></td>
|
||
<td>Modifier leçon</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/courses/:id/lessons/:lesson_id</code></td>
|
||
<td>Supprimer leçon</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/lessons/reorder</code></td>
|
||
<td>Réordonner leçons</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/lessons/:lesson_id/video</code></td>
|
||
<td>Upload vidéo</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/enroll</code></td>
|
||
<td>S'inscrire</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/courses/:id/progress</code></td>
|
||
<td>Progression</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/certificate</code></td>
|
||
<td>Obtenir certificat</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/courses/:id/reviews</code></td>
|
||
<td>Laisser avis</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/enrollments</code></td>
|
||
<td>Mes inscriptions</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/lessons/:lesson_id/progress</code></td>
|
||
<td>Mise à jour progression</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/certificates</code></td>
|
||
<td>Mes certificats</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/creators/me/courses</code></td>
|
||
<td>Mes cours (créateur)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>24. Tags & Suggestions (<code>/tags</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_tag.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/tags/suggest</code></td>
|
||
<td>Suggestions de tags</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>25. Développeur (<code>/developer</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_developer.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/developer/api-keys</code></td>
|
||
<td>Lister clés API</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/developer/api-keys</code></td>
|
||
<td>Créer clé API</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/developer/api-keys/:id</code></td>
|
||
<td>Supprimer clé API</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>26. Sessions (<code>/sessions</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/sessions/logout</code></td>
|
||
<td>Déconnexion</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/sessions/logout-all</code></td>
|
||
<td>Déconnexion tous appareils</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/sessions/logout-others</code></td>
|
||
<td>Déconnexion autres appareils</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/sessions</code></td>
|
||
<td>Sessions actives</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/sessions/:session_id</code></td>
|
||
<td>Révoquer session</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/sessions/stats</code></td>
|
||
<td>Stats sessions</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/sessions/refresh</code></td>
|
||
<td>Rafraîchir session</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>27. Uploads (<code>/uploads</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/upload/limits</code></td>
|
||
<td>Limites upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/upload/validate-type</code></td>
|
||
<td>Valider type fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/uploads/</code></td>
|
||
<td>Upload fichier</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/uploads/batch</code></td>
|
||
<td>Upload batch</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/uploads/:id/status</code></td>
|
||
<td>Statut upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/uploads/:id/progress</code></td>
|
||
<td>Progression</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/uploads/:id</code></td>
|
||
<td>Supprimer upload</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/uploads/stats</code></td>
|
||
<td>Stats uploads</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>28. Notifications (<code>/notifications</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/notifications</code></td>
|
||
<td>Mes notifications</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/notifications/unread-count</code></td>
|
||
<td>Non lues</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/notifications/preferences</code></td>
|
||
<td>Préférences</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 PUT</td>
|
||
<td><code>/notifications/preferences</code></td>
|
||
<td>Modifier préférences</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/notifications/push/subscribe</code></td>
|
||
<td>S'abonner push</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/notifications/:id/read</code></td>
|
||
<td>Marquer lue</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/notifications/read-all</code></td>
|
||
<td>Tout marquer lu</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/notifications/:id</code></td>
|
||
<td>Supprimer</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 DELETE</td>
|
||
<td><code>/notifications</code></td>
|
||
<td>Tout supprimer</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>29. Audit (<code>/audit</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/logs</code></td>
|
||
<td>Rechercher logs</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/stats</code></td>
|
||
<td>Stats audit</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/activity</code></td>
|
||
<td>Activité utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/suspicious</code></td>
|
||
<td>Activité suspecte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/ip/:ip</code></td>
|
||
<td>Activité d'une IP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/audit/logs/:id</code></td>
|
||
<td>Détail log</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/audit/cleanup</code></td>
|
||
<td>Nettoyage anciens logs</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>30. Santé & Métriques (publics)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/health</code></td>
|
||
<td>Santé basique</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/health/deep</code></td>
|
||
<td>Santé approfondie</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/healthz</code></td>
|
||
<td>Liveness probe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/readyz</code></td>
|
||
<td>Readiness probe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/api/v1/status</code></td>
|
||
<td>Statut API</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/api/v1/csrf-token</code></td>
|
||
<td>Token CSRF</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 POST</td>
|
||
<td><code>/api/v1/logs/frontend</code></td>
|
||
<td>Logs frontend ⚡</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/api/v1/announcements/active</code></td>
|
||
<td>Annonces actives</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/metrics</code></td>
|
||
<td>Prometheus (protégé metrics middleware)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>31. Administration générale (<code>/admin</code>)</h2>
|
||
<p><strong>Fichier</strong> : <code>routes_core.go</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/audit/logs</code></td>
|
||
<td>Logs audit admin</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/audit/stats</code></td>
|
||
<td>Stats audit admin</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/audit/suspicious</code></td>
|
||
<td>Activité suspecte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/reports</code></td>
|
||
<td>Signalements</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/reports/:id/resolve</code></td>
|
||
<td>Résoudre signalement</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 PUT</td>
|
||
<td><code>/admin/maintenance</code></td>
|
||
<td>Mode maintenance</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/maintenance</code></td>
|
||
<td>Statut maintenance</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/announcements</code></td>
|
||
<td>Lister annonces</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/announcements</code></td>
|
||
<td>Créer annonce</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 DELETE</td>
|
||
<td><code>/admin/announcements/:id</code></td>
|
||
<td>Supprimer annonce</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/transfers</code></td>
|
||
<td>Transferts</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/transfers/:id/retry</code></td>
|
||
<td>Relancer transfert</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/auth/unlock-account</code></td>
|
||
<td>Débloquer compte</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 POST</td>
|
||
<td><code>/admin/search/reindex</code></td>
|
||
<td>Réindexer Elasticsearch</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 GET</td>
|
||
<td><code>/admin/feature-flags</code></td>
|
||
<td>Feature flags</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒👑 PUT</td>
|
||
<td><code>/admin/feature-flags/:name</code></td>
|
||
<td>Toggle feature flag</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>32. Routes internes (entre services)</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/internal/tracks/:id/stream-ready</code></td>
|
||
<td>Callback stream (header X-Stream-Secret)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/internal/stream-events</code></td>
|
||
<td>Événements stream</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Serveur Streaming Rust (Axum)</h2>
|
||
<p>Voir [[SERVEUR_STREAMING_RUST]] pour le détail complet.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/</code></td>
|
||
<td>Info serveur</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/health</code></td>
|
||
<td>Santé</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/healthz</code></td>
|
||
<td>Liveness</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/readyz</code></td>
|
||
<td>Readiness</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/metrics</code></td>
|
||
<td>Prometheus</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/stream/{filename}</code></td>
|
||
<td>Stream audio (signature)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/internal/jobs/transcode</code></td>
|
||
<td>Job transcoding (clé interne)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 POST</td>
|
||
<td><code>/v1/stream/transcode</code></td>
|
||
<td>Initier transcoding</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/v1/stream/job/{id}</code></td>
|
||
<td>Statut job</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/v1/stream/hls/{job_id}/index.m3u8</code></td>
|
||
<td>Playlist HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/v1/stream/hls/{job_id}/{segment}</code></td>
|
||
<td>Segment HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/hls/{track_id}/master.m3u8</code></td>
|
||
<td>Master playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/hls/{track_id}/{quality}/playlist.m3u8</code></td>
|
||
<td>Playlist qualité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔒 GET</td>
|
||
<td><code>/hls/{track_id}/{quality}/{segment}</code></td>
|
||
<td>Segment qualité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>🔓 GET</td>
|
||
<td><code>/ws</code></td>
|
||
<td>WebSocket streaming</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Pile de middlewares globaux (ordre d'exécution)</h2>
|
||
<ol>
|
||
<li><strong>CORS</strong> — Validation des origines</li>
|
||
<li><strong>Cache Headers</strong> — En-têtes CDN</li>
|
||
<li><strong>Maintenance Mode</strong> — Retourne 503 sauf /health et /admin</li>
|
||
<li><strong>Request Logger</strong> — Logs structurés</li>
|
||
<li><strong>Prometheus Metrics</strong> — Compteurs/histogrammes</li>
|
||
<li><strong>Sentry Recovery</strong> — Capture d'erreurs</li>
|
||
<li><strong>Security Headers</strong> — HSTS, CSP, X-Content-Type-Options</li>
|
||
<li><strong>CCPA Header</strong> — Sec-GPC</li>
|
||
<li><strong>Audit Middleware</strong> — Auto-log POST/PUT/DELETE</li>
|
||
<li><strong>API Monitoring</strong> — Suivi pannes/alertes</li>
|
||
<li><strong>Error Handler</strong> — Stack traces en dev/DEBUG</li>
|
||
<li><strong>Recovery</strong> — Récupération après panic</li>
|
||
<li><strong>Request ID</strong> — UUID par requête</li>
|
||
<li><strong>Global Timeout</strong> — Timeout global</li>
|
||
<li><strong>DDoS Rate Limiting</strong> — 1000 req/s global, 100/s par IP</li>
|
||
<li><strong>Rate Limiter</strong> — Général</li>
|
||
<li><strong>Response Cache</strong> — Redis, TTL 5-15 min</li>
|
||
</ol>
|
||
<hr />
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ARCHITECTURE_VEZA]] — Architecture globale</li>
|
||
<li>[[SCHEMA_BASE_DE_DONNEES]] — Schéma PostgreSQL</li>
|
||
<li>[[SERVEUR_STREAMING_RUST]] — Serveur Rust détaillé</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 SERVEUR_STREAMING_RUST.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/APIs_&_Rust_Modules/SERVEUR_STREAMING_RUST.md</div>
|
||
</div>
|
||
|
||
<h1>Serveur Streaming Rust (veza-stream-server)</h1>
|
||
<blockquote>
|
||
<p>Architecture du serveur audio haute performance basé sur Axum.
|
||
Source : <code>veza-stream-server/src/</code></p>
|
||
</blockquote>
|
||
<h2>Vue d'ensemble</h2>
|
||
<p>Le stream server est un service Rust autonome qui gère :
|
||
- <strong>Streaming audio HLS adaptatif</strong> multi-bitrate
|
||
- <strong>WebSocket temps réel</strong> pour la lecture synchronisée
|
||
- <strong>Transcoding audio</strong> via FFmpeg (WAV → MP3, HLS)
|
||
- <strong>Métriques Prometheus</strong> pour le monitoring</p>
|
||
<p>Il communique avec le backend Go via RabbitMQ (événements asynchrones) et des callbacks REST internes.</p>
|
||
<h2>Stack technique</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Composant</th>
|
||
<th>Technologie</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Framework HTTP</td>
|
||
<td>Axum (async Rust)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Runtime</td>
|
||
<td>Tokio</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Auth</td>
|
||
<td>JWT (validation)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Audio</td>
|
||
<td>FFmpeg (transcoding), HLS.js (côté client)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Messaging</td>
|
||
<td>RabbitMQ (consommateur)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Cache</td>
|
||
<td>In-memory (playlists HLS)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Monitoring</td>
|
||
<td>Prometheus</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Stockage</td>
|
||
<td>S3/MinIO</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Base de données</td>
|
||
<td>PostgreSQL (requêtes directes)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Structure des modules</h2>
|
||
<pre><code>veza-stream-server/src/
|
||
├── main.rs # Point d'entrée, initialisation Axum
|
||
├── routes/
|
||
│ └── api.rs # Définition de toutes les routes
|
||
├── streaming/
|
||
│ ├── websocket.rs # Handler WebSocket avec protocole de sync
|
||
│ ├── hls.rs # Génération de playlists HLS
|
||
│ └── adaptive.rs # Sélection adaptative du bitrate
|
||
├── transcoding/
|
||
│ └── mod.rs # Orchestration transcoding FFmpeg
|
||
├── codecs/
|
||
│ └── mod.rs # Wrappers FFmpeg
|
||
├── audio/
|
||
│ └── mod.rs # Utilitaires audio
|
||
├── middleware/
|
||
│ ├── logging.rs # Logs structurés
|
||
│ ├── security.rs # Headers de sécurité
|
||
│ └── rate_limit.rs # Rate limiting par IP
|
||
├── auth/
|
||
│ └── mod.rs # Validation JWT
|
||
├── config/
|
||
│ └── mod.rs # Configuration depuis env
|
||
├── health/
|
||
│ └── mod.rs # Health checks
|
||
├── monitoring/
|
||
│ └── mod.rs # Métriques Prometheus
|
||
├── cache/
|
||
│ └── mod.rs # Cache mémoire playlists
|
||
└── database/
|
||
└── mod.rs # Requêtes PostgreSQL
|
||
</code></pre>
|
||
<h2>Routes</h2>
|
||
<h3>Santé & monitoring</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/</code></td>
|
||
<td>Message racine (info serveur)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/health</code></td>
|
||
<td>Health check détaillé</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/healthz</code></td>
|
||
<td>Liveness probe (Kubernetes)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/readyz</code></td>
|
||
<td>Readiness probe</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/metrics</code></td>
|
||
<td>Métriques Prometheus</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Streaming audio</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
<th>Auth</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/stream/{filename}</code></td>
|
||
<td>Stream fichier audio</td>
|
||
<td>Signature URL</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/hls/{track_id}/master.m3u8</code></td>
|
||
<td>Playlist master HLS</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/hls/{track_id}/{quality}/playlist.m3u8</code></td>
|
||
<td>Playlist par qualité</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/hls/{track_id}/{quality}/{segment}</code></td>
|
||
<td>Segment HLS</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>WS</td>
|
||
<td><code>/ws</code></td>
|
||
<td>WebSocket streaming temps réel</td>
|
||
<td>JWT (query param)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Transcoding</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Méthode</th>
|
||
<th>Route</th>
|
||
<th>Description</th>
|
||
<th>Auth</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/internal/jobs/transcode</code></td>
|
||
<td>Lancer job transcoding</td>
|
||
<td>Clé API interne</td>
|
||
</tr>
|
||
<tr>
|
||
<td>POST</td>
|
||
<td><code>/v1/stream/transcode</code></td>
|
||
<td>Initier transcoding</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/v1/stream/job/{id}</code></td>
|
||
<td>Statut du job</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/v1/stream/hls/{job_id}/index.m3u8</code></td>
|
||
<td>Playlist du job</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/v1/stream/hls/{job_id}/{segment}</code></td>
|
||
<td>Segment du job</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>GET</td>
|
||
<td><code>/api/streams/jobs/{id}/status</code></td>
|
||
<td>Statut détaillé</td>
|
||
<td>JWT</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Protocole WebSocket</h2>
|
||
<p>Le WebSocket (<code>/ws?track_id=...</code>) utilise un protocole personnalisé pour la lecture synchronisée.</p>
|
||
<h3>Commandes client → serveur</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Commande</th>
|
||
<th>Payload</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>play</code></td>
|
||
<td><code>{ position: float }</code></td>
|
||
<td>Démarrer la lecture à la position</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>pause</code></td>
|
||
<td>—</td>
|
||
<td>Mettre en pause</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>seek</code></td>
|
||
<td><code>{ position: float }</code></td>
|
||
<td>Sauter à une position</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>sync</code></td>
|
||
<td><code>{ position: float }</code></td>
|
||
<td>Synchroniser (co-écoute)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>heartbeat</code></td>
|
||
<td>—</td>
|
||
<td>Maintenir la connexion</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>error</code></td>
|
||
<td><code>{ message: string }</code></td>
|
||
<td>Signaler une erreur client</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Réponses serveur → client</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Réponse</th>
|
||
<th>Payload</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>ready</code></td>
|
||
<td><code>{ duration, bitrates }</code></td>
|
||
<td>Serveur prêt à streamer</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>chunk</code></td>
|
||
<td><code>{ data, position, bitrate }</code></td>
|
||
<td>Chunk audio avec métadonnées</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>sync_ack</code></td>
|
||
<td><code>{ position }</code></td>
|
||
<td>Accusé de réception sync</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>error</code></td>
|
||
<td><code>{ code, message }</code></td>
|
||
<td>Erreur serveur</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Cycle de vie d'une connexion</h3>
|
||
<pre><code>Client Serveur
|
||
│ │
|
||
│── WS Connect ─────────────────▶│
|
||
│ (track_id, JWT en query) │
|
||
│ │── Validation JWT
|
||
│ │── Chargement playlist HLS
|
||
│◀── ready ──────────────────────│
|
||
│ (duration, bitrates) │
|
||
│ │
|
||
│── play { position: 0 } ──────▶│
|
||
│ │── Sélection bitrate adaptatif
|
||
│◀── chunk ──────────────────────│
|
||
│◀── chunk ──────────────────────│
|
||
│◀── chunk ──────────────────────│
|
||
│ │
|
||
│── heartbeat ──────────────────▶│ (toutes les 30s)
|
||
│ │
|
||
│── seek { position: 120 } ────▶│
|
||
│◀── chunk ──────────────────────│
|
||
│ │
|
||
│── pause ──────────────────────▶│
|
||
│ │
|
||
│── WS Close ───────────────────▶│
|
||
</code></pre>
|
||
<h2>Streaming HLS adaptatif</h2>
|
||
<p>Le serveur génère et sert des playlists HLS multi-bitrate avec sélection adaptative.</p>
|
||
<h3>Qualités disponibles</h3>
|
||
<p>Le transcoding produit plusieurs qualités à partir du fichier source :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Qualité</th>
|
||
<th>Bitrate</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>low</td>
|
||
<td>64 kbps</td>
|
||
<td>Mobile / réseau faible</td>
|
||
</tr>
|
||
<tr>
|
||
<td>medium</td>
|
||
<td>128 kbps</td>
|
||
<td>Standard</td>
|
||
</tr>
|
||
<tr>
|
||
<td>high</td>
|
||
<td>256 kbps</td>
|
||
<td>Haute qualité</td>
|
||
</tr>
|
||
<tr>
|
||
<td>lossless</td>
|
||
<td>Original</td>
|
||
<td>Audiophile</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Fonctionnement</h3>
|
||
<ol>
|
||
<li><strong>Upload</strong> : Le backend Go reçoit le fichier audio et le stocke sur S3</li>
|
||
<li><strong>Événement</strong> : <code>track.uploaded</code> publié sur RabbitMQ</li>
|
||
<li><strong>Transcoding</strong> : Le stream server consomme l'événement, transcode via FFmpeg</li>
|
||
<li><strong>Stockage</strong> : Les segments HLS et playlists sont stockés sur S3</li>
|
||
<li><strong>Callback</strong> : <code>POST /internal/tracks/:id/stream-ready</code> vers le backend</li>
|
||
<li><strong>Lecture</strong> : Le client demande le master playlist, le serveur sert les segments</li>
|
||
</ol>
|
||
<h3>Structure des fichiers HLS sur S3</h3>
|
||
<pre><code>hls/{track_id}/
|
||
├── master.m3u8 # Master playlist (liste les qualités)
|
||
├── low/
|
||
│ ├── playlist.m3u8 # Playlist 64 kbps
|
||
│ ├── segment_000.ts # Segments audio
|
||
│ ├── segment_001.ts
|
||
│ └── ...
|
||
├── medium/
|
||
│ ├── playlist.m3u8 # Playlist 128 kbps
|
||
│ └── ...
|
||
├── high/
|
||
│ ├── playlist.m3u8 # Playlist 256 kbps
|
||
│ └── ...
|
||
└── lossless/
|
||
├── playlist.m3u8
|
||
└── ...
|
||
</code></pre>
|
||
<h2>Pile de middlewares</h2>
|
||
<p>Appliqués dans l'ordre à toutes les routes :</p>
|
||
<ol>
|
||
<li><strong>CORS</strong> — Restrictif par défaut, origines configurables</li>
|
||
<li><strong>Timeout</strong> — 30 secondes par requête</li>
|
||
<li><strong>Compression</strong> — gzip</li>
|
||
<li><strong>Security Headers</strong> — X-Content-Type-Options, X-Frame-Options, etc.</li>
|
||
<li><strong>Rate Limiting</strong> — Par IP</li>
|
||
<li><strong>Request Logging</strong> — Logs JSON structurés</li>
|
||
</ol>
|
||
<h2>Configuration</h2>
|
||
<pre><code class="language-rust">pub struct Config {
|
||
port: u16, // PORT (default: 18082)
|
||
database_url: String, // DATABASE_URL
|
||
rabbit_mq: RabbitMQConfig, // RABBITMQ_URL
|
||
s3_bucket: String, // S3_BUCKET
|
||
s3_region: String, // S3_REGION
|
||
log_level: String, // LOG_LEVEL
|
||
allowed_origins: Vec<String>, // ALLOWED_ORIGINS
|
||
}
|
||
</code></pre>
|
||
<p>Toute la configuration provient des variables d'environnement (voir [[CONFIGURATION_ENVIRONNEMENT]]).</p>
|
||
<h2>Communication inter-services</h2>
|
||
<h3>Événements RabbitMQ consommés</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Événement</th>
|
||
<th>Action</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>track.uploaded</code></td>
|
||
<td>Lance le transcoding HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track.deleted</code></td>
|
||
<td>Supprime les segments HLS de S3</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Callbacks REST vers le backend Go</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Callback</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>POST /internal/tracks/:id/stream-ready</code></td>
|
||
<td>Notifie que le transcoding est terminé</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>POST /internal/stream-events</code></td>
|
||
<td>Envoie des événements de streaming</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Header d'authentification : <code>X-Stream-Secret</code></p>
|
||
<h2>Dockerfiles</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Base</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>Dockerfile</code></td>
|
||
<td><code>rust:latest</code></td>
|
||
<td>Développement (avec debug symbols)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Dockerfile.production</code></td>
|
||
<td><code>debian:bookworm-slim</code></td>
|
||
<td>Production (binaire optimisé, minimal)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ARCHITECTURE_VEZA]] — Architecture globale</li>
|
||
<li>[[ROUTES_API]] — Référence complète des routes</li>
|
||
<li>[[CONFIGURATION_ENVIRONNEMENT]] — Variables d'environnement</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 ARCHITECTURE_VEZA.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/ARCHITECTURE_VEZA.md</div>
|
||
</div>
|
||
|
||
<h1>Architecture Technique Veza</h1>
|
||
<blockquote>
|
||
<p>Document de référence — architecture globale de la plateforme Veza.
|
||
Source : code dans <code>/home/senke/git/talas/veza/</code></p>
|
||
</blockquote>
|
||
<h2>Vue d'ensemble</h2>
|
||
<p>Veza est une plateforme musicale communautaire composée de <strong>3 services principaux</strong> communiquant via REST, WebSocket et RabbitMQ, le tout orchestré par Docker Compose.</p>
|
||
<pre><code>┌─────────────────────────────────────────────────────────────┐
|
||
│ FRONTEND │
|
||
│ React 18 · TypeScript · Tailwind │
|
||
│ Vite · Zustand · TanStack Query │
|
||
│ (apps/web/) │
|
||
└──────────┬──────────────┬───────────────┬────────────────────┘
|
||
│ REST /api/v1 │ WS /chat/ws │ WS /stream
|
||
▼ ▼ ▼
|
||
┌──────────────────┐ ┌────────────────────────────────────────┐
|
||
│ BACKEND API │ │ STREAM SERVER │
|
||
│ Go · Gin · GORM │ │ Rust · Axum │
|
||
│ (veza-backend- │ │ (veza-stream-server/) │
|
||
│ api/) │ │ │
|
||
│ │ │ • Streaming audio (HLS adaptatif) │
|
||
│ • 500+ endpoints│ │ • WebSocket temps réel │
|
||
│ • Auth JWT RS256│ │ • Transcoding FFmpeg │
|
||
│ • RBAC complet │ │ • Métriques Prometheus │
|
||
│ • CSRF Redis │ │ │
|
||
│ • Rate limiting │ └──────────────┬─────────────────────────┘
|
||
│ • Audit logging │ │
|
||
└──────┬───────────┘ │
|
||
│ │
|
||
▼ ▼
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ INFRASTRUCTURE │
|
||
│ │
|
||
│ PostgreSQL 16 (:15432) Redis 7 (:16379) │
|
||
│ Elasticsearch (:19200) RabbitMQ 3 (:15672) │
|
||
│ MinIO S3 (:19000) ClamAV 1.4 (:13310) │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
</code></pre>
|
||
<h2>Structure du monorepo</h2>
|
||
<pre><code>veza/
|
||
├── apps/web/ # Frontend React (SPA + PWA)
|
||
├── veza-backend-api/ # API REST Go (Gin + GORM)
|
||
├── veza-stream-server/ # Serveur streaming Rust (Axum)
|
||
├── veza-common/ # Code partagé Go/Rust
|
||
├── veza-docs/ # Documentation technique
|
||
├── veza-desktop/ # Wrapper Electron (charge apps/web)
|
||
├── docker-compose.yml # Infra développement
|
||
├── docker-compose.prod.yml # Infra production
|
||
├── docker-compose.dev.yml # Services dev uniquement
|
||
├── .env.example # Template de configuration
|
||
├── Makefile # Commandes build & dev
|
||
└── k8s/ # Manifests Kubernetes
|
||
</code></pre>
|
||
<h2>Ports réseau (isolation pour éviter les conflits)</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Service</th>
|
||
<th>Port</th>
|
||
<th>Protocole</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Backend API</td>
|
||
<td>18080</td>
|
||
<td>HTTP/REST</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Stream Server</td>
|
||
<td>18082</td>
|
||
<td>HTTP/WS</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Frontend (dev)</td>
|
||
<td>5173</td>
|
||
<td>HTTP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>PostgreSQL</td>
|
||
<td>15432</td>
|
||
<td>TCP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Redis</td>
|
||
<td>16379</td>
|
||
<td>TCP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>RabbitMQ AMQP</td>
|
||
<td>15672</td>
|
||
<td>AMQP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>RabbitMQ Management</td>
|
||
<td>25672</td>
|
||
<td>HTTP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ClamAV</td>
|
||
<td>13310</td>
|
||
<td>TCP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>MinIO S3</td>
|
||
<td>19000</td>
|
||
<td>HTTP</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Elasticsearch</td>
|
||
<td>19200</td>
|
||
<td>HTTP</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Stack technique détaillée</h2>
|
||
<h3>Backend API (Go)</h3>
|
||
<ul>
|
||
<li><strong>Framework</strong> : Gin</li>
|
||
<li><strong>ORM</strong> : GORM v1 (mapping uniquement, migrations en SQL pur)</li>
|
||
<li><strong>Auth</strong> : JWT RS256 (fallback HS256), OAuth 2.0, WebAuthn/Passkeys, MFA TOTP</li>
|
||
<li><strong>Sécurité</strong> : CSRF Redis, rate limiting multi-niveaux, ClamAV antivirus, audit logging</li>
|
||
<li><strong>Recherche</strong> : Elasticsearch (fallback PostgreSQL full-text)</li>
|
||
<li><strong>Stockage</strong> : MinIO S3 compatible</li>
|
||
<li><strong>Monitoring</strong> : Prometheus, Sentry</li>
|
||
<li><strong>Base</strong> : PostgreSQL 16 avec UUIDs, soft deletes</li>
|
||
</ul>
|
||
<h3>Stream Server (Rust)</h3>
|
||
<ul>
|
||
<li><strong>Framework</strong> : Axum (async)</li>
|
||
<li><strong>Audio</strong> : HLS adaptatif multi-bitrate, FFmpeg transcoding</li>
|
||
<li><strong>Temps réel</strong> : WebSocket avec protocole de synchronisation</li>
|
||
<li><strong>Résilience</strong> : Circuit breaker, rate limiting, health checks</li>
|
||
<li><strong>Messaging</strong> : RabbitMQ pour les jobs de transcoding asynchrones</li>
|
||
</ul>
|
||
<h3>Frontend (React)</h3>
|
||
<ul>
|
||
<li><strong>Build</strong> : Vite v7.1.5</li>
|
||
<li><strong>UI</strong> : Tailwind CSS v4, Radix UI</li>
|
||
<li><strong>État</strong> : Zustand (stores), TanStack Query (data fetching)</li>
|
||
<li><strong>Formulaires</strong> : React Hook Form + Zod (validation)</li>
|
||
<li><strong>Routage</strong> : React Router v6 (52+ routes)</li>
|
||
<li><strong>i18n</strong> : i18next (EN/FR/ES)</li>
|
||
<li><strong>Tests</strong> : Vitest, Storybook</li>
|
||
<li><strong>Desktop</strong> : Electron wrapper (même codebase)</li>
|
||
</ul>
|
||
<h2>Patterns architecturaux</h2>
|
||
<h3>1. Microservices avec communication asynchrone</h3>
|
||
<ul>
|
||
<li>Backend API (Go) → logique métier</li>
|
||
<li>Stream Server (Rust) → streaming audio haute performance</li>
|
||
<li>RabbitMQ → distribution d'événements entre services</li>
|
||
</ul>
|
||
<h3>2. Event-driven architecture</h3>
|
||
<p>Événements principaux via RabbitMQ :
|
||
- <code>user.created</code> → notifications, indexation
|
||
- <code>track.uploaded</code> → scan ClamAV → transcoding HLS → indexation Elasticsearch
|
||
- <code>payment.completed</code> → mise à jour commande, notification vendeur</p>
|
||
<h3>3. Sécurité en profondeur</h3>
|
||
<ul>
|
||
<li>CSRF tokens (Redis-backed, obligatoire en production)</li>
|
||
<li>JWT RS256 avec rotation de clés</li>
|
||
<li>OAuth 2.0 avec chiffrement des tokens</li>
|
||
<li>ClamAV pour scan antivirus des uploads</li>
|
||
<li>Rate limiting : global (1000 req/s), par IP (100 req/s), par endpoint</li>
|
||
<li>Verrouillage de compte après N tentatives échouées</li>
|
||
<li>Audit logging automatique sur POST/PUT/DELETE</li>
|
||
<li>Headers de sécurité (HSTS, CSP, X-Content-Type-Options)</li>
|
||
<li>CCPA/RGPD : opt-out, export de données, suppression de compte</li>
|
||
</ul>
|
||
<h3>4. Observabilité</h3>
|
||
<ul>
|
||
<li>Logs structurés (JSON en production, texte en dev)</li>
|
||
<li>Métriques Prometheus (endpoints <code>/metrics</code>)</li>
|
||
<li>Sentry pour le tracking d'erreurs</li>
|
||
<li>Health checks (liveness <code>/healthz</code>, readiness <code>/readyz</code>)</li>
|
||
</ul>
|
||
<h2>Flux de données principaux</h2>
|
||
<h3>Inscription utilisateur</h3>
|
||
<pre><code>Frontend POST /api/v1/auth/register
|
||
→ Backend : validation Zod, hash bcrypt, création User en DB
|
||
→ Email de vérification envoyé
|
||
→ JWT retourné en cookie HTTP-only
|
||
→ Frontend redirige vers /verify-email
|
||
</code></pre>
|
||
<h3>Upload de piste audio</h3>
|
||
<pre><code>Frontend POST /api/v1/tracks (multipart/form-data)
|
||
→ Backend : scan ClamAV → stockage S3 → parsing métadonnées FFmpeg
|
||
→ Création Track en DB (status: processing)
|
||
→ Publication événement track.uploaded sur RabbitMQ
|
||
|
||
Stream Server (écoute RabbitMQ)
|
||
→ Réception track.uploaded
|
||
→ Transcoding WAV → MP3 + HLS multi-bitrate
|
||
→ Upload segments sur S3
|
||
→ Publication transcoding.completed
|
||
|
||
Backend (écoute événement)
|
||
→ Mise à jour Track (status: completed, stream_manifest_url)
|
||
→ Indexation Elasticsearch
|
||
→ Notification utilisateur
|
||
</code></pre>
|
||
<h3>Lecture audio streaming</h3>
|
||
<pre><code>Frontend WS /stream?track_id=xxx&position=0
|
||
→ Stream Server : validation JWT
|
||
→ Chargement playlist HLS depuis cache/S3
|
||
→ Sélection bitrate adaptatif selon réseau
|
||
→ Envoi chunks audio via WebSocket
|
||
→ Heartbeat toutes les 30s
|
||
</code></pre>
|
||
<h2>Commandes de développement</h2>
|
||
<pre><code class="language-bash"># Stack complète (backend Docker, web local)
|
||
make dev
|
||
|
||
# Tous les services locaux avec hot reload
|
||
make dev-full
|
||
|
||
# Infrastructure seule (DB, Redis, RabbitMQ, MinIO)
|
||
docker-compose up -d
|
||
|
||
# Services individuels
|
||
make dev-web # Frontend seul
|
||
make dev-backend-api # Backend seul
|
||
make dev-stream-server # Stream server seul
|
||
|
||
# Build production
|
||
make build
|
||
|
||
# Migrations base de données
|
||
cd veza-backend-api && go run ./cmd/migrate_tool/main.go up
|
||
</code></pre>
|
||
<h2>Fichiers clés (chemins absolus)</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Rôle</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>veza-backend-api/cmd/api/main.go</code></td>
|
||
<td>Point d'entrée backend</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/internal/api/router.go</code></td>
|
||
<td>Enregistrement des routes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/internal/config/config.go</code></td>
|
||
<td>Configuration</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/internal/models/</code></td>
|
||
<td>68 modèles GORM</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/internal/middleware/</code></td>
|
||
<td>17 middlewares</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/migrations/</code></td>
|
||
<td>115 fichiers SQL</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-stream-server/src/main.rs</code></td>
|
||
<td>Point d'entrée streaming</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-stream-server/src/routes/api.rs</code></td>
|
||
<td>Routes Axum</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-stream-server/src/streaming/</code></td>
|
||
<td>WebSocket, HLS, adaptatif</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>apps/web/src/main.tsx</code></td>
|
||
<td>Point d'entrée frontend</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>apps/web/src/router/routeConfig.tsx</code></td>
|
||
<td>Définition des routes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>apps/web/src/stores/</code></td>
|
||
<td>Stores Zustand</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>apps/web/src/services/api/</code></td>
|
||
<td>Clients API</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>docker-compose.yml</code></td>
|
||
<td>Stack développement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>docker-compose.prod.yml</code></td>
|
||
<td>Stack production</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>.env.example</code></td>
|
||
<td>Template de configuration</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ROUTES_API]] — Référence complète des endpoints API</li>
|
||
<li>[[SCHEMA_BASE_DE_DONNEES]] — Schéma PostgreSQL complet (60+ tables)</li>
|
||
<li>[[SERVEUR_STREAMING_RUST]] — Architecture du serveur Rust Axum</li>
|
||
<li>[[FRONTEND_REACT]] — Architecture frontend React</li>
|
||
<li>[[CONFIGURATION_ENVIRONNEMENT]] — Variables d'environnement et Docker</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Auth_&_Core/README.md</div>
|
||
</div>
|
||
|
||
<h1>Authentification & Core System</h1>
|
||
<p>Ce dossier contient les composants de base partagés entre les applications Talas : gestion des utilisateurs, sécurité, sessions, permissions et configuration générale.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Centraliser la logique d’authentification (JWT, OAuth, SSO).</li>
|
||
<li>Fournir des services partagés pour toutes les apps (profil, sessions, ACL).</li>
|
||
<li>Préparer une architecture modulaire facilement extensible.</li>
|
||
</ul>
|
||
<h2>Contenu recommandé :</h2>
|
||
<ul>
|
||
<li><code>auth_controller.go</code> / <code>users.rs</code> (ou équivalents)</li>
|
||
<li><code>middleware/</code> : validation de token, CORS, accès protégé</li>
|
||
<li><code>schemas/</code> : modèles utilisateur, rôles, permissions</li>
|
||
<li><code>utils/</code> : génération tokens, encodage, vérification</li>
|
||
<li><code>tests/</code> : login/signup, forgot password, refresh</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Ce module doit être le plus découpé possible pour pouvoir s’adapter à la croissance future.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 CONFIGURATION_ENVIRONNEMENT.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/CONFIGURATION_ENVIRONNEMENT.md</div>
|
||
</div>
|
||
|
||
<h1>Configuration & Environnement Veza</h1>
|
||
<blockquote>
|
||
<p>Variables d'environnement, Docker Compose, et paramètres de déploiement.
|
||
Source : <code>.env.example</code>, <code>docker-compose*.yml</code>, <code>Makefile</code></p>
|
||
</blockquote>
|
||
<h2>Variables d'environnement</h2>
|
||
<p>Toutes les variables sont définies dans <code>.env.example</code> à la racine du monorepo.</p>
|
||
<h3>Core</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>APP_DOMAIN</code></td>
|
||
<td><code>veza.fr</code></td>
|
||
<td>Domaine principal</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>FRONTEND_URL</code></td>
|
||
<td><code>http://veza.fr:5173</code></td>
|
||
<td>URL frontend</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>PORT_BACKEND</code></td>
|
||
<td><code>18080</code></td>
|
||
<td>Port API backend</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>PORT_STREAM</code></td>
|
||
<td><code>18082</code></td>
|
||
<td>Port stream server</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>APP_ENV</code></td>
|
||
<td><code>development</code></td>
|
||
<td>Environnement (development/staging/production)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Base de données (PostgreSQL)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>DB_USER</code></td>
|
||
<td><code>veza</code></td>
|
||
<td>Utilisateur PostgreSQL</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_PASSWORD</code></td>
|
||
<td><code>password</code></td>
|
||
<td>Mot de passe</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DB_NAME</code></td>
|
||
<td><code>veza</code></td>
|
||
<td>Nom de la base</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DATABASE_URL</code></td>
|
||
<td><code>postgres://veza:password@localhost:15432/veza?sslmode=disable</code></td>
|
||
<td>URL complète</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Redis</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>REDIS_URL</code></td>
|
||
<td><code>redis://:password@localhost:16379</code></td>
|
||
<td>URL Redis</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>REDIS_PASSWORD</code></td>
|
||
<td><code>devpassword</code></td>
|
||
<td>Mot de passe Redis</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>RabbitMQ</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>RABBITMQ_URL</code></td>
|
||
<td><code>amqp://veza:password@localhost:15672/</code></td>
|
||
<td>URL AMQP</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RABBITMQ_DEFAULT_USER</code></td>
|
||
<td><code>veza</code></td>
|
||
<td>Utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RABBITMQ_DEFAULT_PASS</code></td>
|
||
<td><code>devpassword</code></td>
|
||
<td>Mot de passe</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>JWT & Sécurité</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>JWT_SECRET</code></td>
|
||
<td><code>min-32-characters...</code></td>
|
||
<td>Secret JWT (fallback HS256)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_PRIVATE_KEY_PATH</code></td>
|
||
<td><code>/path/to/jwt-private.pem</code></td>
|
||
<td>Clé privée RS256</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_PUBLIC_KEY_PATH</code></td>
|
||
<td><code>/path/to/jwt-public.pem</code></td>
|
||
<td>Clé publique RS256</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_ISSUER</code></td>
|
||
<td><code>veza-api</code></td>
|
||
<td>Émetteur JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>JWT_AUDIENCE</code></td>
|
||
<td><code>veza-platform</code></td>
|
||
<td>Audience JWT</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>OAUTH_ENCRYPTION_KEY</code></td>
|
||
<td><code><32-byte-hex></code></td>
|
||
<td>Chiffrement OAuth</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>OAUTH_ALLOWED_REDIRECT_DOMAINS</code></td>
|
||
<td><code>https://veza.fr:5173</code></td>
|
||
<td>Domaines OAuth autorisés</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>CHAT_JWT_SECRET</code></td>
|
||
<td><code><différent de JWT_SECRET></code></td>
|
||
<td>Secret JWT chat</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Stockage S3 (MinIO)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>S3_ENABLED</code></td>
|
||
<td><code>true</code></td>
|
||
<td>Activer S3</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>S3_BUCKET</code></td>
|
||
<td><code>veza-uploads</code></td>
|
||
<td>Nom du bucket</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>S3_REGION</code></td>
|
||
<td><code>us-east-1</code></td>
|
||
<td>Région</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>S3_ENDPOINT</code></td>
|
||
<td><code>http://localhost:19000</code></td>
|
||
<td>Endpoint MinIO</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>S3_ACCESS_KEY</code></td>
|
||
<td><code>...</code></td>
|
||
<td>Clé d'accès</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>S3_SECRET_KEY</code></td>
|
||
<td><code>...</code></td>
|
||
<td>Clé secrète</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Streaming & Live</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>STREAM_HLS_BASE_URL</code></td>
|
||
<td><code>http://localhost:18083/live</code></td>
|
||
<td>URL base HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>NGINX_RTMP_HOST</code></td>
|
||
<td><code>localhost</code></td>
|
||
<td>Hôte RTMP</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RTMP_CALLBACK_SECRET</code></td>
|
||
<td><code><shared-secret></code></td>
|
||
<td>Secret callbacks RTMP</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Elasticsearch</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>ELASTICSEARCH_URL</code></td>
|
||
<td><code>http://localhost:19200</code></td>
|
||
<td>URL Elasticsearch</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ELASTICSEARCH_AUTO_INDEX</code></td>
|
||
<td><code>true</code></td>
|
||
<td>Auto-indexation au démarrage</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Antivirus</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>ENABLE_CLAMAV</code></td>
|
||
<td><code>true</code></td>
|
||
<td>Activer le scan antivirus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>CLAMAV_REQUIRED</code></td>
|
||
<td><code>true</code></td>
|
||
<td>Échouer si ClamAV indisponible</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Paiements</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>STRIPE_CONNECT_ENABLED</code></td>
|
||
<td><code>true</code></td>
|
||
<td>Activer Stripe Connect</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>HYPERSWITCH_WEBHOOK_SECRET</code></td>
|
||
<td><code><secret></code></td>
|
||
<td>Secret webhook paiement</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Logs & Monitoring</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>LOG_LEVEL</code></td>
|
||
<td><code>INFO</code></td>
|
||
<td>Niveau de log (DEBUG active les stack traces)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>LOG_DIR</code></td>
|
||
<td><code>/var/log/veza</code></td>
|
||
<td>Répertoire des logs</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>LOG_FORMAT</code></td>
|
||
<td><code>json</code></td>
|
||
<td>Format (json en prod, text en dev)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SENTRY_DSN</code></td>
|
||
<td><code>https://...@ingest.sentry.io/0</code></td>
|
||
<td>DSN Sentry</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SENTRY_ENVIRONMENT</code></td>
|
||
<td><code>development</code></td>
|
||
<td>Environnement Sentry</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SENTRY_SAMPLE_RATE_ERRORS</code></td>
|
||
<td><code>1.0</code></td>
|
||
<td>Taux échantillonnage erreurs</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SENTRY_SAMPLE_RATE_TRANSACTIONS</code></td>
|
||
<td><code>0.1</code></td>
|
||
<td>Taux échantillonnage transactions</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>PROMETHEUS_URL</code></td>
|
||
<td><code>http://prometheus:9090</code></td>
|
||
<td>URL Prometheus</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Frontend</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Exemple</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>VITE_API_URL</code></td>
|
||
<td><code>/api/v1</code></td>
|
||
<td>URL API (relative ou absolue)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_USE_MSW</code></td>
|
||
<td><code>1</code></td>
|
||
<td>Activer mocks MSW</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_STORYBOOK</code></td>
|
||
<td><code>1</code></td>
|
||
<td>Mode Storybook</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_SENTRY_DSN</code></td>
|
||
<td><code>https://...</code></td>
|
||
<td>DSN Sentry frontend</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Docker Compose</h2>
|
||
<h3>Développement (<code>docker-compose.yml</code>)</h3>
|
||
<p>Services d'infrastructure pour le développement local :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Service</th>
|
||
<th>Image</th>
|
||
<th>Port exposé</th>
|
||
<th>Port interne</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>postgres</code></td>
|
||
<td>PostgreSQL 16</td>
|
||
<td>15432</td>
|
||
<td>5432</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>redis</code></td>
|
||
<td>Redis 7</td>
|
||
<td>16379</td>
|
||
<td>6379</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>rabbitmq</code></td>
|
||
<td>RabbitMQ 3</td>
|
||
<td>15672 (AMQP), 25672 (management)</td>
|
||
<td>5672, 15672</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>clamav</code></td>
|
||
<td>ClamAV 1.4</td>
|
||
<td>13310</td>
|
||
<td>3310</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>minio</code></td>
|
||
<td>MinIO</td>
|
||
<td>19000</td>
|
||
<td>9000</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>elasticsearch</code></td>
|
||
<td>Elasticsearch</td>
|
||
<td>19200</td>
|
||
<td>9200</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<pre><code class="language-bash"># Lancer l'infrastructure
|
||
docker-compose up -d
|
||
|
||
# Ou via Makefile
|
||
make infra
|
||
</code></pre>
|
||
<h3>Production (<code>docker-compose.prod.yml</code>)</h3>
|
||
<p>Mêmes services avec :
|
||
- <strong>Volumes persistants</strong> pour les données
|
||
- <strong>Limites de ressources</strong> (CPU, mémoire)
|
||
- <strong>Health checks</strong> sur tous les services
|
||
- <strong>Configuration logging</strong> centralisée
|
||
- <strong>Isolation réseau</strong> entre services
|
||
- <strong>Restart policy</strong> : <code>unless-stopped</code></p>
|
||
<hr />
|
||
<h2>Dockerfiles des services applicatifs</h2>
|
||
<h3>Backend API (Go)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Base</th>
|
||
<th>Taille</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>veza-backend-api/Dockerfile</code></td>
|
||
<td><code>golang:1.21-alpine</code></td>
|
||
<td>~300 Mo</td>
|
||
<td>Développement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-backend-api/Dockerfile.production</code></td>
|
||
<td><code>scratch</code></td>
|
||
<td>~15 Mo</td>
|
||
<td>Production (binaire statique)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Stream Server (Rust)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Base</th>
|
||
<th>Taille</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>veza-stream-server/Dockerfile</code></td>
|
||
<td><code>rust:latest</code></td>
|
||
<td>~1 Go</td>
|
||
<td>Développement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>veza-stream-server/Dockerfile.production</code></td>
|
||
<td><code>debian:bookworm-slim</code></td>
|
||
<td>~100 Mo</td>
|
||
<td>Production</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Frontend (React)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Base</th>
|
||
<th>Taille</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>apps/web/Dockerfile</code></td>
|
||
<td><code>node:20-alpine</code> → <code>nginx:alpine</code></td>
|
||
<td>~50 Mo</td>
|
||
<td>Développement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>apps/web/Dockerfile.production</code></td>
|
||
<td><code>nginx:latest</code></td>
|
||
<td>~30 Mo</td>
|
||
<td>Production</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Commandes Makefile</h2>
|
||
<pre><code class="language-bash"># Développement
|
||
make dev # Stack complète (backend Docker, web local)
|
||
make dev-full # Tous les services locaux + hot reload
|
||
make dev-web # Frontend seul
|
||
make dev-backend-api # Backend seul
|
||
make dev-stream-server # Stream server seul
|
||
|
||
# Infrastructure
|
||
make infra # docker-compose up -d
|
||
|
||
# Build
|
||
make build # Build tous les conteneurs
|
||
|
||
# Base de données
|
||
make migrate-up # Appliquer les migrations
|
||
make migrate-down # Rollback dernière migration
|
||
|
||
# Tests
|
||
make test # Tous les tests
|
||
make test-backend # Tests backend Go
|
||
make test-frontend # Tests frontend Vitest
|
||
make test-e2e # Tests end-to-end
|
||
</code></pre>
|
||
<hr />
|
||
<h2>Nginx (reverse proxy frontend)</h2>
|
||
<p>Fichier : <code>apps/web/nginx.conf</code></p>
|
||
<p>Configuration du reverse proxy en production :</p>
|
||
<pre><code>Client → Nginx (port 80/443)
|
||
├── / → fichiers statiques (SPA)
|
||
├── /api/* → Backend Go (port 8080)
|
||
├── /ws/* → Chat WebSocket (port 8081)
|
||
└── /stream/* → Stream Server Rust (port 8082)
|
||
</code></pre>
|
||
<p>Fonctionnalités :
|
||
- <strong>SPA fallback</strong> : Toutes les routes non-API renvoient <code>index.html</code>
|
||
- <strong>Gzip</strong> : Compression activée
|
||
- <strong>Cache</strong> : Headers pour assets statiques (JS, CSS, images)
|
||
- <strong>Sécurité</strong> : X-Frame-Options, X-Content-Type-Options</p>
|
||
<hr />
|
||
<h2>Différences dev / staging / production</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Aspect</th>
|
||
<th>Développement</th>
|
||
<th>Staging</th>
|
||
<th>Production</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>APP_ENV</code></td>
|
||
<td>development</td>
|
||
<td>staging</td>
|
||
<td>production</td>
|
||
</tr>
|
||
<tr>
|
||
<td>CORS</td>
|
||
<td>Wildcard <code>*</code></td>
|
||
<td>Domaines staging</td>
|
||
<td>Domaines stricts</td>
|
||
</tr>
|
||
<tr>
|
||
<td>CSRF</td>
|
||
<td>Optionnel (si Redis)</td>
|
||
<td>Obligatoire</td>
|
||
<td>Obligatoire</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Swagger/docs</td>
|
||
<td>Activé</td>
|
||
<td>Activé</td>
|
||
<td><strong>Désactivé</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td>pprof debug</td>
|
||
<td>Activé</td>
|
||
<td>Désactivé</td>
|
||
<td><strong>Désactivé</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Logs</td>
|
||
<td>Texte, DEBUG</td>
|
||
<td>JSON, INFO</td>
|
||
<td>JSON, WARN+</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Stack traces</td>
|
||
<td>Dans les réponses</td>
|
||
<td>Pas dans les réponses</td>
|
||
<td>Pas dans les réponses</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Sentry</td>
|
||
<td>Optionnel</td>
|
||
<td>Activé</td>
|
||
<td>Activé</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ClamAV</td>
|
||
<td>Optionnel</td>
|
||
<td>Recommandé</td>
|
||
<td><strong>Obligatoire</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Redis</td>
|
||
<td>Optionnel</td>
|
||
<td>Obligatoire</td>
|
||
<td><strong>Obligatoire</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Rate limiting</td>
|
||
<td>Souple</td>
|
||
<td>Modéré</td>
|
||
<td>Strict (DDoS)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ARCHITECTURE_VEZA]] — Architecture globale</li>
|
||
<li>[[ROUTES_API]] — Endpoints API</li>
|
||
<li>[[SCHEMA_BASE_DE_DONNEES]] — Schéma PostgreSQL</li>
|
||
<li>[[SERVEUR_STREAMING_RUST]] — Serveur streaming</li>
|
||
<li>[[FRONTEND_REACT]] — Architecture frontend</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Community/Groupes_Chat/README.md</div>
|
||
</div>
|
||
|
||
<h1>Groupes & Chat</h1>
|
||
<p>Module de <strong>messagerie communautaire</strong> pour groupes d’utilisateurs : collaboration, entraide, salon projet.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Créer des espaces privés/publics de discussion.</li>
|
||
<li>Gérer les rôles, notifications, permissions.</li>
|
||
<li>Permettre l’upload de fichiers légers (images, samples).</li>
|
||
</ul>
|
||
<h2>Contenu recommandé :</h2>
|
||
<ul>
|
||
<li>WebSocket ou SSE backend</li>
|
||
<li><code>rooms/</code>, <code>messages/</code>, <code>users/</code></li>
|
||
<li><code>permissions/</code> : modérateurs, membres</li>
|
||
<li>Web UI intégrable (chat component)</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Inspiré de Discord/Mattermost, mais minimaliste.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Community/README.md</div>
|
||
</div>
|
||
|
||
<h1>Talas Community – App Communautaire</h1>
|
||
<p>Ce dossier regroupe les composants de l’application communautaire de Talas : partage, groupes, chat, échanges entre artistes.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Offrir une plateforme fluide pour les petits créateurs.</li>
|
||
<li>Favoriser les échanges, l’entraide, la collaboration et la visibilité.</li>
|
||
<li>Permettre des extensions type forum, salon, recherche collaborateur.</li>
|
||
</ul>
|
||
<h2>Sous-sections :</h2>
|
||
<ul>
|
||
<li><code>Groupes_Chat/</code> : groupes privés/publics, messagerie</li>
|
||
<li><code>Partage/</code> : fichiers audio, presets, projets</li>
|
||
<li><code>Troc/</code> : plateforme de don, échange matériel ou services</li>
|
||
<li><code>Formation/</code> : espace de diffusion tutoriels, guides, lives</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Peut évoluer vers un écosystème type SoundCloud + Discord + Coursera artisanal.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 FRONTEND_REACT.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/FRONTEND_REACT.md</div>
|
||
</div>
|
||
|
||
<h1>Architecture Frontend Veza (React)</h1>
|
||
<blockquote>
|
||
<p>Application web SPA + PWA avec support desktop Electron.
|
||
Source : <code>apps/web/src/</code></p>
|
||
</blockquote>
|
||
<h2>Stack technique</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Composant</th>
|
||
<th>Technologie</th>
|
||
<th>Version</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Framework UI</td>
|
||
<td>React</td>
|
||
<td>18</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Langage</td>
|
||
<td>TypeScript</td>
|
||
<td>strict</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Build</td>
|
||
<td>Vite</td>
|
||
<td>7.1.5</td>
|
||
</tr>
|
||
<tr>
|
||
<td>CSS</td>
|
||
<td>Tailwind CSS</td>
|
||
<td>v4</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Composants</td>
|
||
<td>Radix UI + custom</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>État global</td>
|
||
<td>Zustand</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Data fetching</td>
|
||
<td>TanStack Query (React Query)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Formulaires</td>
|
||
<td>React Hook Form + Zod</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Routage</td>
|
||
<td>React Router</td>
|
||
<td>v6</td>
|
||
</tr>
|
||
<tr>
|
||
<td>i18n</td>
|
||
<td>i18next</td>
|
||
<td>EN/FR/ES</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tests unitaires</td>
|
||
<td>Vitest</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tests composants</td>
|
||
<td>Storybook</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Desktop</td>
|
||
<td>Electron (wrapper)</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Structure du projet</h2>
|
||
<pre><code>apps/web/src/
|
||
├── app/ # Composant App + initialisation
|
||
├── components/ # Composants UI (36 sous-dossiers)
|
||
│ ├── admin/ # Panel admin
|
||
│ ├── auth/ # Guards + flows auth
|
||
│ ├── commerce/ # Marketplace, checkout
|
||
│ ├── dashboard/ # Widgets dashboard
|
||
│ ├── feedback/ # Toasts, notifications
|
||
│ ├── layout/ # Sidebar, Header, MainLayout
|
||
│ ├── marketplace/ # Affichage produits, panier
|
||
│ ├── modals/ # Dialogues modaux
|
||
│ ├── player/ # Lecteur audio
|
||
│ ├── search/ # Recherche, filtres
|
||
│ ├── social/ # Likes, follows
|
||
│ ├── upload/ # Upload de fichiers
|
||
│ └── ui/ # Composants de base (19 sous-dossiers)
|
||
├── features/ # Modules fonctionnels (38 sous-dossiers)
|
||
│ ├── admin/ # Fonctionnalité admin
|
||
│ ├── analytics/ # Stats, graphiques
|
||
│ ├── auth/ # Flows d'authentification
|
||
│ ├── chat/ # Chat temps réel
|
||
│ ├── commerce/ # Logique marketplace
|
||
│ ├── developer/ # Outils développeur
|
||
│ ├── library/ # Bibliothèque musicale
|
||
│ ├── live/ # Streaming live
|
||
│ ├── marketplace/ # Marketplace
|
||
│ ├── notifications/ # Notifications
|
||
│ ├── playlists/ # Gestion playlists
|
||
│ ├── player/ # Logique lecteur audio
|
||
│ ├── profile/ # Profil utilisateur
|
||
│ ├── settings/ # Paramètres
|
||
│ ├── social/ # Social
|
||
│ ├── streaming/ # Streaming audio
|
||
│ └── tracks/ # Gestion pistes
|
||
├── hooks/ # Hooks React custom (46 fichiers)
|
||
├── router/ # Configuration routage
|
||
│ ├── routeConfig.tsx # Définition des routes
|
||
│ ├── AppRouter.tsx # Wrapper routeur
|
||
│ ├── ProtectedRoute.tsx # Guard authentification
|
||
│ └── PublicRoute.tsx # Wrapper pages publiques
|
||
├── services/ # Clients API & logique métier
|
||
│ ├── api/ # Couche API REST
|
||
│ ├── websocket/ # Handlers WebSocket
|
||
│ └── storage/ # Storage local/session
|
||
├── stores/ # Stores Zustand
|
||
├── types/ # Types TypeScript (9 fichiers)
|
||
├── utils/ # Utilitaires (52 fichiers)
|
||
├── schemas/ # Schémas Zod (validation)
|
||
├── config/ # Configuration (env, URLs API)
|
||
├── context/ # Providers React Context
|
||
├── lib/ # Intégrations tierces
|
||
│ ├── i18n.ts # Configuration i18next
|
||
│ └── sentry.ts # Sentry error tracking
|
||
├── locales/ # Traductions i18n
|
||
├── styles/ # Styles globaux
|
||
└── __tests__/ # Tests
|
||
</code></pre>
|
||
<h2>Routes de l'application</h2>
|
||
<h3>Routes publiques (sans authentification)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Route</th>
|
||
<th>Page</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>/login</code></td>
|
||
<td>Login</td>
|
||
<td>Page de connexion</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/register</code></td>
|
||
<td>Register</td>
|
||
<td>Inscription</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/forgot-password</code></td>
|
||
<td>ForgotPassword</td>
|
||
<td>Récupération mot de passe</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/verify-email</code></td>
|
||
<td>VerifyEmail</td>
|
||
<td>Vérification email</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/reset-password</code></td>
|
||
<td>ResetPassword</td>
|
||
<td>Reset avec token</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/</code></td>
|
||
<td>Landing</td>
|
||
<td>Page d'accueil</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/discover</code></td>
|
||
<td>Discover</td>
|
||
<td>Découverte publique</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/p/:playlistToken</code></td>
|
||
<td>SharedPlaylist</td>
|
||
<td>Playlist partagée</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3>Routes protégées (authentification requise)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Route</th>
|
||
<th>Page</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>/dashboard</code></td>
|
||
<td>Dashboard</td>
|
||
<td>Feed principal</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/library</code></td>
|
||
<td>Library</td>
|
||
<td>Bibliothèque musicale</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/settings/*</code></td>
|
||
<td>Settings</td>
|
||
<td>Paramètres utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/u/:username</code></td>
|
||
<td>Profile</td>
|
||
<td>Profil utilisateur</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/playlist/:id</code></td>
|
||
<td>PlaylistDetail</td>
|
||
<td>Détail playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/track/:id</code></td>
|
||
<td>TrackDetail</td>
|
||
<td>Détail piste</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/marketplace/*</code></td>
|
||
<td>Marketplace</td>
|
||
<td>Pages marketplace</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/cart</code></td>
|
||
<td>Cart</td>
|
||
<td>Panier</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/checkout</code></td>
|
||
<td>Checkout</td>
|
||
<td>Paiement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/chat</code></td>
|
||
<td>Chat</td>
|
||
<td>Interface de chat</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/notifications</code></td>
|
||
<td>Notifications</td>
|
||
<td>Notifications</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/analytics</code></td>
|
||
<td>Analytics</td>
|
||
<td>Dashboard analytics</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/webhooks</code></td>
|
||
<td>Webhooks</td>
|
||
<td>Gestion webhooks</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/admin/*</code></td>
|
||
<td>Admin</td>
|
||
<td>Panel admin</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/search</code></td>
|
||
<td>Search</td>
|
||
<td>Résultats recherche</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/social/*</code></td>
|
||
<td>Social</td>
|
||
<td>Fonctionnalités sociales</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/live/*</code></td>
|
||
<td>Live</td>
|
||
<td>Streaming live</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/seller/*</code></td>
|
||
<td>Seller</td>
|
||
<td>Dashboard vendeur</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/developer/*</code></td>
|
||
<td>Developer</td>
|
||
<td>Outils développeur</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/queue</code></td>
|
||
<td>Queue</td>
|
||
<td>File d'attente</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/listen-together</code></td>
|
||
<td>CoListening</td>
|
||
<td>Co-écoute</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/wishlist</code></td>
|
||
<td>Wishlist</td>
|
||
<td>Liste de souhaits</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>/purchases</code></td>
|
||
<td>Purchases</td>
|
||
<td>Historique achats</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Gestion d'état (Zustand)</h2>
|
||
<h3>Stores principaux</h3>
|
||
<pre><code class="language-typescript">// UI State (stores/ui.ts)
|
||
{
|
||
sidebarOpen: boolean,
|
||
darkMode: boolean,
|
||
activeModal: string | null,
|
||
}
|
||
|
||
// Library State (stores/library.ts)
|
||
{
|
||
favorites: Track[],
|
||
recentlyPlayed: Track[],
|
||
playlists: Playlist[],
|
||
}
|
||
|
||
// Cart State (stores/cartStore.ts)
|
||
{
|
||
items: CartItem[],
|
||
total: number,
|
||
}
|
||
|
||
// Rate Limit State (stores/rateLimit.ts)
|
||
{
|
||
remaining: number,
|
||
resetTime: Date,
|
||
}
|
||
</code></pre>
|
||
<h2>Services API (<code>services/api/</code>)</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Domaine</th>
|
||
<th>Exemples d'opérations</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>auth.ts</code></td>
|
||
<td>Authentification</td>
|
||
<td>login, register, refresh, logout</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tracks.ts</code></td>
|
||
<td>Pistes</td>
|
||
<td>CRUD, upload, search, like</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlists.ts</code></td>
|
||
<td>Playlists</td>
|
||
<td>CRUD, collaborators, share</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>users.ts</code></td>
|
||
<td>Utilisateurs</td>
|
||
<td>profil, follow, block, settings</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>marketplace.ts</code></td>
|
||
<td>Marketplace</td>
|
||
<td>products, orders, reviews</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>search.ts</code></td>
|
||
<td>Recherche</td>
|
||
<td>unified search, suggestions</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>streaming.ts</code></td>
|
||
<td>Streaming</td>
|
||
<td>intégration stream server</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>chat.ts</code></td>
|
||
<td>Chat</td>
|
||
<td>rooms, messages, reactions</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>notifications.ts</code></td>
|
||
<td>Notifications</td>
|
||
<td>list, preferences, push</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>analytics.ts</code></td>
|
||
<td>Analytics</td>
|
||
<td>stats, charts, export</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Hooks personnalisés (<code>hooks/</code>)</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Hook</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>useUser()</code></td>
|
||
<td>Données utilisateur courant</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useAuth()</code></td>
|
||
<td>État d'authentification</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useTracks()</code></td>
|
||
<td>Opérations sur les pistes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>usePlaylists()</code></td>
|
||
<td>Opérations sur les playlists</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>usePlayer()</code></td>
|
||
<td>État du lecteur audio</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useSearch()</code></td>
|
||
<td>Fonctionnalité recherche</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useChat()</code></td>
|
||
<td>Opérations chat</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useNotifications()</code></td>
|
||
<td>État notifications</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useLocalStorage()</code></td>
|
||
<td>Persistance locale</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>useQueryClient()</code></td>
|
||
<td>Intégration TanStack Query</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>46 hooks au total pour encapsuler la logique métier.</p>
|
||
<h2>Configuration</h2>
|
||
<pre><code class="language-typescript">// config/env.ts
|
||
export const env = {
|
||
API_URL: import.meta.env.VITE_API_URL || '/api/v1',
|
||
FRONTEND_URL: 'http://localhost:5173',
|
||
USE_MSW: import.meta.env.VITE_USE_MSW === 'true',
|
||
STORYBOOK: import.meta.env.VITE_STORYBOOK === 'true',
|
||
SENTRY_DSN: import.meta.env.VITE_SENTRY_DSN,
|
||
}
|
||
</code></pre>
|
||
<h3>Variables d'environnement frontend</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Variable</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>VITE_API_URL</code></td>
|
||
<td>URL de l'API backend</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_USE_MSW</code></td>
|
||
<td>Activer les mocks MSW</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_STORYBOOK</code></td>
|
||
<td>Mode Storybook</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>VITE_SENTRY_DSN</code></td>
|
||
<td>DSN Sentry pour error tracking</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Internationalisation (i18n)</h2>
|
||
<ul>
|
||
<li><strong>Bibliothèque</strong> : i18next</li>
|
||
<li><strong>Langues</strong> : Anglais (EN), Français (FR), Espagnol (ES)</li>
|
||
<li><strong>Fichiers</strong> : <code>src/locales/</code></li>
|
||
<li><strong>Détection</strong> : Langue du navigateur automatique</li>
|
||
<li><strong>Persistance</strong> : localStorage</li>
|
||
</ul>
|
||
<h2>Scripts de développement</h2>
|
||
<pre><code class="language-bash"># Développement avec hot reload
|
||
npm run dev # ou : make dev-web
|
||
|
||
# Développement avec API mockée (MSW)
|
||
npm run dev:mocks
|
||
|
||
# Build production
|
||
npm run build
|
||
|
||
# Tests
|
||
npm run test # Vitest
|
||
npm run test:e2e # E2E (au root du repo)
|
||
|
||
# Qualité
|
||
npm run lint # ESLint
|
||
npm run typecheck # TypeScript strict
|
||
|
||
# Storybook (catalogue composants)
|
||
npm run storybook # Port 6006
|
||
npm run build-storybook
|
||
</code></pre>
|
||
<h2>Nginx (production)</h2>
|
||
<p>En production, le frontend est servi par Nginx avec :
|
||
- <strong>SPA routing</strong> : Toutes les routes renvoient vers <code>index.html</code>
|
||
- <strong>Proxy <code>/api</code></strong> → Backend Go (port 8080)
|
||
- <strong>Proxy <code>/ws</code></strong> → Chat WebSocket (port 8081)
|
||
- <strong>Proxy <code>/stream</code></strong> → Stream server (port 8082)
|
||
- <strong>Compression gzip</strong> activée
|
||
- <strong>Cache headers</strong> pour les assets statiques
|
||
- <strong>Security headers</strong> : X-Frame-Options, X-Content-Type-Options</p>
|
||
<p>Configuration : <code>apps/web/nginx.conf</code></p>
|
||
<h2>Dockerfiles</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Fichier</th>
|
||
<th>Base</th>
|
||
<th>Usage</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>Dockerfile</code></td>
|
||
<td><code>node:20-alpine</code> → <code>nginx:alpine</code></td>
|
||
<td>Développement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Dockerfile.production</code></td>
|
||
<td><code>nginx:latest</code></td>
|
||
<td>Production</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Desktop (Electron)</h2>
|
||
<p>Le dossier <code>veza-desktop/</code> contient un wrapper Electron minimal qui charge <code>apps/web</code>. Pas d'application native séparée — le même code frontend est utilisé partout.</p>
|
||
<h2>Statistiques</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Métrique</th>
|
||
<th>Valeur</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Composants UI</td>
|
||
<td>661</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Routes</td>
|
||
<td>52+</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Hooks custom</td>
|
||
<td>46</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Utilitaires</td>
|
||
<td>52</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Sous-dossiers features</td>
|
||
<td>38</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Langues i18n</td>
|
||
<td>3 (EN/FR/ES)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ARCHITECTURE_VEZA]] — Architecture globale</li>
|
||
<li>[[ROUTES_API]] — Endpoints API backend</li>
|
||
<li>[[CONFIGURATION_ENVIRONNEMENT]] — Variables d'environnement</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Personal/README.md</div>
|
||
</div>
|
||
|
||
<h1>Talas Personal – Application Utilisateur</h1>
|
||
<p>Ce dossier contient l’application personnelle Talas : gestion des produits achetés, plugins hébergés, fichiers audio, presets favoris.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Fournir à chaque artiste un “atelier personnel” connecté à Talas.</li>
|
||
<li>Centraliser docs, garanties, ressources, historique d’usage.</li>
|
||
<li>Intégrer des outils avancés (AudioGridder, presets, favoris cloud).</li>
|
||
</ul>
|
||
<h2>Sous-dossiers :</h2>
|
||
<ul>
|
||
<li><code>AudioGridder_Client/</code> : serveur distant de plugins</li>
|
||
<li><code>Cloud_Perso/</code> : fichiers audio, presets, snapshots</li>
|
||
<li><code>Produits_Personnels/</code> : garanties, docs, historique</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Tu peux l'étendre vers un "OS musical personnel" avec interopérabilité.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/README.md</div>
|
||
</div>
|
||
|
||
<h1>03_APPS_&_SERVICES – Développement Applicatif</h1>
|
||
<p>Contient toutes les spécifications techniques de la plateforme <strong>Veza</strong> : architecture, API, schéma de données, streaming, frontend et configuration.</p>
|
||
<p>Le code source vit dans <code>/home/senke/git/talas/veza/</code> — ce dossier ne contient que la <strong>documentation technique</strong>.</p>
|
||
<h2>Documents de référence</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Document</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>[[ARCHITECTURE_VEZA]]</td>
|
||
<td>Architecture globale (3 services, stack, flux de données)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>[[ROUTES_API]]</td>
|
||
<td>Référence des 500+ endpoints REST et WebSocket</td>
|
||
</tr>
|
||
<tr>
|
||
<td>[[SCHEMA_BASE_DE_DONNEES]]</td>
|
||
<td>60+ tables PostgreSQL, relations, Redis</td>
|
||
</tr>
|
||
<tr>
|
||
<td>[[SERVEUR_STREAMING_RUST]]</td>
|
||
<td>Serveur Axum : HLS adaptatif, WebSocket, transcoding</td>
|
||
</tr>
|
||
<tr>
|
||
<td>[[FRONTEND_REACT]]</td>
|
||
<td>React 18, 661 composants, 52+ routes, Zustand</td>
|
||
</tr>
|
||
<tr>
|
||
<td>[[CONFIGURATION_ENVIRONNEMENT]]</td>
|
||
<td>Docker, variables d’env, différences dev/staging/prod</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2>Modules fonctionnels</h2>
|
||
<ul>
|
||
<li><code>Auth_&_Core/</code> : inscription, login, sessions JWT RS256, RBAC, MFA, WebAuthn/Passkeys</li>
|
||
<li><code>Shop/</code> : marketplace, panier, paiements Stripe Connect, KYC, royalties</li>
|
||
<li><code>Community/</code> : social (feed, groupes, likes), chat temps réel, co-écoute</li>
|
||
<li><code>Personal/</code> : cloud personnel, inventaire équipement, file d’attente</li>
|
||
<li><code>APIs_&_Rust_Modules/</code> : routes API détaillées, serveur streaming Rust</li>
|
||
</ul>
|
||
<h2>Stack résumée</h2>
|
||
<ul>
|
||
<li><strong>Backend</strong> : Go (Gin, GORM) — 500+ endpoints, 68 modèles, 115 migrations SQL</li>
|
||
<li><strong>Streaming</strong> : Rust (Axum) — HLS adaptatif, WebSocket, transcoding FFmpeg</li>
|
||
<li><strong>Frontend</strong> : React 18, TypeScript, Tailwind v4, Zustand, TanStack Query</li>
|
||
<li><strong>Infra</strong> : PostgreSQL 16, Redis 7, RabbitMQ 3, Elasticsearch, MinIO S3, ClamAV</li>
|
||
</ul>
|
||
<h2>Connexions transversales</h2>
|
||
<ul>
|
||
<li>[[04_INFRA_DEPLOIEMENT]] (CI/CD, conteneurisation, serveurs)</li>
|
||
<li>[[05_EXPERIENCE_UTILISATEUR]] (interface + feedback UX)</li>
|
||
<li>[[06_COMMUNAUTE_ECOSYSTEME]] (fonctions communautaires)</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 SCHEMA_BASE_DE_DONNEES.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/SCHEMA_BASE_DE_DONNEES.md</div>
|
||
</div>
|
||
|
||
<h1>Schéma Base de Données Veza</h1>
|
||
<blockquote>
|
||
<p>Référence complète du schéma PostgreSQL — 60+ tables, UUIDs, soft deletes.
|
||
Source : <code>veza-backend-api/internal/models/</code> (68 fichiers Go) et <code>migrations/</code> (115 fichiers SQL)
|
||
ORM : GORM v1 (mapping uniquement, migrations 100% SQL)</p>
|
||
</blockquote>
|
||
<h2>Stratégie de migration</h2>
|
||
<ul>
|
||
<li><strong>Migrations SQL pures</strong> dans <code>veza-backend-api/migrations/</code> (001 à 115+)</li>
|
||
<li><strong>GORM</strong> utilisé uniquement pour le mapping Go ↔ PostgreSQL, pas pour la création de schéma</li>
|
||
<li><strong>AutoMigrate()</strong> est vide — tout est géré par SQL</li>
|
||
<li><strong>Outil</strong> : <code>go run ./cmd/migrate_tool/main.go up</code> (ou <code>down</code> pour rollback)</li>
|
||
<li>Table <code>schema_migrations</code> pour le suivi des migrations appliquées</li>
|
||
</ul>
|
||
<h2>Conventions</h2>
|
||
<ul>
|
||
<li><strong>Clés primaires</strong> : UUID v4 (<code>uuid.UUID</code> avec <code>google/uuid</code>)</li>
|
||
<li><strong>Soft delete</strong> : Colonne <code>deleted_at</code> indexée sur 20+ tables</li>
|
||
<li><strong>Timestamps</strong> : <code>created_at</code>, <code>updated_at</code> sur toutes les tables</li>
|
||
<li><strong>JSONB</strong> : Utilisé pour les données flexibles (social_links, specs, metadata)</li>
|
||
<li><strong>Enums</strong> : Types PostgreSQL custom (user_role, track_status, etc.)</li>
|
||
<li><strong>Foreign keys</strong> : Contraintes PostgreSQL natives, toujours actives</li>
|
||
</ul>
|
||
<hr />
|
||
<h2>A. Utilisateurs & Authentification</h2>
|
||
<h3><code>users</code></h3>
|
||
<p>Table centrale — profil utilisateur.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>username</code></td>
|
||
<td>VARCHAR(30)</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>NOT NULL, UNIQUE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>password_hash</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>NOT NULL</td>
|
||
<td>Masqué en JSON</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>token_version</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td>Pour révocation de tokens</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>first_name</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_name</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>avatar</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>URL avatar</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>banner_url</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>URL bannière</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bio</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>location</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>birthdate</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>gender</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>role</code></td>
|
||
<td>user_role ENUM</td>
|
||
<td>DEFAULT 'user'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_verified</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_banned</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_admin</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_public</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_login_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>login_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>password_changed_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>social_links</code></td>
|
||
<td>JSONB</td>
|
||
<td>DEFAULT '{}'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>INDEX</td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>roles</code> (M2M via <code>user_roles</code>), <code>track_likes</code> (has many, CASCADE)</p>
|
||
<h3><code>sessions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>token_hash</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>UNIQUE INDEX</td>
|
||
<td>Token hashé</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ip_address</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_agent</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>revoked_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>refresh_tokens</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), NOT NULL, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>token_hash</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>NOT NULL, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>roles</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>UNIQUE, NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>display_name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_system</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
<td>Rôle système (non supprimable)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>users</code> (M2M), <code>permissions</code> (M2M)</p>
|
||
<h3><code>permissions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td>UNIQUE, NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>resource</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>action</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_roles</code> (table pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), UNIQUE(user_id, role_id)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>role_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → roles (CASCADE)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>role</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td></td>
|
||
<td>Nom du rôle (dénormalisé)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>assigned_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>DEFAULT CURRENT_TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>assigned_by</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>role_permissions</code> (table pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>role_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → roles (CASCADE), UNIQUE(role_id, permission_id)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>permission_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → permissions (CASCADE)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>mfa_configs</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NOT NULL, UNIQUE INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>secret</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>NOT NULL</td>
|
||
<td>Masqué en JSON</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>backup_codes</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>JSON array</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_enabled</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_used_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>recovery_codes</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>code</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>Masqué</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_used</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>used_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>webauthn_credentials</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>credential_id</code></td>
|
||
<td>BYTEA</td>
|
||
<td>UNIQUE, NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>public_key</code></td>
|
||
<td>BYTEA</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>attestation_type</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>DEFAULT 'none'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>aaguid</code></td>
|
||
<td>BYTEA</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>sign_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td>DEFAULT 'My Passkey'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_used_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>federated_identities</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>provider</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td>google, github, facebook, twitter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>provider_id</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>display_name</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>avatar_url</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>access_token</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>Masqué</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>refresh_token</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>Masqué</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>api_keys</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>prefix</code></td>
|
||
<td>VARCHAR(16)</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>hashed_key</code></td>
|
||
<td>VARCHAR(128)</td>
|
||
<td>Masqué</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>scopes</code></td>
|
||
<td>TEXT[]</td>
|
||
<td>PostgreSQL array</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_used_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_settings</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_notifications</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>push_notifications</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>browser_notifications</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_on_follow</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_on_like</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_on_comment</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_on_message</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_on_mention</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>email_marketing</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>allow_search_indexing</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>show_activity</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>explicit_content</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>autoplay</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_profiles</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>language</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'en'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>timezone</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'UTC'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>theme</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'auto'</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_presence</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'offline'</td>
|
||
<td>online/away/busy/offline</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>last_seen_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status_message</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
<td>Piste en écoute</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_title</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>invisible</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>B. Pistes audio</h2>
|
||
<h3><code>tracks</code></h3>
|
||
<p>Table principale des pistes audio.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>title</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>artist</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>album</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>duration</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td>Secondes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>genre</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tags</code></td>
|
||
<td>TEXT[]</td>
|
||
<td></td>
|
||
<td>PostgreSQL array</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>year</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bpm</code></td>
|
||
<td>INT</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>musical_key</code></td>
|
||
<td>VARCHAR(10)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_path</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_size</code></td>
|
||
<td>BIGINT</td>
|
||
<td></td>
|
||
<td>Octets</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>format</code></td>
|
||
<td>VARCHAR(10)</td>
|
||
<td></td>
|
||
<td>wav, mp3, flac...</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bitrate</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td>kbps</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>sample_rate</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td>Hz</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>waveform_path</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>waveform_url</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>cover_art_path</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_public</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>track_status ENUM</td>
|
||
<td></td>
|
||
<td>uploading/processing/completed/failed</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status_message</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>stream_status</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'pending'</td>
|
||
<td>pending/processing/ready/error</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>stream_manifest_url</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td>URL playlist HLS</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>play_count</code></td>
|
||
<td>BIGINT</td>
|
||
<td></td>
|
||
<td>Non exposé en API</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>like_count</code></td>
|
||
<td>BIGINT</td>
|
||
<td></td>
|
||
<td>Non exposé en API</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>updated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>INDEX</td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>user</code> (belongs to), <code>playlists</code> (M2M), <code>likes</code> (has many), <code>shares</code> (has many), <code>versions</code> (has many), <code>hls_streams</code> (has many)</p>
|
||
<h3><code>track_versions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), UNIQUE(track_id, version_number)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>version_number</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_path</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_size</code></td>
|
||
<td>BIGINT</td>
|
||
<td>Octets</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>changelog</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_likes</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), UNIQUE(user_id, track_id)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_plays</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (SET NULL), NULLABLE, INDEX</td>
|
||
<td>Anonyme si non connecté</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>duration</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td>Secondes jouées</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>played_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>device</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ip_address</code></td>
|
||
<td>VARCHAR(45)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_shares</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>share_token</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>permissions</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>DEFAULT 'read' (read/download)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>access_count</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_comments</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>parent_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → track_comments (CASCADE), NULLABLE</td>
|
||
<td>Réponses</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content</code></td>
|
||
<td>TEXT</td>
|
||
<td>NOT NULL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>timestamp</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
<td>Position en secondes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_edited</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>parent</code> (self-ref), <code>replies</code> (has many self-ref)</p>
|
||
<h3><code>track_reposts</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_stems</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_path</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>format</code></td>
|
||
<td>VARCHAR(10)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>size_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_lyrics</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content</code></td>
|
||
<td>TEXT</td>
|
||
<td>NOT NULL</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_history</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (SET NULL)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>action</code></td>
|
||
<td>ENUM</td>
|
||
<td>INDEX</td>
|
||
<td>created/updated/deleted/published/unpublished/restored</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>old_value</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>new_value</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>tags</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(30)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>use_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_tags</code> (pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tag_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>genres</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>slug</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>track_genres</code> (pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>genre_slug</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>position</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>playback_analytics</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>play_time</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td>Secondes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>pause_count</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>seek_count</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>completion_rate</code></td>
|
||
<td>DECIMAL(5,2)</td>
|
||
<td></td>
|
||
<td>0-100%</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>started_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ended_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>C. Playlists</h2>
|
||
<h3><code>playlists</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(200)</td>
|
||
<td></td>
|
||
<td>Titre (colonne DB: <code>name</code>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_public</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>cover_url</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>follower_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_editorial</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td>Playlist éditoriale</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_default_favorites</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td>Playlist favoris auto</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>user</code> (belongs to), <code>tracks</code> (has many PlaylistTrack), <code>collaborators</code> (has many, CASCADE)</p>
|
||
<h3><code>playlist_tracks</code> (pivot ordonné)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → playlists (CASCADE), INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>position</code></td>
|
||
<td>INT</td>
|
||
<td>Ordre dans la playlist</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>added_by</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>added_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>playlist_collaborators</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → playlists, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users, INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>permission</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'read'</td>
|
||
<td>read/write/admin</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>playlist_follows</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>playlist_share_links</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>share_token</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>access_count</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>playlist_versions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (SET NULL)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>version</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>action</code></td>
|
||
<td>ENUM</td>
|
||
<td></td>
|
||
<td>Type de modification</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>title</code></td>
|
||
<td>VARCHAR(200)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_public</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>cover_url</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tracks_snapshot</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td>JSON des pistes à cette version</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_genre_follows</code> (pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>genre_slug</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_tag_follows</code> (pivot)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tag_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK composite</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>D. Chat & Messagerie</h2>
|
||
<h3><code>rooms</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>room_type</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'public'</td>
|
||
<td>public/private/dm</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_private</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>members</code> (has many, CASCADE), <code>messages</code> (has many, CASCADE)</p>
|
||
<h3><code>room_members</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>room_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → rooms (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>role</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'member'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>joined_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>room_invitations</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>room_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → rooms</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>inviter_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>invitee_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>token</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'pending' (pending/accepted/expired)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>messages</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>room_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → rooms</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>sender_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>message_type</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'text'</td>
|
||
<td>text/image/audio/system</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>reply_to_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE, self-ref</td>
|
||
<td>Réponse à</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_edited</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_deleted</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_pinned</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>edited_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'sent'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>metadata</code></td>
|
||
<td>JSONB</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content_tsv</code></td>
|
||
<td>TSVECTOR</td>
|
||
<td></td>
|
||
<td>Recherche full-text</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>message_reactions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE(user_id, message_id, emoji)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>message_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>emoji</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>read_receipts</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE(user_id, message_id)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>message_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>read_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>delivered_status</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE(user_id, message_id)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>message_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>delivered_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>E. Streaming & Collaboration</h2>
|
||
<h3><code>hls_streams</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>playlist_url</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>segments_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bitrates</code></td>
|
||
<td>JSONB</td>
|
||
<td></td>
|
||
<td>Liste des bitrates disponibles</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'pending', INDEX</td>
|
||
<td>pending/processing/ready/failed</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>hls_transcode_queue</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>priority</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 5</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'pending', INDEX</td>
|
||
<td>pending/processing/completed/failed</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>retry_count</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>max_retries</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>error_message</code></td>
|
||
<td>TEXT</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>started_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>completed_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>live_streams</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>title</code></td>
|
||
<td>VARCHAR(200)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>category</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>thumbnail_url</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>stream_key</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td>Masqué en JSON</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>streamer_name</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_live</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>started_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ended_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>viewer_count</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>tags</code></td>
|
||
<td>JSONB</td>
|
||
<td>DEFAULT '[]'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>scheduled_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>stream_url</code></td>
|
||
<td>TEXT</td>
|
||
<td>DEFAULT ''</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_vod</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>co_listening_sessions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>host_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users, INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks, INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>queues</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>current_track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>current_position</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_playing</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>shuffle</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>repeat_mode</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'off'</td>
|
||
<td>off/one/all</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>volume</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 100</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>queue_items</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>queue_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → queues</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → tracks</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>position</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>queue_sessions</code> (sessions collaboratives)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>share_token</code></td>
|
||
<td>VARCHAR(32)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>shared_queue_items</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>session_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>track_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>position</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>F. Fichiers & Stockage</h2>
|
||
<h3><code>user_files</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>folder_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → user_folders (SET NULL), NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>filename</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>s3_key</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td>Clé MinIO/S3</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>size_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>mime_type</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td>DEFAULT 'application/octet-stream'</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_folders</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>parent_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → user_folders (CASCADE), NULLABLE</td>
|
||
<td>Hiérarchie</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Relations</strong> : <code>parent</code> (self-ref), <code>children</code> (has many), <code>files</code> (has many)</p>
|
||
<h3><code>cloud_file_versions</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → user_files (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>version</code></td>
|
||
<td>INT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>storage_key</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>size_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>cloud_file_shares</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → user_files (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>token</code></td>
|
||
<td>VARCHAR(64)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>permissions</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'read'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>user_storage_quotas</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>max_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 5368709120</td>
|
||
<td>~5 Go</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>used_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td>DEFAULT 0</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>G. Équipement (Gear)</h2>
|
||
<h3><code>gear_items</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>name</code></td>
|
||
<td>VARCHAR(200)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>category</code></td>
|
||
<td>VARCHAR(100)</td>
|
||
<td></td>
|
||
<td>micro, interface, casque...</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>brand</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>model</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>serial_number</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>image</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>images</code></td>
|
||
<td>JSONB</td>
|
||
<td>DEFAULT '[]'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td></td>
|
||
<td>actif, en réparation, vendu</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>condition</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td></td>
|
||
<td>neuf, bon, usé</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>purchase_date</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>purchase_price</code></td>
|
||
<td>DECIMAL(12,2)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>currency</code></td>
|
||
<td>VARCHAR(3)</td>
|
||
<td>DEFAULT 'USD'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>vendor</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>order_number</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>warranty_start</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>warranty_expire</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>warranty_type</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>warranty_notes</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>support_contact</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>specs</code></td>
|
||
<td>JSONB</td>
|
||
<td></td>
|
||
<td>Spécifications techniques</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>notes</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>documents</code></td>
|
||
<td>JSONB</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>maintenance_history</code></td>
|
||
<td>JSONB</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_public</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td>Visible sur le profil</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>deleted_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td>Soft delete</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>gear_images</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>gear_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → gear_items (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>image_url</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>position</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>gear_repairs</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>gear_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → gear_items (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>repair_date</code></td>
|
||
<td>DATE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>cost_cents</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 0</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>currency</code></td>
|
||
<td>VARCHAR(3)</td>
|
||
<td>DEFAULT 'EUR'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>provider</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>notes</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>gear_documents</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>gear_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → gear_items (CASCADE)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>type</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>DEFAULT 'invoice'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>storage_key</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>filename</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>H. Paiements & Royalties</h2>
|
||
<h3><code>seller_stripe_accounts</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>stripe_account_id</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>charges_enabled</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>payouts_enabled</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>onboarding_completed</code></td>
|
||
<td>BOOL</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>kyc_status</code></td>
|
||
<td>VARCHAR(32)</td>
|
||
<td>DEFAULT 'not_started'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>kyc_verification_session_id</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>kyc_verified_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>kyc_last_error</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>royalty_records</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>period</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>INDEX</td>
|
||
<td>Période (ex: 2026-03)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>plays</code></td>
|
||
<td>BIGINT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>revenue</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>royalty_amount</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>royalty_rate</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'calculated'</td>
|
||
<td>calculated/paid</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>calculated_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>paid_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>royalty_payouts</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>payout_id</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>amount</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>currency</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'EUR'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>period</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>INDEX</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'pending'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>payment_method</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>transaction_id</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>processed_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>estimated_arrival</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>notes</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>royalty_rates</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content_type</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>UNIQUE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>rate</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>description</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>creator_royalty_rates</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>creator_id</code></td>
|
||
<td>UUID</td>
|
||
<td>UNIQUE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>rate</code></td>
|
||
<td>FLOAT</td>
|
||
<td></td>
|
||
<td>Taux personnalisé</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>reason</code></td>
|
||
<td>VARCHAR</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>royalty_config</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>platform_fee_rate</code></td>
|
||
<td>FLOAT</td>
|
||
<td>DEFAULT 0.15</td>
|
||
<td>15% frais plateforme</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>minimum_payout_amount</code></td>
|
||
<td>FLOAT</td>
|
||
<td>DEFAULT 50.0</td>
|
||
<td>Seuil minimum versement</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>payout_schedule</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'monthly'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>processing_delay</code></td>
|
||
<td>INT</td>
|
||
<td>DEFAULT 3</td>
|
||
<td>Jours</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>currency</code></td>
|
||
<td>VARCHAR</td>
|
||
<td>DEFAULT 'EUR'</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>I. Modération & Administration</h2>
|
||
<h3><code>reports</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>reporter_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>reported_user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content_type</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content_id</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>reason</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'pending'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>resolved_by</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>resolved_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>announcements</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>title</code></td>
|
||
<td>VARCHAR(200)</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>type</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'info'</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>is_active</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT true</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>starts_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ends_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_by</code></td>
|
||
<td>UUID</td>
|
||
<td>NULLABLE</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3><code>notifications</code></h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td>FK → users (CASCADE), INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>type</code></td>
|
||
<td>VARCHAR(50)</td>
|
||
<td>INDEX</td>
|
||
<td>follow, like, comment, system...</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>title</code></td>
|
||
<td>VARCHAR(255)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>content</code></td>
|
||
<td>TEXT</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>link</code></td>
|
||
<td>VARCHAR(500)</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>read</code></td>
|
||
<td>BOOL</td>
|
||
<td>DEFAULT false</td>
|
||
<td>INDEX composite avec user_id</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>read_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>created_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>INDEX</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>J. Exports de données</h2>
|
||
<h3><code>data_exports</code> (RGPD)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Colonne</th>
|
||
<th>Type</th>
|
||
<th>Contraintes</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>id</code></td>
|
||
<td>UUID</td>
|
||
<td>PK</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>user_id</code></td>
|
||
<td>UUID</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>status</code></td>
|
||
<td>VARCHAR(20)</td>
|
||
<td>DEFAULT 'pending'</td>
|
||
<td>pending/processing/completed/failed</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>s3_key</code></td>
|
||
<td>TEXT</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>file_size_bytes</code></td>
|
||
<td>BIGINT</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>expires_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>completed_at</code></td>
|
||
<td>TIMESTAMP</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>error_message</code></td>
|
||
<td>TEXT</td>
|
||
<td>NULLABLE</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Utilisation de Redis</h2>
|
||
<p>Redis est <strong>optionnel</strong> — dégradation gracieuse si indisponible.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Cas d'usage</th>
|
||
<th>Pattern de clé</th>
|
||
<th>TTL</th>
|
||
<th>Fallback</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>Sessions</strong></td>
|
||
<td><code>sessions:{token_hash}</code></td>
|
||
<td>Configurable</td>
|
||
<td>Table <code>sessions</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Cache HTTP</strong></td>
|
||
<td><code>http_cache:{sha256(url)}</code></td>
|
||
<td>5-15 min</td>
|
||
<td>Pas de cache</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Rate limiting</strong></td>
|
||
<td><code>ratelimit:{key}</code></td>
|
||
<td>Variable</td>
|
||
<td>In-memory avec mutex</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Verrouillage compte</strong></td>
|
||
<td><code>lockout:{email}:count</code>, <code>lockout:{email}:locked_until</code></td>
|
||
<td>Configurable</td>
|
||
<td>In-memory map</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Token blacklist</strong></td>
|
||
<td><code>token_blacklist:{jti}</code></td>
|
||
<td>Durée JWT</td>
|
||
<td>Pas de révocation</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Présence utilisateur</strong></td>
|
||
<td><code>presence:{user_id}</code></td>
|
||
<td>Variable</td>
|
||
<td>Table <code>user_presence</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Cache applicatif</strong></td>
|
||
<td>Via <code>CacheService</code></td>
|
||
<td>Variable</td>
|
||
<td>Pas de cache</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Headers de cache : <code>X-Cache: HIT</code> ou <code>X-Cache: MISS</code></p>
|
||
<hr />
|
||
<h2>Statistiques</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Métrique</th>
|
||
<th>Valeur</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Fichiers modèles Go</td>
|
||
<td>68</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tables PostgreSQL</td>
|
||
<td>60+</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Migrations SQL</td>
|
||
<td>115</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tables avec soft delete</td>
|
||
<td>20+</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Tables avec UUIDs</td>
|
||
<td>95%+</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Cas d'usage Redis</td>
|
||
<td>6 principaux</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<hr />
|
||
<h2>Documents liés</h2>
|
||
<ul>
|
||
<li>[[ARCHITECTURE_VEZA]] — Architecture globale</li>
|
||
<li>[[ROUTES_API]] — Endpoints API complets</li>
|
||
<li>[[SERVEUR_STREAMING_RUST]] — Serveur streaming</li>
|
||
<li>[[CONFIGURATION_ENVIRONNEMENT]] — Variables d'environnement</li>
|
||
</ul>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Shop/Backend/README.md</div>
|
||
</div>
|
||
|
||
<h1>Backend Talas Shop</h1>
|
||
<p>Ce dossier contient le <strong>serveur backend de la boutique Talas</strong> : gestion des produits, du panier, des commandes, des paiements et des retours.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Offrir un backend sécurisé, rapide, et évolutif pour la vente de matériel.</li>
|
||
<li>Intégrer les paiements (Stripe, ou simulateur).</li>
|
||
<li>Gérer les droits, stocks, suivis de commande et retours.</li>
|
||
</ul>
|
||
<h2>Contenu recommandé :</h2>
|
||
<ul>
|
||
<li>API REST/GraphQL (<code>/products</code>, <code>/cart</code>, <code>/orders</code>)</li>
|
||
<li><code>services/</code> : logique produit, commande, paiement</li>
|
||
<li><code>models/</code> : schéma base de données (PostgreSQL recommandé)</li>
|
||
<li><code>admin/</code> : endpoints internes (dashboard, statistiques)</li>
|
||
<li><code>webhooks/</code> : Stripe, emails transactionnels, retours</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Ce backend doit être indépendant de la logique d’auth, qui réside dans <code>Auth_&_Core</code>.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Shop/Frontend/README.md</div>
|
||
</div>
|
||
|
||
<h1>Frontend Talas Shop</h1>
|
||
<p>Ce dossier contient l’interface web de la boutique en ligne Talas : navigation produit, panier, commande, espace client.</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Créer une expérience utilisateur fluide et accessible.</li>
|
||
<li>Mettre en avant les produits, leurs avantages et la réparabilité.</li>
|
||
<li>Intégrer le paiement et l’espace client.</li>
|
||
</ul>
|
||
<h2>Contenu recommandé :</h2>
|
||
<ul>
|
||
<li><code>pages/</code> : accueil, produit, panier, commande, espace client</li>
|
||
<li><code>components/</code> : ProductCard, Cart, PaymentForm</li>
|
||
<li><code>hooks/</code> : gestion panier, authentification</li>
|
||
<li><code>styles/</code> : design system (Tailwind, SCSS, etc.)</li>
|
||
<li><code>api/</code> : appels backend (GET produits, POST commande…)</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>L’interface doit être compatible mobile-first et intégrer des modules d'accessibilité.</p>
|
||
</blockquote>
|
||
<div class='page-break'></div>
|
||
|
||
<div class='doc-header'>
|
||
<h2>📄 README.md</h2>
|
||
<div class='doc-path'>Chemin: 03_APPS_&_SERVICES/Shop/Paiement/README.md</div>
|
||
</div>
|
||
|
||
<h1>Paiement – Talas Shop</h1>
|
||
<p>Ce dossier isole la logique liée au <strong>paiement</strong> dans la boutique Talas (gestion des transactions, webhooks, factures, remboursements).</p>
|
||
<h2>Objectifs :</h2>
|
||
<ul>
|
||
<li>Sécuriser le processus d’achat.</li>
|
||
<li>Gérer les erreurs, les remboursements, et les cas limites.</li>
|
||
<li>Permettre des extensions futures (paiement fractionné, bons d’achat, etc.).</li>
|
||
</ul>
|
||
<h2>Contenu recommandé :</h2>
|
||
<ul>
|
||
<li><code>integrations/stripe/</code> : checkout, webhooks</li>
|
||
<li><code>simulations/</code> : sandbox de test local</li>
|
||
<li><code>pdf/</code> : génération des factures</li>
|
||
<li><code>failures/</code> : logs d’échecs, cas d’usage atypiques</li>
|
||
<li><code>README_infra.md</code> : configuration webhook/port</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Tu peux isoler ce module en microservice si besoin.</p>
|
||
</blockquote>
|
||
</body>
|
||
</html>
|