1016 lines
31 KiB
Markdown
1016 lines
31 KiB
Markdown
|
|
# Schéma Base de Données Veza
|
||
|
|
|
||
|
|
> Référence complète du schéma PostgreSQL — 60+ tables, UUIDs, soft deletes.
|
||
|
|
> Source : `veza-backend-api/internal/models/` (68 fichiers Go) et `migrations/` (115 fichiers SQL)
|
||
|
|
> ORM : GORM v1 (mapping uniquement, migrations 100% SQL)
|
||
|
|
|
||
|
|
## Stratégie de migration
|
||
|
|
|
||
|
|
- **Migrations SQL pures** dans `veza-backend-api/migrations/` (001 à 115+)
|
||
|
|
- **GORM** utilisé uniquement pour le mapping Go ↔ PostgreSQL, pas pour la création de schéma
|
||
|
|
- **AutoMigrate()** est vide — tout est géré par SQL
|
||
|
|
- **Outil** : `go run ./cmd/migrate_tool/main.go up` (ou `down` pour rollback)
|
||
|
|
- Table `schema_migrations` pour le suivi des migrations appliquées
|
||
|
|
|
||
|
|
## Conventions
|
||
|
|
|
||
|
|
- **Clés primaires** : UUID v4 (`uuid.UUID` avec `google/uuid`)
|
||
|
|
- **Soft delete** : Colonne `deleted_at` indexée sur 20+ tables
|
||
|
|
- **Timestamps** : `created_at`, `updated_at` sur toutes les tables
|
||
|
|
- **JSONB** : Utilisé pour les données flexibles (social_links, specs, metadata)
|
||
|
|
- **Enums** : Types PostgreSQL custom (user_role, track_status, etc.)
|
||
|
|
- **Foreign keys** : Contraintes PostgreSQL natives, toujours actives
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## A. Utilisateurs & Authentification
|
||
|
|
|
||
|
|
### `users`
|
||
|
|
|
||
|
|
Table centrale — profil utilisateur.
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `username` | VARCHAR(30) | NOT NULL | |
|
||
|
|
| `email` | VARCHAR | NOT NULL, UNIQUE | |
|
||
|
|
| `password_hash` | VARCHAR | NOT NULL | Masqué en JSON |
|
||
|
|
| `token_version` | INT | DEFAULT 0 | Pour révocation de tokens |
|
||
|
|
| `first_name` | VARCHAR | | |
|
||
|
|
| `last_name` | VARCHAR | | |
|
||
|
|
| `avatar` | TEXT | | URL avatar |
|
||
|
|
| `banner_url` | TEXT | | URL bannière |
|
||
|
|
| `bio` | TEXT | | |
|
||
|
|
| `location` | VARCHAR | | |
|
||
|
|
| `birthdate` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `gender` | VARCHAR(20) | | |
|
||
|
|
| `role` | user_role ENUM | DEFAULT 'user' | |
|
||
|
|
| `is_active` | BOOL | DEFAULT true | |
|
||
|
|
| `is_verified` | BOOL | DEFAULT false | |
|
||
|
|
| `is_banned` | BOOL | DEFAULT false | |
|
||
|
|
| `is_admin` | BOOL | DEFAULT false | |
|
||
|
|
| `is_public` | BOOL | DEFAULT true | |
|
||
|
|
| `last_login_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `login_count` | INT | DEFAULT 0 | |
|
||
|
|
| `password_changed_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `social_links` | JSONB | DEFAULT '{}' | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
| `deleted_at` | TIMESTAMP | INDEX | Soft delete |
|
||
|
|
|
||
|
|
**Relations** : `roles` (M2M via `user_roles`), `track_likes` (has many, CASCADE)
|
||
|
|
|
||
|
|
### `sessions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users, INDEX | |
|
||
|
|
| `token_hash` | VARCHAR | UNIQUE INDEX | Token hashé |
|
||
|
|
| `ip_address` | VARCHAR | | |
|
||
|
|
| `user_agent` | VARCHAR | | |
|
||
|
|
| `revoked_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `expires_at` | TIMESTAMP | NOT NULL | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
|
||
|
|
### `refresh_tokens`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), NOT NULL, INDEX | |
|
||
|
|
| `token_hash` | VARCHAR | NOT NULL, INDEX | |
|
||
|
|
| `expires_at` | TIMESTAMP | NOT NULL | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
### `roles`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `name` | VARCHAR(50) | UNIQUE, NOT NULL | |
|
||
|
|
| `display_name` | VARCHAR(100) | NOT NULL | |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `is_system` | BOOL | | Rôle système (non supprimable) |
|
||
|
|
| `is_active` | BOOL | DEFAULT true | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
|
||
|
|
**Relations** : `users` (M2M), `permissions` (M2M)
|
||
|
|
|
||
|
|
### `permissions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `name` | VARCHAR(100) | UNIQUE, NOT NULL | |
|
||
|
|
| `resource` | VARCHAR(50) | NOT NULL | |
|
||
|
|
| `action` | VARCHAR(50) | NOT NULL | |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
|
||
|
|
### `user_roles` (table pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), UNIQUE(user_id, role_id) | |
|
||
|
|
| `role_id` | UUID | FK → roles (CASCADE) | |
|
||
|
|
| `role` | VARCHAR(50) | | Nom du rôle (dénormalisé) |
|
||
|
|
| `assigned_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | |
|
||
|
|
| `assigned_by` | UUID | NULLABLE, INDEX | |
|
||
|
|
| `expires_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `is_active` | BOOL | DEFAULT true | |
|
||
|
|
|
||
|
|
### `role_permissions` (table pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `role_id` | UUID | FK → roles (CASCADE), UNIQUE(role_id, permission_id) |
|
||
|
|
| `permission_id` | UUID | FK → permissions (CASCADE) |
|
||
|
|
|
||
|
|
### `mfa_configs`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | NOT NULL, UNIQUE INDEX | |
|
||
|
|
| `secret` | VARCHAR | NOT NULL | Masqué en JSON |
|
||
|
|
| `backup_codes` | TEXT | | JSON array |
|
||
|
|
| `is_enabled` | BOOL | DEFAULT false | |
|
||
|
|
| `last_used_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
### `recovery_codes`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | INDEX |
|
||
|
|
| `code` | VARCHAR | Masqué |
|
||
|
|
| `is_used` | BOOL | DEFAULT false |
|
||
|
|
| `used_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `expires_at` | TIMESTAMP | |
|
||
|
|
| `created_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `webauthn_credentials`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | NOT NULL | |
|
||
|
|
| `credential_id` | BYTEA | UNIQUE, NOT NULL | |
|
||
|
|
| `public_key` | BYTEA | NOT NULL | |
|
||
|
|
| `attestation_type` | VARCHAR(50) | DEFAULT 'none' | |
|
||
|
|
| `aaguid` | BYTEA | | |
|
||
|
|
| `sign_count` | INT | DEFAULT 0 | |
|
||
|
|
| `name` | VARCHAR(100) | DEFAULT 'My Passkey' | |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `last_used_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
|
||
|
|
### `federated_identities`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `provider` | VARCHAR | | google, github, facebook, twitter |
|
||
|
|
| `provider_id` | VARCHAR | | |
|
||
|
|
| `email` | VARCHAR | | |
|
||
|
|
| `display_name` | VARCHAR | | |
|
||
|
|
| `avatar_url` | VARCHAR | | |
|
||
|
|
| `access_token` | TEXT | | Masqué |
|
||
|
|
| `refresh_token` | TEXT | | Masqué |
|
||
|
|
| `expires_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
|
||
|
|
### `api_keys`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | INDEX |
|
||
|
|
| `name` | VARCHAR(100) | |
|
||
|
|
| `prefix` | VARCHAR(16) | INDEX |
|
||
|
|
| `hashed_key` | VARCHAR(128) | Masqué |
|
||
|
|
| `scopes` | TEXT[] | PostgreSQL array |
|
||
|
|
| `last_used_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `expires_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `created_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `user_settings`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE |
|
||
|
|
| `email_notifications` | BOOL | |
|
||
|
|
| `push_notifications` | BOOL | |
|
||
|
|
| `browser_notifications` | BOOL | |
|
||
|
|
| `email_on_follow` | BOOL | |
|
||
|
|
| `email_on_like` | BOOL | |
|
||
|
|
| `email_on_comment` | BOOL | |
|
||
|
|
| `email_on_message` | BOOL | |
|
||
|
|
| `email_on_mention` | BOOL | |
|
||
|
|
| `email_marketing` | BOOL | |
|
||
|
|
| `allow_search_indexing` | BOOL | |
|
||
|
|
| `show_activity` | BOOL | |
|
||
|
|
| `explicit_content` | BOOL | |
|
||
|
|
| `autoplay` | BOOL | |
|
||
|
|
|
||
|
|
### `user_profiles`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE |
|
||
|
|
| `language` | VARCHAR | DEFAULT 'en' |
|
||
|
|
| `timezone` | VARCHAR | DEFAULT 'UTC' |
|
||
|
|
| `theme` | VARCHAR | DEFAULT 'auto' |
|
||
|
|
|
||
|
|
### `user_presence`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `user_id` | UUID | PK | |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'offline' | online/away/busy/offline |
|
||
|
|
| `last_seen_at` | TIMESTAMP | | |
|
||
|
|
| `status_message` | TEXT | | |
|
||
|
|
| `track_id` | UUID | NULLABLE | Piste en écoute |
|
||
|
|
| `track_title` | TEXT | | |
|
||
|
|
| `invisible` | BOOL | DEFAULT false | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## B. Pistes audio
|
||
|
|
|
||
|
|
### `tracks`
|
||
|
|
|
||
|
|
Table principale des pistes audio.
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `creator_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `file_id` | UUID | NULLABLE | |
|
||
|
|
| `title` | VARCHAR(255) | NOT NULL | |
|
||
|
|
| `artist` | VARCHAR(255) | | |
|
||
|
|
| `album` | VARCHAR(255) | | |
|
||
|
|
| `duration` | INT | | Secondes |
|
||
|
|
| `genre` | VARCHAR(100) | | |
|
||
|
|
| `tags` | TEXT[] | | PostgreSQL array |
|
||
|
|
| `year` | INT | DEFAULT 0 | |
|
||
|
|
| `bpm` | INT | NULLABLE | |
|
||
|
|
| `musical_key` | VARCHAR(10) | | |
|
||
|
|
| `file_path` | VARCHAR(500) | | |
|
||
|
|
| `file_size` | BIGINT | | Octets |
|
||
|
|
| `format` | VARCHAR(10) | | wav, mp3, flac... |
|
||
|
|
| `bitrate` | INT | | kbps |
|
||
|
|
| `sample_rate` | INT | | Hz |
|
||
|
|
| `waveform_path` | VARCHAR | | |
|
||
|
|
| `waveform_url` | VARCHAR | | |
|
||
|
|
| `cover_art_path` | VARCHAR | | |
|
||
|
|
| `is_public` | BOOL | DEFAULT true | |
|
||
|
|
| `status` | track_status ENUM | | uploading/processing/completed/failed |
|
||
|
|
| `status_message` | TEXT | | |
|
||
|
|
| `stream_status` | VARCHAR | DEFAULT 'pending' | pending/processing/ready/error |
|
||
|
|
| `stream_manifest_url` | VARCHAR | | URL playlist HLS |
|
||
|
|
| `play_count` | BIGINT | | Non exposé en API |
|
||
|
|
| `like_count` | BIGINT | | Non exposé en API |
|
||
|
|
| `created_at` | TIMESTAMP | | |
|
||
|
|
| `updated_at` | TIMESTAMP | | |
|
||
|
|
| `deleted_at` | TIMESTAMP | INDEX | Soft delete |
|
||
|
|
|
||
|
|
**Relations** : `user` (belongs to), `playlists` (M2M), `likes` (has many), `shares` (has many), `versions` (has many), `hls_streams` (has many)
|
||
|
|
|
||
|
|
### `track_versions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), UNIQUE(track_id, version_number) |
|
||
|
|
| `version_number` | INT | |
|
||
|
|
| `file_path` | VARCHAR(500) | |
|
||
|
|
| `file_size` | BIGINT | Octets |
|
||
|
|
| `changelog` | TEXT | |
|
||
|
|
|
||
|
|
### `track_likes`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), UNIQUE(user_id, track_id) |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE) |
|
||
|
|
| `created_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `track_plays`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | FK → tracks, INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users (SET NULL), NULLABLE, INDEX | Anonyme si non connecté |
|
||
|
|
| `duration` | INT | | Secondes jouées |
|
||
|
|
| `played_at` | TIMESTAMP | INDEX | |
|
||
|
|
| `device` | VARCHAR(100) | | |
|
||
|
|
| `ip_address` | VARCHAR(45) | | |
|
||
|
|
|
||
|
|
### `track_shares`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `track_id` | UUID | INDEX |
|
||
|
|
| `user_id` | UUID | INDEX |
|
||
|
|
| `share_token` | VARCHAR(255) | UNIQUE |
|
||
|
|
| `permissions` | VARCHAR(50) | DEFAULT 'read' (read/download) |
|
||
|
|
| `expires_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `access_count` | BIGINT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `track_comments`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `parent_id` | UUID | FK → track_comments (CASCADE), NULLABLE | Réponses |
|
||
|
|
| `content` | TEXT | NOT NULL | |
|
||
|
|
| `timestamp` | FLOAT | | Position en secondes |
|
||
|
|
| `is_edited` | BOOL | DEFAULT false | |
|
||
|
|
|
||
|
|
**Relations** : `parent` (self-ref), `replies` (has many self-ref)
|
||
|
|
|
||
|
|
### `track_reposts`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX |
|
||
|
|
| `created_at` | TIMESTAMP | INDEX |
|
||
|
|
|
||
|
|
### `track_stems`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX |
|
||
|
|
| `name` | VARCHAR(100) | |
|
||
|
|
| `file_path` | VARCHAR(500) | |
|
||
|
|
| `format` | VARCHAR(10) | |
|
||
|
|
| `size_bytes` | BIGINT | |
|
||
|
|
| `created_at` | TIMESTAMP | |
|
||
|
|
| `deleted_at` | TIMESTAMP | Soft delete |
|
||
|
|
|
||
|
|
### `track_lyrics`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), UNIQUE |
|
||
|
|
| `content` | TEXT | NOT NULL |
|
||
|
|
|
||
|
|
### `track_history`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users (SET NULL) | |
|
||
|
|
| `action` | ENUM | INDEX | created/updated/deleted/published/unpublished/restored |
|
||
|
|
| `old_value` | TEXT | | |
|
||
|
|
| `new_value` | TEXT | | |
|
||
|
|
|
||
|
|
### `tags`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `name` | VARCHAR(30) | UNIQUE |
|
||
|
|
| `use_count` | INT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `track_tags` (pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `track_id` | UUID | PK composite |
|
||
|
|
| `tag_id` | UUID | PK composite |
|
||
|
|
| `created_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `genres`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `slug` | VARCHAR(50) | PK |
|
||
|
|
| `name` | VARCHAR(100) | |
|
||
|
|
|
||
|
|
### `track_genres` (pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `track_id` | UUID | PK composite |
|
||
|
|
| `genre_slug` | VARCHAR(50) | PK composite |
|
||
|
|
| `position` | INT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `playback_analytics`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `play_time` | INT | | Secondes |
|
||
|
|
| `pause_count` | INT | | |
|
||
|
|
| `seek_count` | INT | | |
|
||
|
|
| `completion_rate` | DECIMAL(5,2) | | 0-100% |
|
||
|
|
| `started_at` | TIMESTAMP | | |
|
||
|
|
| `ended_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## C. Playlists
|
||
|
|
|
||
|
|
### `playlists`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `name` | VARCHAR(200) | | Titre (colonne DB: `name`) |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `is_public` | BOOL | DEFAULT true | |
|
||
|
|
| `cover_url` | VARCHAR(500) | | |
|
||
|
|
| `track_count` | INT | DEFAULT 0 | |
|
||
|
|
| `follower_count` | INT | DEFAULT 0 | |
|
||
|
|
| `is_editorial` | BOOL | DEFAULT false | Playlist éditoriale |
|
||
|
|
| `is_default_favorites` | BOOL | DEFAULT false | Playlist favoris auto |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
**Relations** : `user` (belongs to), `tracks` (has many PlaylistTrack), `collaborators` (has many, CASCADE)
|
||
|
|
|
||
|
|
### `playlist_tracks` (pivot ordonné)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `playlist_id` | UUID | FK → playlists (CASCADE), INDEX |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX |
|
||
|
|
| `position` | INT | Ordre dans la playlist |
|
||
|
|
| `added_by` | UUID | |
|
||
|
|
| `added_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `playlist_collaborators`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `playlist_id` | UUID | FK → playlists, INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users, INDEX | |
|
||
|
|
| `permission` | VARCHAR(20) | DEFAULT 'read' | read/write/admin |
|
||
|
|
|
||
|
|
### `playlist_follows`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `playlist_id` | UUID | INDEX |
|
||
|
|
| `user_id` | UUID | INDEX |
|
||
|
|
|
||
|
|
### `playlist_share_links`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `playlist_id` | UUID | INDEX |
|
||
|
|
| `user_id` | UUID | INDEX |
|
||
|
|
| `share_token` | VARCHAR(255) | UNIQUE |
|
||
|
|
| `expires_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `access_count` | BIGINT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `playlist_versions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `playlist_id` | UUID | INDEX | |
|
||
|
|
| `user_id` | UUID | FK → users (SET NULL) | |
|
||
|
|
| `version` | INT | | |
|
||
|
|
| `action` | ENUM | | Type de modification |
|
||
|
|
| `title` | VARCHAR(200) | | |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `is_public` | BOOL | | |
|
||
|
|
| `cover_url` | VARCHAR(500) | | |
|
||
|
|
| `tracks_snapshot` | TEXT | | JSON des pistes à cette version |
|
||
|
|
|
||
|
|
### `user_genre_follows` (pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `user_id` | UUID | PK composite |
|
||
|
|
| `genre_slug` | VARCHAR | PK composite |
|
||
|
|
|
||
|
|
### `user_tag_follows` (pivot)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `user_id` | UUID | PK composite |
|
||
|
|
| `tag_id` | UUID | PK composite |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## D. Chat & Messagerie
|
||
|
|
|
||
|
|
### `rooms`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `name` | VARCHAR(255) | | |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `room_type` | VARCHAR | DEFAULT 'public' | public/private/dm |
|
||
|
|
| `is_private` | BOOL | DEFAULT false | |
|
||
|
|
| `creator_id` | UUID | FK → users (CASCADE) | |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
**Relations** : `members` (has many, CASCADE), `messages` (has many, CASCADE)
|
||
|
|
|
||
|
|
### `room_members`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `room_id` | UUID | FK → rooms (CASCADE) |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE) |
|
||
|
|
| `role` | VARCHAR | DEFAULT 'member' |
|
||
|
|
| `joined_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `room_invitations`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `room_id` | UUID | FK → rooms |
|
||
|
|
| `inviter_id` | UUID | FK → users |
|
||
|
|
| `invitee_id` | UUID | NULLABLE |
|
||
|
|
| `token` | UUID | UNIQUE |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'pending' (pending/accepted/expired) |
|
||
|
|
| `expires_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `messages`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `room_id` | UUID | FK → rooms | |
|
||
|
|
| `sender_id` | UUID | FK → users | |
|
||
|
|
| `content` | TEXT | | |
|
||
|
|
| `message_type` | VARCHAR | DEFAULT 'text' | text/image/audio/system |
|
||
|
|
| `reply_to_id` | UUID | NULLABLE, self-ref | Réponse à |
|
||
|
|
| `is_edited` | BOOL | DEFAULT false | |
|
||
|
|
| `is_deleted` | BOOL | DEFAULT false | |
|
||
|
|
| `is_pinned` | BOOL | DEFAULT false | |
|
||
|
|
| `edited_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'sent' | |
|
||
|
|
| `metadata` | JSONB | NULLABLE | |
|
||
|
|
| `content_tsv` | TSVECTOR | | Recherche full-text |
|
||
|
|
|
||
|
|
### `message_reactions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE(user_id, message_id, emoji) |
|
||
|
|
| `message_id` | UUID | |
|
||
|
|
| `emoji` | VARCHAR(50) | |
|
||
|
|
|
||
|
|
### `read_receipts`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE(user_id, message_id) |
|
||
|
|
| `message_id` | UUID | |
|
||
|
|
| `read_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `delivered_status`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE(user_id, message_id) |
|
||
|
|
| `message_id` | UUID | |
|
||
|
|
| `delivered_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## E. Streaming & Collaboration
|
||
|
|
|
||
|
|
### `hls_streams`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | FK → tracks (CASCADE), INDEX | |
|
||
|
|
| `playlist_url` | VARCHAR(500) | | |
|
||
|
|
| `segments_count` | INT | DEFAULT 0 | |
|
||
|
|
| `bitrates` | JSONB | | Liste des bitrates disponibles |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'pending', INDEX | pending/processing/ready/failed |
|
||
|
|
|
||
|
|
### `hls_transcode_queue`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `track_id` | UUID | INDEX | |
|
||
|
|
| `priority` | INT | DEFAULT 5 | |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'pending', INDEX | pending/processing/completed/failed |
|
||
|
|
| `retry_count` | INT | | |
|
||
|
|
| `max_retries` | INT | | |
|
||
|
|
| `error_message` | TEXT | NULLABLE | |
|
||
|
|
| `started_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `completed_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
|
||
|
|
### `live_streams`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE) | |
|
||
|
|
| `title` | VARCHAR(200) | | |
|
||
|
|
| `description` | TEXT | | |
|
||
|
|
| `category` | VARCHAR(100) | | |
|
||
|
|
| `thumbnail_url` | VARCHAR(500) | | |
|
||
|
|
| `stream_key` | VARCHAR(100) | | Masqué en JSON |
|
||
|
|
| `streamer_name` | VARCHAR(100) | | |
|
||
|
|
| `is_live` | BOOL | DEFAULT false | |
|
||
|
|
| `started_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `ended_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `viewer_count` | INT | DEFAULT 0 | |
|
||
|
|
| `tags` | JSONB | DEFAULT '[]' | |
|
||
|
|
| `scheduled_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `stream_url` | TEXT | DEFAULT '' | |
|
||
|
|
| `is_vod` | BOOL | DEFAULT false | |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
### `co_listening_sessions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `host_id` | UUID | FK → users, INDEX |
|
||
|
|
| `track_id` | UUID | FK → tracks, INDEX |
|
||
|
|
| `expires_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `queues`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | UNIQUE | |
|
||
|
|
| `current_track_id` | UUID | NULLABLE | |
|
||
|
|
| `current_position` | INT | DEFAULT 0 | |
|
||
|
|
| `is_playing` | BOOL | DEFAULT false | |
|
||
|
|
| `shuffle` | BOOL | DEFAULT false | |
|
||
|
|
| `repeat_mode` | VARCHAR(20) | DEFAULT 'off' | off/one/all |
|
||
|
|
| `volume` | INT | DEFAULT 100 | |
|
||
|
|
|
||
|
|
### `queue_items`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `queue_id` | UUID | FK → queues |
|
||
|
|
| `track_id` | UUID | FK → tracks |
|
||
|
|
| `position` | INT | |
|
||
|
|
|
||
|
|
### `queue_sessions` (sessions collaboratives)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `share_token` | VARCHAR(32) | UNIQUE |
|
||
|
|
| `creator_id` | UUID | INDEX |
|
||
|
|
|
||
|
|
### `shared_queue_items`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `session_id` | UUID | INDEX |
|
||
|
|
| `track_id` | UUID | |
|
||
|
|
| `position` | INT | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## F. Fichiers & Stockage
|
||
|
|
|
||
|
|
### `user_files`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users | |
|
||
|
|
| `folder_id` | UUID | FK → user_folders (SET NULL), NULLABLE | |
|
||
|
|
| `filename` | VARCHAR(255) | | |
|
||
|
|
| `s3_key` | VARCHAR(500) | | Clé MinIO/S3 |
|
||
|
|
| `size_bytes` | BIGINT | DEFAULT 0 | |
|
||
|
|
| `mime_type` | VARCHAR(100) | DEFAULT 'application/octet-stream' | |
|
||
|
|
|
||
|
|
### `user_folders`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE) | |
|
||
|
|
| `name` | VARCHAR(255) | | |
|
||
|
|
| `parent_id` | UUID | FK → user_folders (CASCADE), NULLABLE | Hiérarchie |
|
||
|
|
|
||
|
|
**Relations** : `parent` (self-ref), `children` (has many), `files` (has many)
|
||
|
|
|
||
|
|
### `cloud_file_versions`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `file_id` | UUID | FK → user_files (CASCADE) |
|
||
|
|
| `version` | INT | |
|
||
|
|
| `storage_key` | TEXT | |
|
||
|
|
| `size_bytes` | BIGINT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `cloud_file_shares`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `file_id` | UUID | FK → user_files (CASCADE) |
|
||
|
|
| `token` | VARCHAR(64) | UNIQUE |
|
||
|
|
| `permissions` | VARCHAR(20) | DEFAULT 'read' |
|
||
|
|
| `expires_at` | TIMESTAMP | |
|
||
|
|
|
||
|
|
### `user_storage_quotas`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `user_id` | UUID | PK | |
|
||
|
|
| `max_bytes` | BIGINT | DEFAULT 5368709120 | ~5 Go |
|
||
|
|
| `used_bytes` | BIGINT | DEFAULT 0 | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## G. Équipement (Gear)
|
||
|
|
|
||
|
|
### `gear_items`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users | |
|
||
|
|
| `name` | VARCHAR(200) | | |
|
||
|
|
| `category` | VARCHAR(100) | | micro, interface, casque... |
|
||
|
|
| `brand` | VARCHAR | | |
|
||
|
|
| `model` | VARCHAR | | |
|
||
|
|
| `serial_number` | VARCHAR | | |
|
||
|
|
| `image` | VARCHAR(500) | | |
|
||
|
|
| `images` | JSONB | DEFAULT '[]' | |
|
||
|
|
| `status` | VARCHAR(50) | | actif, en réparation, vendu |
|
||
|
|
| `condition` | VARCHAR(50) | | neuf, bon, usé |
|
||
|
|
| `purchase_date` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `purchase_price` | DECIMAL(12,2) | | |
|
||
|
|
| `currency` | VARCHAR(3) | DEFAULT 'USD' | |
|
||
|
|
| `vendor` | VARCHAR | | |
|
||
|
|
| `order_number` | VARCHAR | | |
|
||
|
|
| `warranty_start` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `warranty_expire` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `warranty_type` | VARCHAR | | |
|
||
|
|
| `warranty_notes` | TEXT | | |
|
||
|
|
| `support_contact` | VARCHAR | | |
|
||
|
|
| `specs` | JSONB | | Spécifications techniques |
|
||
|
|
| `notes` | TEXT | | |
|
||
|
|
| `documents` | JSONB | | |
|
||
|
|
| `maintenance_history` | JSONB | | |
|
||
|
|
| `is_public` | BOOL | DEFAULT false | Visible sur le profil |
|
||
|
|
| `deleted_at` | TIMESTAMP | | Soft delete |
|
||
|
|
|
||
|
|
### `gear_images`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `gear_id` | UUID | FK → gear_items (CASCADE) |
|
||
|
|
| `image_url` | VARCHAR(500) | |
|
||
|
|
| `position` | INT | DEFAULT 0 |
|
||
|
|
|
||
|
|
### `gear_repairs`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `gear_id` | UUID | FK → gear_items (CASCADE) |
|
||
|
|
| `repair_date` | DATE | |
|
||
|
|
| `description` | TEXT | |
|
||
|
|
| `cost_cents` | INT | DEFAULT 0 |
|
||
|
|
| `currency` | VARCHAR(3) | DEFAULT 'EUR' |
|
||
|
|
| `provider` | VARCHAR(255) | |
|
||
|
|
| `notes` | TEXT | |
|
||
|
|
|
||
|
|
### `gear_documents`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `gear_id` | UUID | FK → gear_items (CASCADE) |
|
||
|
|
| `type` | VARCHAR(50) | DEFAULT 'invoice' |
|
||
|
|
| `storage_key` | TEXT | |
|
||
|
|
| `filename` | VARCHAR(255) | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## H. Paiements & Royalties
|
||
|
|
|
||
|
|
### `seller_stripe_accounts`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `user_id` | UUID | UNIQUE |
|
||
|
|
| `stripe_account_id` | VARCHAR(255) | UNIQUE |
|
||
|
|
| `charges_enabled` | BOOL | |
|
||
|
|
| `payouts_enabled` | BOOL | |
|
||
|
|
| `onboarding_completed` | BOOL | |
|
||
|
|
| `kyc_status` | VARCHAR(32) | DEFAULT 'not_started' |
|
||
|
|
| `kyc_verification_session_id` | VARCHAR(255) | |
|
||
|
|
| `kyc_verified_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `kyc_last_error` | TEXT | |
|
||
|
|
|
||
|
|
### `royalty_records`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `content_id` | UUID | INDEX | |
|
||
|
|
| `creator_id` | UUID | INDEX | |
|
||
|
|
| `period` | VARCHAR | INDEX | Période (ex: 2026-03) |
|
||
|
|
| `plays` | BIGINT | | |
|
||
|
|
| `revenue` | FLOAT | | |
|
||
|
|
| `royalty_amount` | FLOAT | | |
|
||
|
|
| `royalty_rate` | FLOAT | | |
|
||
|
|
| `status` | VARCHAR | DEFAULT 'calculated' | calculated/paid |
|
||
|
|
| `calculated_at` | TIMESTAMP | | |
|
||
|
|
| `paid_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
|
||
|
|
### `royalty_payouts`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `payout_id` | VARCHAR | UNIQUE |
|
||
|
|
| `creator_id` | UUID | INDEX |
|
||
|
|
| `amount` | FLOAT | |
|
||
|
|
| `currency` | VARCHAR | DEFAULT 'EUR' |
|
||
|
|
| `period` | VARCHAR | INDEX |
|
||
|
|
| `status` | VARCHAR | DEFAULT 'pending' |
|
||
|
|
| `payment_method` | VARCHAR | |
|
||
|
|
| `transaction_id` | VARCHAR | |
|
||
|
|
| `processed_at` | TIMESTAMP | |
|
||
|
|
| `estimated_arrival` | TIMESTAMP | |
|
||
|
|
| `notes` | VARCHAR | |
|
||
|
|
|
||
|
|
### `royalty_rates`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `content_type` | VARCHAR | UNIQUE |
|
||
|
|
| `rate` | FLOAT | |
|
||
|
|
| `description` | VARCHAR | |
|
||
|
|
| `is_active` | BOOL | DEFAULT true |
|
||
|
|
|
||
|
|
### `creator_royalty_rates`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `creator_id` | UUID | UNIQUE | |
|
||
|
|
| `rate` | FLOAT | | Taux personnalisé |
|
||
|
|
| `reason` | VARCHAR | | |
|
||
|
|
| `is_active` | BOOL | DEFAULT true | |
|
||
|
|
|
||
|
|
### `royalty_config`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `platform_fee_rate` | FLOAT | DEFAULT 0.15 | 15% frais plateforme |
|
||
|
|
| `minimum_payout_amount` | FLOAT | DEFAULT 50.0 | Seuil minimum versement |
|
||
|
|
| `payout_schedule` | VARCHAR | DEFAULT 'monthly' | |
|
||
|
|
| `processing_delay` | INT | DEFAULT 3 | Jours |
|
||
|
|
| `currency` | VARCHAR | DEFAULT 'EUR' | |
|
||
|
|
| `is_active` | BOOL | DEFAULT true | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## I. Modération & Administration
|
||
|
|
|
||
|
|
### `reports`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `reporter_id` | UUID | |
|
||
|
|
| `reported_user_id` | UUID | NULLABLE |
|
||
|
|
| `content_type` | VARCHAR(50) | |
|
||
|
|
| `content_id` | UUID | NULLABLE |
|
||
|
|
| `reason` | TEXT | |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'pending' |
|
||
|
|
| `resolved_by` | UUID | NULLABLE |
|
||
|
|
| `resolved_at` | TIMESTAMP | NULLABLE |
|
||
|
|
|
||
|
|
### `announcements`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes |
|
||
|
|
|---------|------|-------------|
|
||
|
|
| `id` | UUID | PK |
|
||
|
|
| `title` | VARCHAR(200) | |
|
||
|
|
| `content` | TEXT | |
|
||
|
|
| `type` | VARCHAR(20) | DEFAULT 'info' |
|
||
|
|
| `is_active` | BOOL | DEFAULT true |
|
||
|
|
| `starts_at` | TIMESTAMP | |
|
||
|
|
| `ends_at` | TIMESTAMP | NULLABLE |
|
||
|
|
| `created_by` | UUID | NULLABLE |
|
||
|
|
|
||
|
|
### `notifications`
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | FK → users (CASCADE), INDEX | |
|
||
|
|
| `type` | VARCHAR(50) | INDEX | follow, like, comment, system... |
|
||
|
|
| `title` | VARCHAR(255) | | |
|
||
|
|
| `content` | TEXT | | |
|
||
|
|
| `link` | VARCHAR(500) | | |
|
||
|
|
| `read` | BOOL | DEFAULT false | INDEX composite avec user_id |
|
||
|
|
| `read_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `created_at` | TIMESTAMP | INDEX | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## J. Exports de données
|
||
|
|
|
||
|
|
### `data_exports` (RGPD)
|
||
|
|
|
||
|
|
| Colonne | Type | Contraintes | Description |
|
||
|
|
|---------|------|-------------|-------------|
|
||
|
|
| `id` | UUID | PK | |
|
||
|
|
| `user_id` | UUID | | |
|
||
|
|
| `status` | VARCHAR(20) | DEFAULT 'pending' | pending/processing/completed/failed |
|
||
|
|
| `s3_key` | TEXT | NULLABLE | |
|
||
|
|
| `file_size_bytes` | BIGINT | NULLABLE | |
|
||
|
|
| `expires_at` | TIMESTAMP | | |
|
||
|
|
| `completed_at` | TIMESTAMP | NULLABLE | |
|
||
|
|
| `error_message` | TEXT | NULLABLE | |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Utilisation de Redis
|
||
|
|
|
||
|
|
Redis est **optionnel** — dégradation gracieuse si indisponible.
|
||
|
|
|
||
|
|
| Cas d'usage | Pattern de clé | TTL | Fallback |
|
||
|
|
|-------------|---------------|-----|----------|
|
||
|
|
| **Sessions** | `sessions:{token_hash}` | Configurable | Table `sessions` |
|
||
|
|
| **Cache HTTP** | `http_cache:{sha256(url)}` | 5-15 min | Pas de cache |
|
||
|
|
| **Rate limiting** | `ratelimit:{key}` | Variable | In-memory avec mutex |
|
||
|
|
| **Verrouillage compte** | `lockout:{email}:count`, `lockout:{email}:locked_until` | Configurable | In-memory map |
|
||
|
|
| **Token blacklist** | `token_blacklist:{jti}` | Durée JWT | Pas de révocation |
|
||
|
|
| **Présence utilisateur** | `presence:{user_id}` | Variable | Table `user_presence` |
|
||
|
|
| **Cache applicatif** | Via `CacheService` | Variable | Pas de cache |
|
||
|
|
|
||
|
|
Headers de cache : `X-Cache: HIT` ou `X-Cache: MISS`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Statistiques
|
||
|
|
|
||
|
|
| Métrique | Valeur |
|
||
|
|
|----------|--------|
|
||
|
|
| Fichiers modèles Go | 68 |
|
||
|
|
| Tables PostgreSQL | 60+ |
|
||
|
|
| Migrations SQL | 115 |
|
||
|
|
| Tables avec soft delete | 20+ |
|
||
|
|
| Tables avec UUIDs | 95%+ |
|
||
|
|
| Cas d'usage Redis | 6 principaux |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Documents liés
|
||
|
|
|
||
|
|
- [[ARCHITECTURE_VEZA]] — Architecture globale
|
||
|
|
- [[ROUTES_API]] — Endpoints API complets
|
||
|
|
- [[SERVEUR_STREAMING_RUST]] — Serveur streaming
|
||
|
|
- [[CONFIGURATION_ENVIRONNEMENT]] — Variables d'environnement
|