veza/veza-backend-api
senke 9002e91d91 refactor(backend,infra): unify SMTP env schema on canonical SMTP_* names
Third item of the v1.0.6 backlog. The v1.0.5.1 hotfix surfaced that two
email paths in-tree read *different* env vars for the same configuration:

    internal/email/sender.go         internal/services/email_service.go
    SMTP_USERNAME                    SMTP_USER
    SMTP_FROM                        FROM_EMAIL
    SMTP_FROM_NAME                   FROM_NAME

The hotfix worked around it by exporting both sets in `.env.template`.
This commit reconciles them onto a single schema so the workaround can
go away.

Changes
  * `internal/email/sender.go` is now the single loader. The canonical
    names (`SMTP_USERNAME`, `SMTP_FROM`, `SMTP_FROM_NAME`) are read
    first; the legacy names (`SMTP_USER`, `FROM_EMAIL`, `FROM_NAME`)
    stay supported as a migration fallback that logs a structured
    deprecation warning ("remove_in: v1.1.0"). Canonical always wins
    over deprecated — no silent precedence flip.
  * `NewSMTPEmailSender` callers keep working unchanged; a new
    `LoadSMTPConfigFromEnvWithLogger(*zap.Logger)` variant lets callers
    opt into the warning stream.
  * `internal/services/email_service.go` drops its six inline
    `os.Getenv` reads and delegates to the shared loader, so
    `AuthService.Register` and `RequestPasswordReset` now see exactly
    the same config as the async job worker.
  * `.env.template`: the duplicate (SMTP_USER + FROM_EMAIL + FROM_NAME)
    block added in v1.0.5.1 is removed — only the canonical SMTP_*
    names ship for new contributors.
  * `docker-compose.yml` (backend-api service): FROM_EMAIL / FROM_NAME
    renamed to SMTP_FROM / SMTP_FROM_NAME to match the canonical schema.
  * No Host/Port default injected in the loader. If SMTP_HOST is
    empty, callers see Host=="" and log-only (historic dev behavior).
    Dev defaults (MailHog localhost:1025) live in `.env.template`, so
    a fresh clone still works; a misconfigured prod pod fails loud
    instead of silently dialing localhost.

Tests
  * 5 new Go tests in `internal/email/smtp_env_test.go`: empty-env
    returns empty config; canonical names read directly; deprecated
    names fall back (one warning per var); canonical wins over
    deprecated silently; nil logger is allowed.
  * Existing `TestLoadSMTPConfigFromEnv`, `TestSMTPEmailSender_Send`,
    and every auth/services package remained green (40+ packages).

Import-cycle note: the loader deliberately lives in `internal/email`,
not `internal/config`, because `internal/config` already depends on
`internal/email` (wiring `EmailSender` at boot). Putting the loader in
`email` keeps the dependency flow one-way.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:44:09 +02:00
..
.github/workflows release(v0.903): Vault - ORDER BY whitelist, rate limiter, VERSION sync, chat-server cleanup, Go 1.24 2026-02-27 09:43:25 +01:00
cmd feat(workers): hourly cleanup of orphan tracks stuck in processing 2026-04-16 14:57:24 +02:00
docs fix(release): v1.0.1 — Conformité complète ROADMAP checklist 2026-03-03 20:17:54 +01:00
internal refactor(backend,infra): unify SMTP env schema on canonical SMTP_* names 2026-04-16 20:44:09 +02:00
migrations feat(backend,web): self-service creator role upgrade via /settings 2026-04-16 18:35:07 +02:00
ops/prometheus stabilizing veza-backend-api: phase 1 2025-12-16 11:23:49 -05:00
scripts fix(release): v1.0.2 — Conformité complète V1_SIGNOFF (21 critères) 2026-03-03 21:18:53 +01:00
templates/email feat(v0.10.5): Notifications Complètes (F551-F555) 2026-03-10 10:09:32 +01:00
tests style(backend): gofmt -w on 85 files (whitespace only) 2026-04-14 12:22:14 +02:00
veza_back_api_db stabilizing veza-backend-api: phase 1 2025-12-16 11:23:49 -05:00
.dockerignore report generation and future tasks selection 2025-12-08 19:57:54 +01:00
.env.production fix(v0.12.6): apply all pentest remediations — 36 findings across 36 files 2026-03-14 00:44:46 +01:00
.env.production.example stabilisation commit A 2026-01-07 19:39:21 +01:00
.env.template refactor(backend,infra): unify SMTP env schema on canonical SMTP_* names 2026-04-16 20:44:09 +02:00
.golangci.yml v0.9.4 2026-03-05 23:03:43 +01:00
CONTRIBUTING.md [DOC-007] doc: Write contributing guide 2025-12-25 11:06:54 +01:00
d_plus_all.txt lab DB: schema, migration et \d+ * 2025-12-04 18:00:13 +01:00
Dockerfile feat: backend, stream server & infra improvements 2026-03-18 11:36:06 +01:00
Dockerfile.production fix(build): unify Go version to 1.24 across Dockerfile and CI 2026-02-22 17:32:17 +01:00
go.mod fix(deps): bump x/net to v0.51.0 for GO-2026-4559 2026-04-15 15:31:35 +02:00
go.sum fix(deps): bump x/net to v0.51.0 for GO-2026-4559 2026-04-15 15:31:35 +02:00
LICENSE complete migration to full UUID - part A 2025-12-04 09:27:47 +01:00
Makefile refactor(backend): split seed tool into domain-specific modules 2026-03-25 23:35:07 +01:00
openapi.yaml feat(v0.12.8): documentation & API publique — rate limiting, scopes, OpenAPI 2026-03-12 18:44:09 +01:00
package.json v0.9.4 2026-03-05 23:03:43 +01:00
README.md fix(backend): use explicit DISABLE_RATE_LIMIT_FOR_TESTS flag instead of env-based bypass 2026-02-15 15:56:53 +01:00
test_output.txt refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
veza_uuid_lab_schema.sql lab DB: schema, migration et \d+ * 2025-12-04 18:00:13 +01:00

Veza Backend API

Version: 1.2.0
Language: Go 1.23+
Framework: Gin
Database: PostgreSQL (GORM)
License: Apache 2.0


📋 Table des Matières

  1. Vue d'ensemble
  2. Installation
  3. Configuration
  4. Architecture
  5. API Endpoints
  6. Développement
  7. Tests
  8. Déploiement
  9. 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

# 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

# Build image
make docker-build

# Run container
make docker-run

⚙️ Configuration

Variables d'Environnement Requises

# 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
STREAM_SERVER_INTERNAL_API_KEY=           # Clé partagée pour callbacks stream-ready (doit correspondre à INTERNAL_API_KEY du Stream Server)
CHAT_SERVER_URL=http://localhost:8081     # URL Chat Server

# DEV/TEST UNIQUEMENT - Ne jamais utiliser en production
# CSRF_DISABLED=true                       # Désactive CSRF (dev/test seulement)
# BYPASS_CONTENT_CREATOR_ROLE=true         # Bypass vérification rôle créateur (dev/test seulement)
# DISABLE_RATE_LIMIT_FOR_TESTS=true        # Désactive rate limiting (E2E/integration tests seulement)

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 :

{
  "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

# 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é

make lint               # golangci-lint
make vet                # go vet
make security           # gosec + govulncheck

Mode Développement

# Définir environnement
export APP_ENV=development
export LOG_LEVEL=DEBUG

# Lancer
make dev

🧪 Tests

Tests Unitaires

make test               # Tests unitaires (sans integration)
make test-coverage      # Tests avec couverture

Tests d'Intégration

make test-integration   # Tests d'intégration (requiert Docker)

Exécution Manuelle

# Tests unitaires
go test ./...

# Tests avec couverture
go test ./... -cover

# Tests d'intégration
go test ./tests/integration/... -tags=integration

🚢 Déploiement

Docker

# 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

Rate limiting est toujours actif (A04). Limites par défaut selon l'environnement :

Environnement Global (req/min) Register (inscriptions/heure)
development, test 1000 20
staging, production 200 3
  • Global : RATE_LIMIT_LIMIT requêtes par RATE_LIMIT_WINDOW secondes (override possible)
  • 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