stabilizing veza-backend-api: P3 - FINAL

This commit is contained in:
senke 2025-12-16 13:37:36 -05:00
parent b7b226d1d5
commit bfcec3dd78

View file

@ -1,196 +1,535 @@
[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/golang-migrate/migrate/ci.yaml?branch=master)](https://github.com/golang-migrate/migrate/actions/workflows/ci.yaml?query=branch%3Amaster)
[![GoDoc](https://pkg.go.dev/badge/github.com/golang-migrate/migrate)](https://pkg.go.dev/github.com/golang-migrate/migrate/v4)
[![Coverage Status](https://img.shields.io/coveralls/github/golang-migrate/migrate/master.svg)](https://coveralls.io/github/golang-migrate/migrate?branch=master)
[![packagecloud.io](https://img.shields.io/badge/deb-packagecloud.io-844fec.svg)](https://packagecloud.io/golang-migrate/migrate?filter=debs)
[![Docker Pulls](https://img.shields.io/docker/pulls/migrate/migrate.svg)](https://hub.docker.com/r/migrate/migrate/)
![Supported Go Versions](https://img.shields.io/badge/Go-1.24%2C%201.25-lightgrey.svg)
[![GitHub Release](https://img.shields.io/github/release/golang-migrate/migrate.svg)](https://github.com/golang-migrate/migrate/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/golang-migrate/migrate/v4)](https://goreportcard.com/report/github.com/golang-migrate/migrate/v4)
# Veza Backend API
# migrate
__Database migrations written in Go. Use as [CLI](#cli-usage) or import as [library](#use-in-your-go-project).__
* Migrate reads migrations from [sources](#migration-sources)
and applies them in correct order to a [database](#databases).
* Drivers are "dumb", migrate glues everything together and makes sure the logic is bulletproof.
(Keeps the drivers lightweight, too.)
* Database drivers don't assume things or try to correct user input. When in doubt, fail.
Forked from [mattes/migrate](https://github.com/mattes/migrate)
## Databases
Database drivers run migrations. [Add a new database?](database/driver.go)
* [PostgreSQL](database/postgres)
* [PGX v4](database/pgx)
* [PGX v5](database/pgx/v5)
* [Redshift](database/redshift)
* [Ql](database/ql)
* [Cassandra / ScyllaDB](database/cassandra)
* [SQLite](database/sqlite)
* [SQLite3](database/sqlite3) ([todo #165](https://github.com/mattes/migrate/issues/165))
* [SQLCipher](database/sqlcipher)
* [MySQL / MariaDB](database/mysql)
* [Neo4j](database/neo4j)
* [MongoDB](database/mongodb)
* [CrateDB](database/crate) ([todo #170](https://github.com/mattes/migrate/issues/170))
* [Shell](database/shell) ([todo #171](https://github.com/mattes/migrate/issues/171))
* [Google Cloud Spanner](database/spanner)
* [CockroachDB](database/cockroachdb)
* [YugabyteDB](database/yugabytedb)
* [ClickHouse](database/clickhouse)
* [Firebird](database/firebird)
* [MS SQL Server](database/sqlserver)
* [rqlite](database/rqlite)
### Database URLs
Database connection strings are specified via URLs. The URL format is driver dependent but generally has the form: `dbdriver://username:password@host:port/dbname?param1=true&param2=false`
Any [reserved URL characters](https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters) need to be escaped. Note, the `%` character also [needs to be escaped](https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_the_percent_character)
Explicitly, the following characters need to be escaped:
`!`, `#`, `$`, `%`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `/`, `:`, `;`, `=`, `?`, `@`, `[`, `]`
It's easiest to always run the URL parts of your DB connection URL (e.g. username, password, etc) through an URL encoder. See the example Python snippets below:
```bash
$ python3 -c 'import urllib.parse; print(urllib.parse.quote(input("String to encode: "), ""))'
String to encode: FAKEpassword!#$%&'()*+,/:;=?@[]
FAKEpassword%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D
$ python2 -c 'import urllib; print urllib.quote(raw_input("String to encode: "), "")'
String to encode: FAKEpassword!#$%&'()*+,/:;=?@[]
FAKEpassword%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D
$
```
## Migration Sources
Source drivers read migrations from local or remote sources. [Add a new source?](source/driver.go)
* [Filesystem](source/file) - read from filesystem
* [io/fs](source/iofs) - read from a Go [io/fs](https://pkg.go.dev/io/fs#FS)
* [Go-Bindata](source/go_bindata) - read from embedded binary data ([jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata))
* [pkger](source/pkger) - read from embedded binary data ([markbates/pkger](https://github.com/markbates/pkger))
* [GitHub](source/github) - read from remote GitHub repositories
* [GitHub Enterprise](source/github_ee) - read from remote GitHub Enterprise repositories
* [Bitbucket](source/bitbucket) - read from remote Bitbucket repositories
* [Gitlab](source/gitlab) - read from remote Gitlab repositories
* [AWS S3](source/aws_s3) - read from Amazon Web Services S3
* [Google Cloud Storage](source/google_cloud_storage) - read from Google Cloud Platform Storage
## CLI usage
* Simple wrapper around this library.
* Handles ctrl+c (SIGINT) gracefully.
* No config search paths, no config files, no magic ENV var injections.
[CLI Documentation](cmd/migrate) (includes CLI install instructions)
### Basic usage
```bash
$ migrate -source file://path/to/migrations -database postgres://localhost:5432/database up 2
```
### Docker usage
```bash
$ docker run -v {{ migration dir }}:/migrations --network host migrate/migrate
-path=/migrations/ -database postgres://localhost:5432/database up 2
```
## Use in your Go project
* API is stable and frozen for this release (v3 & v4).
* Uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies.
* To help prevent database corruptions, it supports graceful stops via `GracefulStop chan bool`.
* Bring your own logger.
* Uses `io.Reader` streams internally for low memory overhead.
* Thread-safe and no goroutine leaks.
__[Go Documentation](https://pkg.go.dev/github.com/golang-migrate/migrate/v4)__
```go
import (
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/github"
)
func main() {
m, err := migrate.New(
"github://mattes:personal-access-token@mattes/migrate_test",
"postgres://localhost:5432/database?sslmode=enable")
m.Steps(2)
}
```
Want to use an existing database client?
```go
import (
"database/sql"
_ "github.com/lib/pq"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
func main() {
db, err := sql.Open("postgres", "postgres://localhost:5432/database?sslmode=enable")
driver, err := postgres.WithInstance(db, &postgres.Config{})
m, err := migrate.NewWithDatabaseInstance(
"file:///migrations",
"postgres", driver)
m.Up() // or m.Steps(2) if you want to explicitly set the number of migrations to run
}
```
## Getting started
Go to [getting started](GETTING_STARTED.md)
## Tutorials
* [CockroachDB](database/cockroachdb/TUTORIAL.md)
* [PostgreSQL](database/postgres/TUTORIAL.md)
(more tutorials to come)
## Migration files
Each migration has an up and down migration. [Why?](FAQ.md#why-two-separate-files-up-and-down-for-a-migration)
```bash
1481574547_create_users_table.up.sql
1481574547_create_users_table.down.sql
```
[Best practices: How to write migrations.](MIGRATIONS.md)
## Coming from another db migration tool?
Check out [migradaptor](https://github.com/musinit/migradaptor/).
*Note: migradaptor is not affiliated or supported by this project*
## Versions
Version | Supported? | Import | Notes
--------|------------|--------|------
**master** | :white_check_mark: | `import "github.com/golang-migrate/migrate/v4"` | New features and bug fixes arrive here first |
**v4** | :white_check_mark: | `import "github.com/golang-migrate/migrate/v4"` | Used for stable releases |
**v3** | :x: | `import "github.com/golang-migrate/migrate"` (with package manager) or `import "gopkg.in/golang-migrate/migrate.v3"` (not recommended) | **DO NOT USE** - No longer supported |
## Development and Contributing
Yes, please! [`Makefile`](Makefile) is your friend,
read the [development guide](CONTRIBUTING.md).
Also have a look at the [FAQ](FAQ.md).
**Version**: 1.2.0
**Language**: Go 1.23+
**Framework**: Gin
**Database**: PostgreSQL (GORM)
**License**: Apache 2.0
---
Looking for alternatives? [https://awesome-go.com/#database](https://awesome-go.com/#database).
## 📋 Table des Matières
1. [Vue d'ensemble](#vue-densemble)
2. [Installation](#installation)
3. [Configuration](#configuration)
4. [Architecture](#architecture)
5. [API Endpoints](#api-endpoints)
6. [Développement](#développement)
7. [Tests](#tests)
8. [Déploiement](#déploiement)
9. [Intégration avec autres services](#intégration-avec-autres-services)
---
## 🎯 Vue d'ensemble
**Veza Backend API** est le serveur HTTP principal de la plateforme Veza (audio collaborative). Il expose une API REST pour :
- **Authentification & Autorisation** : JWT, sessions, RBAC
- **Gestion Utilisateurs** : Profils, settings, completion
- **Gestion Tracks** : Upload, streaming, métadonnées, likes, partage
- **Playlists** : Création, collaboration, tracks
- **Marketplace** : Produits, commandes, téléchargements
- **Chat** : Génération de tokens JWT pour WebSocket (délégué au Chat Server Rust)
- **Audit & Monitoring** : Logs, métriques Prometheus, health checks
- **Webhooks** : Système d'événements asynchrones
**Rôle dans Veza** :
- **Backend Go** : API REST principale (port 8080)
- **Frontend React** : Consommateur de l'API REST
- **Chat Server Rust** : WebSocket (port 8081) — reçoit tokens JWT depuis `/api/v1/chat/token`
- **Stream Server Rust** : Streaming audio WebRTC (port 8082) — reçoit callbacks depuis `/api/v1/internal/tracks/:id/stream-ready`
---
## 🚀 Installation
### Prérequis
- **Go** 1.23 ou supérieur
- **PostgreSQL** 12+ (base de données principale)
- **Redis** (optionnel, pour cache et rate limiting)
- **ClamAV** (optionnel, pour scan antivirus des uploads)
- **RabbitMQ** (optionnel, pour event bus)
### Installation depuis les sources
```bash
# Cloner le repository
git clone <repository-url>
cd veza-backend-api
# Installer les dépendances
go mod download
# Build
make build
# Ou build pour Linux
make build-linux
```
### Installation via Docker
```bash
# Build image
make docker-build
# Run container
make docker-run
```
---
## ⚙️ Configuration
### Variables d'Environnement Requises
```bash
# REQUIS - Sécurité
JWT_SECRET=<32+ chars> # Secret JWT (minimum 32 caractères)
DATABASE_URL=postgres://user:pass@host:5432/dbname # URL PostgreSQL
APP_ENV=production # development|staging|production
# REQUIS en production
CORS_ALLOWED_ORIGINS=https://app.veza.com,https://www.veza.com # Origines CORS autorisées
# Optionnel - Base de données
DB_MAX_RETRIES=5 # Nombre de tentatives de connexion DB
DB_RETRY_INTERVAL=5s # Intervalle entre tentatives
# Optionnel - Redis
REDIS_URL=redis://localhost:6379 # URL Redis
REDIS_ENABLE=true # Activer/désactiver Redis
# Optionnel - RabbitMQ
RABBITMQ_URL=amqp://guest:guest@localhost:5672/ # URL RabbitMQ
RABBITMQ_ENABLE=true # Activer/désactiver RabbitMQ
RABBITMQ_MAX_RETRIES=3 # Tentatives de connexion
RABBITMQ_RETRY_INTERVAL=2s # Intervalle entre tentatives
# Optionnel - ClamAV
CLAMAV_REQUIRED=true # Rejeter uploads si ClamAV down (true) ou accepter en mode dégradé (false)
CLAMAV_ADDRESS=localhost:3310 # Adresse ClamAV
# Optionnel - Uploads
UPLOAD_DIR=uploads # Répertoire d'upload
MAX_CONCURRENT_UPLOADS=10 # Limite uploads simultanés (backpressure)
# Optionnel - Serveur
APP_PORT=8080 # Port HTTP (défaut: 8080)
HANDLER_TIMEOUT=30s # Timeout global handlers
# Optionnel - JWT
JWT_ISSUER=veza-api # Issuer claim
JWT_AUDIENCE=veza-app # Audience claim
CHAT_JWT_SECRET=<secret> # Secret pour tokens Chat (fallback: JWT_SECRET)
# Optionnel - Rate Limiting
RATE_LIMIT_LIMIT=100 # Limite requêtes
RATE_LIMIT_WINDOW=60 # Fenêtre en secondes
AUTH_RATE_LIMIT_LOGIN_ATTEMPTS=5 # Tentatives login max
AUTH_RATE_LIMIT_LOGIN_WINDOW=1 # Fenêtre login en minutes
# Optionnel - Sentry
SENTRY_DSN=https://... # DSN Sentry pour error tracking
SENTRY_ENVIRONMENT=production # Environnement Sentry
SENTRY_SAMPLE_RATE_ERRORS=1.0 # Sample rate erreurs (0.0-1.0)
SENTRY_SAMPLE_RATE_TRANSACTIONS=0.1 # Sample rate transactions (0.0-1.0)
# Optionnel - Logging
LOG_LEVEL=INFO # DEBUG|INFO|WARN|ERROR
# Optionnel - Services externes
STREAM_SERVER_URL=http://localhost:8082 # URL Stream Server
CHAT_SERVER_URL=http://localhost:8081 # URL Chat Server
```
### Fichiers de Configuration
- `.env` : Variables d'environnement (optionnel, chargé via `godotenv`)
- `.env.{APP_ENV}` : Variables spécifiques à l'environnement
- `migrations/*.sql` : Migrations SQL (exécutées au démarrage)
### Validation de Configuration
La configuration est validée au démarrage :
- **Production** : `CORS_ALLOWED_ORIGINS` est **REQUIS** (fail-fast si vide)
- **JWT_SECRET** : Minimum 32 caractères (fail-fast si trop court)
- **DATABASE_URL** : Requis pour tous les environnements
---
## 🏗️ Architecture
### Structure du Projet
```
veza-backend-api/
├── cmd/
│ └── api/
│ └── main.go # Point d'entrée
├── internal/
│ ├── api/ # Routes et configuration router
│ ├── core/ # Business logic (auth, track, marketplace, social)
│ │ ├── auth/ # Authentification
│ │ ├── track/ # Gestion tracks
│ │ ├── marketplace/ # Marketplace
│ │ └── social/ # Social features
│ ├── config/ # Configuration (env, validation, secrets)
│ ├── database/ # DB connection, migrations, pool
│ ├── handlers/ # HTTP handlers (legacy + modern)
│ ├── middleware/ # Auth, CORS, rate limiting, recovery, metrics
│ ├── models/ # GORM models (User, Track, Playlist, etc.)
│ ├── repositories/ # Data access layer (GORM)
│ ├── services/ # Business services (JWT, Session, Upload, etc.)
│ ├── workers/ # Background jobs (webhooks, analytics)
│ ├── metrics/ # Prometheus metrics
│ ├── monitoring/ # Business metrics (tracks_uploaded, users_registered)
│ ├── logging/ # Structured logging (zap)
│ └── validators/ # Input validation
├── migrations/ # Migrations SQL
├── tests/ # Tests d'intégration
├── docs/ # Documentation
└── Makefile # Commandes build/test
```
### Patterns
**Pattern Moderne** (recommandé) :
- Handlers dans `internal/core/*/handler.go`
- Services dans `internal/core/*/service.go`
- Utilisation de `context.Context` pour timeouts
- Gestion d'erreurs via `internal/errors`
**Pattern Legacy** (déprécié) :
- Handlers dans `internal/handlers/*.go`
- Migration progressive vers pattern moderne
### Dépendances Internes
- `internal/errors` : Error handling uniforme
- `internal/response` : Réponses HTTP standardisées
- `internal/common` : Types et utilitaires communs
### Dépendances Externes
- **PostgreSQL** : Base principale (GORM + `database/sql`)
- **Redis** : Cache, rate limiting, sessions (optionnel)
- **RabbitMQ** : Event bus (optionnel)
- **ClamAV** : Scan antivirus uploads (optionnel)
- **Sentry** : Error tracking (optionnel)
---
## 🌐 API Endpoints
### Base URL
```
http://localhost:8080/api/v1
```
### Routes Principales
#### Authentification (`/auth`)
```
POST /auth/register # Inscription
POST /auth/login # Connexion (rate limited)
POST /auth/refresh # Renouvellement token
POST /auth/verify-email # Vérification email
POST /auth/resend-verification # Renvoyer vérification
GET /auth/check-username # Vérifier disponibilité username
POST /auth/password/reset-request # Demande reset password
POST /auth/password/reset # Reset password
POST /auth/logout # Déconnexion (protégé)
GET /auth/me # Profil utilisateur (protégé)
```
#### Utilisateurs (`/users`)
```
GET /users/:id # Profil utilisateur
GET /users/by-username/:username # Profil par username
PUT /users/:id # Mise à jour profil (protégé, ownership)
GET /users/:id/completion # Complétion profil (protégé)
```
#### Tracks (`/tracks`)
```
GET /tracks # Liste tracks
GET /tracks/:id # Détails track
GET /tracks/:id/stats # Statistiques track
GET /tracks/:id/history # Historique track
GET /tracks/:id/download # Téléchargement track
GET /tracks/shared/:token # Track partagé (public)
POST /tracks # Upload track (protégé, creator role)
PUT /tracks/:id # Mise à jour track (protégé, ownership)
DELETE /tracks/:id # Suppression track (protégé, ownership)
POST /tracks/:id/like # Like track (protégé)
DELETE /tracks/:id/like # Unlike track (protégé)
GET /tracks/:id/likes # Liste likes (protégé)
POST /tracks/:id/share # Partager track (protégé)
DELETE /tracks/share/:id # Révoquer partage (protégé)
```
#### Playlists (`/playlists`)
```
GET /playlists # Liste playlists
GET /playlists/:id # Détails playlist
POST /playlists # Créer playlist (protégé)
PUT /playlists/:id # Mettre à jour playlist (protégé)
DELETE /playlists/:id # Supprimer playlist (protégé)
POST /playlists/:id/tracks # Ajouter track (protégé)
DELETE /playlists/:id/tracks/:track_id # Retirer track (protégé)
```
#### Marketplace (`/marketplace`)
```
GET /marketplace/products # Liste produits
POST /marketplace/products # Créer produit (protégé, creator role)
POST /marketplace/orders # Créer commande (protégé)
GET /marketplace/download/:product_id # URL téléchargement (protégé)
```
#### Chat (`/chat`)
```
POST /chat/token # Génération token WS (protégé)
```
#### Admin (`/admin`)
```
GET /admin/audit/logs # Logs audit (protégé, admin role)
GET /admin/audit/stats # Statistiques audit (protégé, admin role)
GET /admin/audit/suspicious # Activité suspecte (protégé, admin role)
GET /admin/debug/pprof/*path # Profiling pprof (protégé, admin role)
```
#### Health & Monitoring
```
GET /health # Health check simple
GET /healthz # Liveness probe (Kubernetes)
GET /readyz # Readiness probe (DB, Redis, RabbitMQ)
GET /status # Status détaillé (DB, Redis, Chat, Stream)
GET /metrics # Prometheus metrics
```
### Authentification
**JWT Bearer Token** :
```
Authorization: Bearer <token>
```
**JWT Claims** :
```json
{
"sub": "uuid-v4",
"iss": "veza-api",
"aud": "veza-app",
"exp": 1234567890,
"iat": 1234567890,
"token_version": 1,
"role": "user"
}
```
**Rôles** : `user`, `admin`, `creator`, `premium`, `artist`, `producer`, `label`
---
## 💻 Développement
### Commandes Build/Run
```bash
# Build
make build # Compile pour OS courant
make build-linux # Compile pour Linux
# Run
make run # Build + run
make dev # Mode développement (go run)
```
### Commandes Qualité
```bash
make lint # golangci-lint
make vet # go vet
make security # gosec + govulncheck
```
### Mode Développement
```bash
# Définir environnement
export APP_ENV=development
export LOG_LEVEL=DEBUG
# Lancer
make dev
```
---
## 🧪 Tests
### Tests Unitaires
```bash
make test # Tests unitaires (sans integration)
make test-coverage # Tests avec couverture
```
### Tests d'Intégration
```bash
make test-integration # Tests d'intégration (requiert Docker)
```
### Exécution Manuelle
```bash
# Tests unitaires
go test ./...
# Tests avec couverture
go test ./... -cover
# Tests d'intégration
go test ./tests/integration/... -tags=integration
```
---
## 🚢 Déploiement
### Docker
```bash
# Build image
docker build -t veza-backend-api .
# Run container
docker run -p 8080:8080 \
-e JWT_SECRET=<secret> \
-e DATABASE_URL=postgres://... \
-e APP_ENV=production \
-e CORS_ALLOWED_ORIGINS=https://app.veza.com \
veza-backend-api
```
### Kubernetes
Les health checks sont disponibles :
- `/healthz` : Liveness probe
- `/readyz` : Readiness probe
### Variables d'Environnement Production
**REQUIS** :
- `JWT_SECRET` (min 32 chars)
- `DATABASE_URL`
- `CORS_ALLOWED_ORIGINS` (fail-fast si vide en production)
- `APP_ENV=production`
**Recommandé** :
- `REDIS_ENABLE=true`
- `RABBITMQ_ENABLE=true`
- `CLAMAV_REQUIRED=true`
- `SENTRY_DSN` (pour error tracking)
---
## 🔗 Intégration avec autres services
### Frontend React
- Consomme `/api/v1/*` avec JWT Bearer tokens
- Headers requis: `Authorization: Bearer <token>`
- Content-Type: `application/json`
### Chat Server (Rust)
- Reçoit tokens JWT depuis `/api/v1/chat/token`
- Valide tokens avec `CHAT_JWT_SECRET` (ou `JWT_SECRET` si non défini)
- WebSocket endpoint: `ws://localhost:8081/ws`
### Stream Server (Rust)
- Reçoit callbacks depuis `/api/v1/internal/tracks/:id/stream-ready`
- Endpoint interne (pas de auth JWT, validation par IP/secret si nécessaire)
### Schéma DB / UUID
- **UUID v4** : Tous les IDs utilisent `uuid.UUID`
- Tables: `users`, `tracks`, `playlists`, `sessions`, `rooms`, `messages`, etc.
---
## 📊 Monitoring & Observabilité
### Métriques Prometheus
Exposées via `/metrics` :
- **HTTP** : `veza_http_requests_total`, `veza_http_request_duration_seconds`
- **Auth** : `veza_auth_login_attempts_total`, `veza_auth_sessions_active`
- **Database** : `veza_database_query_duration_seconds`, `veza_database_connections_active`
- **Business** : `veza_tracks_uploaded_total`, `veza_users_registered_total`, `veza_playlists_created_total`
- **Uploads** : `veza_file_uploads_total`, `veza_uploads_failed_total`
### Profiling
- **pprof** : `/api/v1/admin/debug/pprof/*path` (protégé par auth admin)
### Logs
- **Structured Logging** : Zap (JSON en production)
- **Request ID** : Corrélation des logs via `request_id`
- **Niveaux** : DEBUG, INFO, WARN, ERROR
---
## 🔒 Sécurité
### Validation
- **JWT Secret** : Minimum 32 caractères (fail-fast au démarrage)
- **CORS** : Strict en production (fail-fast si `CORS_ALLOWED_ORIGINS` vide)
- **Input Validation** : Tags `validate` sur tous les DTOs
- **Ownership Checks** : Middleware `RequireOwnershipOrAdmin` pour ressources sensibles
### Uploads
- **ClamAV** : Scan antivirus (configurable via `CLAMAV_REQUIRED`)
- **Backpressure** : Limite uploads simultanés (`MAX_CONCURRENT_UPLOADS`)
- **Validation** : Type MIME, taille, extension
### Rate Limiting
- **Global** : `RATE_LIMIT_LIMIT` requêtes par `RATE_LIMIT_WINDOW` secondes
- **Login** : `AUTH_RATE_LIMIT_LOGIN_ATTEMPTS` tentatives par `AUTH_RATE_LIMIT_LOGIN_WINDOW` minutes
---
## 📝 License
Apache 2.0
---
## 🤝 Support
- **Documentation API** : `/swagger/index.html` (Swagger UI)
- **Issues** : [GitHub Issues](https://github.com/veza/veza-backend-api/issues)