|
Some checks failed
Veza CI / Rust (Stream Server) (push) Successful in 4m22s
Security Scan / Secret Scanning (gitleaks) (push) Successful in 1m5s
Veza CI / Frontend (Web) (push) Failing after 17m19s
E2E Playwright / e2e (full) (push) Failing after 20m28s
Veza CI / Backend (Go) (push) Successful in 21m31s
Veza CI / Notify on failure (push) Successful in 4s
Three pre-existing infra issues surfaced by the Day 1→Day 3 push wave.
Each is independent — bundled here because the goal is "ci.yml + e2e.yml
green" before the v1.0.9 tag, and they're all small.
(1) gofmt — ci.yml golangci-lint v2 step
Five files were unformatted on main. Pre-existing (untouched by my
Item G work, but the formatter caught them now):
- internal/api/router.go
- internal/core/marketplace/reconcile_hyperswitch_test.go
- internal/models/user.go
- internal/monitoring/ledger_metrics.go
- internal/monitoring/ledger_metrics_test.go
Pure whitespace via `gofmt -w` — no behavior change.
(2) e2e silent-fail — playwright webServer port collision
The e2e workflow pre-starts the backend in step 9 ("Build + start
backend API") so it can fail-fast on a non-ok health check. But
playwright.config.ts had `reuseExistingServer: !process.env.CI` on
the backend webServer entry — meaning in CI Playwright tried to
spawn a SECOND backend on port 18080. The spawn collided with
EADDRINUSE and Playwright silently exited before printing any test
output. The artifact upload then warned "No files were found"
because tests/e2e/playwright-report/ never got written, and the job
ended in `Failure` for an unrelated reason (the artifact upload
step's GHESNotSupportedError).
Fix: backend `reuseExistingServer: true` always — workflow + dev
both pre-start backend on 18080. Vite stays `!CI` because the
workflow doesn't pre-start it. Comment in playwright.config.ts
documents the symptom so the next person debugging gets the
pointer immediately.
(3) orders.hyperswitch_payment_id missing in fresh DBs — migration 080
skip-branch + 099 ordering drift
Migration 080 (`add_payment_fields`) wraps its ALTERs in
"skip if orders doesn't exist". At authoring time orders existed
earlier in the migration sequence; that ordering has since shifted
(orders is now created at 099_z_create_orders.sql, AFTER 080).
Result: in any freshly-migrated DB (CI, fresh dev, future restore
drills) migration 080 takes the skip branch and the columns are
never added — even though the Order model and the marketplace code
rely on them.
Symptom: every CI run logs
pq: column "hyperswitch_payment_id" does not exist
from the periodic ledger_metrics worker. Order checkout would also
fail to persist payment_id at write time, breaking reconciliation.
Fix: append-only migration 987 with idempotent
`ADD COLUMN IF NOT EXISTS` + a partial index on the reconciliation
hot path. Production envs that did pick up 080 in the original
order are no-ops; fresh envs converge to the same end state.
Rollback in migrations/rollback/.
Verified locally:
$ cd veza-backend-api && go build ./... && VEZA_SKIP_INTEGRATION=1 \
go test -short -count=1 ./internal/...
(all green)
SKIP_TESTS=1: backend-only Go + Playwright config + SQL. Frontend
unit tests irrelevant to this commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| .github/workflows | ||
| cmd | ||
| docs | ||
| internal | ||
| migrations | ||
| ops/prometheus | ||
| scripts | ||
| templates/email | ||
| tests | ||
| veza_back_api_db | ||
| .dockerignore | ||
| .env.production | ||
| .env.production.example | ||
| .env.template | ||
| .golangci.yml | ||
| CONTRIBUTING.md | ||
| d_plus_all.txt | ||
| Dockerfile | ||
| Dockerfile.production | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| openapi.yaml | ||
| package.json | ||
| README.md | ||
| test_output.txt | ||
| veza_uuid_lab_schema.sql | ||
Veza Backend API
Version: 1.2.0
Language: Go 1.23+
Framework: Gin
Database: PostgreSQL (GORM)
License: Apache 2.0
📋 Table des Matières
- Vue d'ensemble
- Installation
- Configuration
- Architecture
- API Endpoints
- Développement
- Tests
- Déploiement
- 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é viagodotenv).env.{APP_ENV}: Variables spécifiques à l'environnementmigrations/*.sql: Migrations SQL (exécutées au démarrage)
Validation de Configuration
La configuration est validée au démarrage :
- Production :
CORS_ALLOWED_ORIGINSest 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.Contextpour 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 uniformeinternal/response: Réponses HTTP standardiséesinternal/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_URLCORS_ALLOWED_ORIGINS(fail-fast si vide en production)APP_ENV=production
Recommandé :
REDIS_ENABLE=trueRABBITMQ_ENABLE=trueCLAMAV_REQUIRED=trueSENTRY_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(ouJWT_SECRETsi 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_ORIGINSvide) - Input Validation : Tags
validatesur tous les DTOs - Ownership Checks : Middleware
RequireOwnershipOrAdminpour 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_LIMITrequêtes parRATE_LIMIT_WINDOWsecondes (override possible) - Login :
AUTH_RATE_LIMIT_LOGIN_ATTEMPTStentatives parAUTH_RATE_LIMIT_LOGIN_WINDOWminutes
📝 License
Apache 2.0
🤝 Support
- Documentation API :
/swagger/index.html(Swagger UI) - Issues : GitHub Issues