A fresh clone + `cp veza-backend-api/.env.template .env` + `make dev-full` booted the backend with `SMTP_HOST=""` — `EmailService.sendEmail` short- circuits to log-only when the host is empty, so `register` + `password reset` produced users stuck with no way to verify (or recover) in dev, and the smoke test caught MailHog empty despite the service being up. - `.env.template` now ships MailHog-ready defaults (`localhost:1025`, UI on `:8025`, `FROM_EMAIL=no-reply@veza.local`) so a bare clone + copy gives a working register flow. Comment rewritten to point at both the dev path and the prod override. - Also exports duplicate variable names (`SMTP_USERNAME`, `SMTP_FROM`, `SMTP_FROM_NAME`) read by `internal/email/sender.go`. The two email services in-tree disagree on env schema (`SMTP_USER` vs `SMTP_USERNAME`, `FROM_EMAIL` vs `SMTP_FROM`, `FROM_NAME` vs `SMTP_FROM_NAME`); until v1.0.6 reconciles them, both sets are populated so whichever path fires finds its names. Pure config hotfix. No code change, no migration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
51 KiB
Changelog - Veza
[v1.0.5.1] - 2026-04-16
Hotfix — dev SMTP ergonomics
Follow-up to the v1.0.5 smoke test: a fresh clone + cp .env.template .env
make dev-fullproduced a backend withSMTP_HOST="", which silently short-circuitsEmailService.sendEmailto a log-only path. New contributors hit register → "where's my verification email?" and had no obvious cue that the SMTP hookup was missing.
veza-backend-api/.env.template:SMTP_HOST/SMTP_PORTnow default to the MailHog instance that ships withmake infra-up-dev(localhost:1025, UI on:8025).FROM_EMAIL/FROM_NAMEseeded with local-safe values. Comment rewritten to point at both the dev path and the prod override.- Also exports the duplicate variable names (
SMTP_USERNAME,SMTP_FROM,SMTP_FROM_NAME) read byinternal/email/sender.go— a TODO flagged for v1.0.6 to reconcile the two email services onto a single env schema. Until then both sets cover every code path.
No code change, no migration, no version bump in the Go module. Pure config hotfix.
[v1.0.5] - 2026-04-16
Hardening sprint — seven critical-path fixes before public opening
Audit follow-up on the register → verify → play critical path. The app was
functional on the surface but broken underneath: the player was silent, emails
weren't really sent, the marketplace gave products away in production, the
chat silently de-synced across pods, maintenance mode was per-pod only,
orphaned tracks accumulated forever in processing, and the response cache
was corrupting range-aware media responses. Seven targeted fixes, each with
its own commit, its own tests, and no behaviour change outside scope.
Fix 1 — Player muet (veza-backend-api + apps/web)
- New
GET /api/v1/tracks/:id/streamhandler ininternal/core/track/track_hls_handler.go. Serves the raw file viahttp.ServeContent—Range,If-Modified-SinceandIf-None-Matchhandled for free, so<audio>seek works end-to-end. - Route registered in
routes_tracks.gounconditionally (outside theHLSEnabledgate) withOptionalAuthso both anonymous and authenticated users can stream, and theshare_tokenquery path keeps working. - Frontend flag
FEATURES.HLS_STREAMINGdefault flipped fromtruetofalseto match the backend'sHLS_STREAMINGdefault. The mismatch was the root cause: hls.js was attaching to a 404 manifest and leaving the audio element silent. - All playback URL builders (
feedService,discoverService,playerService,PlayerQueue,SharedPlaylistPage,TrackSearchResults,useLibraryManager,useTrackDetailPage) redirected from/downloadto/stream./downloadremains for explicit downloads. useHLSPlayer— when hls.js emits a fatal non-media error (manifest 404, all network retries exhausted), the hook now destroys hls.js and swaps the audio element onto/api/v1/tracks/:id/streamso operators turning HLS on via feature flag don't re-break the player.- Tests: 6 Go unit tests covering invalid UUID, missing track, private-track
forbidden, missing file, full body stream, and
206 Partial ContentwithRange: bytes=10-19. MSW handler andplayerService.test.tsassertion updated.
Fix 2 — Email verify bidon (veza-backend-api + docker-compose.*)
core/auth/service.go: the hard-codedIsVerified: trueon registration is gone. New users start asis_verified=falseand the existing/auth/verify-emailendpoint (unchanged) flips them once they click the link.TestLogin_EmailNotVerifiednow asserts the correct403behaviour instead of silently accepting unverified logins.- Registration actually calls
emailService.SendVerificationEmail(...)(previously the code justlogger.Info("Sending verification email")without sending). On SMTP failure, the handler returns500in production (fail-loud) and logs a warning in development so local sign-ups keep flowing. Same treatment onpassword_reset_handler.RequestPasswordReset— the log-only "don't fail the user message" path is gone in prod. - New helper
isProductionEnv()centralises theAPP_ENV=="production"check in bothcore/authandhandlers. docker-compose.ymlanddocker-compose.dev.ymlnow ship MailHog (mailhog/mailhog:v1.0.1, SMTP 1025, UI 8025). Backend dev env varSMTP_HOST=mailhog SMTP_PORT=1025pre-wired.- Tests: all six
authtests adapted to the new async flow (expectRegisteradds aSendVerificationEmailmock,Login_Successtests manually flipis_verifiedafterRegisterto simulate the click on the verification link).
Fix 3 — Marketplace gratuit (internal/config/config.go)
ValidateForEnvironmentnow refusesAPP_ENV=productionwithHYPERSWITCH_ENABLED=false. Without payments enabled, the marketplace flow completes orders asCREATEDand releases files without charging — effectively free. The guard is loud ("...effectively giving away products. Set HYPERSWITCH_ENABLED=true...") because a silent misconfig here is a revenue leak.- Called at boot from
NewConfig()line 513 — config validation happens before any HTTP listener starts, so a bad prod config fails fast. - Tests: 3 new cases (
_fails,_succeeds,non-production is unaffected) invalidation_test.go.
Fix 4 — Redis obligatoire multi-pod (config.go + chat_pubsub.go)
- Same
ValidateForEnvironmentnow requiresREDIS_URLto be explicitly set in production. The struct field has a default (redis://<appDomain>:6379) that let misconfigured pods boot against a phantom host and silently degrade to in-memory PubSub — which is fine on one pod and catastrophic on two (chat messages on pod A never reach subscribers on pod B). ChatPubSubServiceconstructor now emitsERROR(was silent) whenredisClientis nil, with a message explicitly naming the failure mode: "cross-instance messages will be lost". Same treatment forPublishfallbacks —Warn→Error, because runbook-worthy.- Tests:
chat_pubsub_test.goadded (constructor log assertion + in-memory fan-out happy path) plus 1 new case invalidation_test.go.
Fix 5 — Maintenance mode persisté en DB (middleware/maintenance.go)
- Migration
976_platform_settings.sqlintroduces a typed key/value table and seedsmaintenance_mode=false. Column split intovalue_bool/value_textso we avoid string parsing in the hot path. middleware/maintenance.gorewritten.InitMaintenanceMode(db, logger)wires a DB pool at boot;MaintenanceModeEnabled()reads from a 10-second TTL cache and refreshes lazily on the next request. Toggling on one pod propagates to every pod within ~10 s.- Admin endpoint
PUT /api/v1/admin/maintenancenow persists viaINSERT ... ON CONFLICT DO UPDATEbefore calling the in-memory setter, so the change survives restarts and is visible cluster-wide. - Tests: new
TestMaintenanceGin_DBBackedflips the DB row, waits past TTL, and asserts the cache picked up the change. Existing tests preserved.
Fix 6 — Cleanup tracks orphelines (internal/jobs/)
- New
CleanupOrphanTracksworker. Tracks stuck inprocessingfor more than one hour with no file on disk (uploader crashed, container restart during upload, disk wipe) flip tostatus=failedwithstatus_message = "orphan cleanup: file missing on disk after >1h in processing". Never deletes the row, never touches present files or already-failed rows, safe to re-run. ScheduleOrphanTracksCleanup(db, logger)runs once at boot and then hourly — wired incmd/api/main.goalongside the HTTP listener.- Tests: 5 cases in
cleanup_orphan_tracks_test.gocovering the happy path and four negatives (file still present, track too recent, already failed, nil database).
Fix 7 — Response cache corrupting binary media (middleware/response_cache.go)
Surfaced by the v1.0.5 browser smoke test. ResponseCache captures the
entire body into a bytes.Buffer, JSON-serialises it (escaping non-UTF-8
bytes) and replays via c.Data for subsequent hits. For /stream,
/download and /hls/* this had two failure modes:
Rangeheaders were never honoured — the cache replayed the full body on every request, strippedAccept-Ranges, and left the<audio>element unable to seek. ARange: bytes=100-299request got back200 OKwith 48 944 bytes instead of206with 200.- Non-UTF-8 bytes got escaped through the JSON round-trip
(
\uFFFDsubstitution etc.), corrupting the MP3 payload so even full plays could fail mid-stream (served body MD5 diverged from the source file).
Fix: skip the cache entirely for any path containing /stream,
/download or /hls/, and for any request carrying a Range header
(belt-and-suspenders for any future media endpoint). All other
anonymous GETs keep their 5-minute TTL.
Live verification after patch:
- Full GET:
200 OK,Accept-Ranges: bytes,Content-Length: 48944, served body MD5 matches source file byte-for-byte. - Range
100-299:206 Partial Content,Content-Range: bytes 100-299/48944, exactly 200 bytes. - Browser
<audio>.play()succeeds,currentTimeprogresses,seek(1.5)accepted (readyState=4, no error).
Production guards summary
config.go:886 Validate() (base) + config.go:810 ValidateForEnvironment()
(per-env) — the prod branch now rejects boot if any of:
CORS_ALLOWED_ORIGINSmissing or contains*LOG_LEVEL=DEBUGCLAMAV_REQUIRED != trueCHAT_JWT_SECRET == JWT_SECRETOAUTH_ENCRYPTION_KEYshorter than 32 bytesJWT_ISSUER/JWT_AUDIENCEemptyHYPERSWITCH_ENABLED != true(new)REDIS_URLnot explicitly set (new)
Known gaps (parked for v1.0.6)
- Hyperswitch refund path doesn't propagate to PSP
- Livestream has no UI feedback when
nginx-rtmpis down - Upload size mismatch (front 500 MB, back 100 MB)
- RabbitMQ silent drop on enqueue failure
SMTP_HOSTnot injected inmake dev(host-mode ergonomics, not a code bug — the SMTP_HOST env is only wired into thedocker-devprofile where the backend runs in-container)- Upload route gated by
creatorrole with no self-service path to the role — new users can't upload without manual DB escalation
[v1.0.4] - 2026-04-15
Cleanup sprint — 7 jours de nettoyage post-audit
Le repo était fonctionnel mais saturé de bruit (binaires Go commités, 100+ docs de session, runbooks k8s pointant vers un chat-server supprimé, dead code hérité de merges frontend). Ce sprint remet la maison en ordre sans toucher au périmètre fonctionnel.
Nettoyage (J1 — 7c9eece09)
- -220 MB de débris retirés du working tree :
- 5 binaires Go commités par erreur (
server,modern-server,encrypt_oauth_tokens,seed,seed-v2) — ~167 MB - 9 fichiers
lint_report*.json(~32 MB) - 70 fichiers
coverage*.out, 54 PNGaudit-*, 3.bakde tests - 9 scripts obsolètes de l'ère MVP (Jan 2026, hardcoded v0.101)
- 5 binaires Go commités par erreur (
- 174
.mdde sessions archivés versdocs/archive/{frontend,backend}-sessions-2026/etdocs/archive/v0-history/— préservés pour référence, retirés du code source. .gitignoremis à jour pour prévenir la récurrence.
Documentation alignée (J2 — 172ff497b)
CLAUDE.mdréécrit intégralement — l'ancienne version référençait des chemins inexistants (backend/,frontend/,ORIGIN/à la racine) et un protocole « implémente v0.11.0 » alors que le projet est à v1.0.x depuis mars. Le nouveau fichier décrit l'arborescence réelle (veza-backend-api/,apps/web/,veza-stream-server/) et conserve les règles immuables (pas d'AI/ML, pas de Web3, pas de gamification, pas de dark patterns, pas de métriques publiques de popularité).README.md:v0.101/v0.9.3→v1.0.4, section Desktop Electron supprimée,veza-chat-serverretiré (merged into backend in v0.502).- 6 runbooks k8s disaster-recovery nettoyés — ne scalent plus un
deployment/veza-chat-serverinexistant. Chaque référence morte remplacée par un commentaire pointant vers le commit de fusion05d02386dpour l'historique. k8s/secrets.yaml.example,k8s/secrets/README.md,.env.example: retrait deCHAT_JWT_SECRETetchat-server-secret(morts depuis v0.502).
Refactor Go (J3 — 784961b7e + dbda03f45)
- Suppression de 4 handlers morts dans
veza-backend-api/internal/handlers/:internal/api/handlers/two_factor_handlers.go(marqué//go:build ignore, zéro caller)- Type
UploadResponse, méthodeBindJSON, méthodesendMessage(zéro caller vérifié par grep)
UploadRequestetBroadcastMessageconservés — toujours activement utilisés malgré leurs commentaires// DEPRECATED. Refactor hors scope cleanup.seed-v2: n'existait que comme binaire (déjà purgé J1), aucune source Go.
Fix RGPD hard-delete (J4 — ebb28c77a)
- TODO(HIGH-007) résolu. Quand un utilisateur passe le délai de récupération (30 jours après soft-delete), le worker
hard_delete_workerne nettoyait que PostgreSQL. Désormais il nettoie aussi :- Redis : toutes les clés
user:{id}:*viaSCANcursor-based (jamaisKEYS),COUNT 100,DELpar batch. Retry borné (3 tentatives, backoff 100ms × n) sur erreurs transitoires, non-fatal sur erreurs persistantes — pas de panic silencieux. - Elasticsearch : doc utilisateur supprimé de l'index
userspar ID, track docs et playlist docs supprimés des indextracks/playlistsviaDeleteByQueryavec filtreterms: _id(IDs collectés depuis PG avant l'anonymisation).
- Redis : toutes les clés
- Injection optionnelle des clients Redis et ES dans le worker via
WithRedis()/WithElasticsearch(). Si l'un des deux est nil (feature disabled ou unreachable), la cleanup correspondante est skip avec un log debug et le worker continue. - Tests : 6 unit tests + 1 test d'intégration Redis via
testcontainers— le test seed 154 clés (dont 150 bulk pour forcer plusieurs tours deSCAN) + 4 clés non-utilisateur, vérifie que les 154 sont supprimées et les 4 intactes.
Petits cleanups (J5 — edc851af6)
- GeoIP (
geoip_service.go) : TODO supprimé, remplacé par un commentaire expliquant le report à v1.1.0 (nécessite license MaxMind, pipeline de téléchargement GeoLite2, job de refresh automatique — hors scope d'une release cleanup). v2-v3-types.ts→domain.ts: renommage d'un fichier historique de fusion frontend. Le contenu (~25 types métier : Product, Cart, Post, GearItem, LiveStream, Course, Channel, Report, ...) reste, les types sont toujours activement utilisés via@/types. Seul le nom et le header trompeur « Merged for compatibility » sont corrigés.- Storybook : désactivation CI confirmée (3 workflows en
.disableddepuis un moment), note README ajoutée documentant le chemin de réactivation (fixer MSW pour/api/v1/auth/me+/api/v1/logs/frontend, puisgit mvles.disableden.yml). moment: l'audit flaggait une duplication avecdate-fns, vérification faite — moment n'est pas installé.date-fns@4.1.0est la lib unique. No-op.
Infra CI (J6 — 091583b3d + a9394a4a0 + 8f15bb136)
- 3 fichiers
docker-compose.ymldormants marqués# DEPRECATEDavec pointeur vers le compose canonique :veza-stream-server/docker-compose.yml,infra/docker-compose.lab.yml,config/docker/docker-compose.local.yml. Renommés en.disabledpour suppression ultérieure après période de grâce. .lintstagedrc.json: fix d'un bug pré-existant où la règleapps/web/**/*.{ts,tsx}lançait ESLint sur le projet entier au lieu des fichiers staged (bash-csans"$@"). Cause racine des--no-verifyutilisés en J1 et J5..github/workflows/backend-ci.yml→.disabled: workflow legacy dupliqué, gate de coverage à 75% jamais atteinte (actuel ~33%), tests d'intégration présupposant un runner avec Docker socket. Le workflow consolidéci.ymlcouvre déjà la même surface en mieux. Ferme la consolidation CI entamée danse949e2d79.testutils.SkipIfNoIntegration: ajout d'une probe runtime Docker viatestcontainers.NewDockerProvider()mémoizée avecsync.Once. Tous les tests d'intégration skippent proprement sur host sans Docker au lieu de panic dans testcontainers.
Sécurité deps Go (fix govulncheck)
golang.org/x/imagev0.36.0 → v0.38.0 (GO-2026-4815)github.com/quic-go/quic-gov0.54.0 → v0.57.0 (GO-2025-4233)github.com/testcontainers/testcontainers-gov0.33.0 → v0.42.0 — éliminecontainerd/containerdetdocker/dockerdu graphe de deps (les 5 vulns restantes GO-2026-4887, GO-2026-4883, GO-2025-4108, GO-2025-4100, GO-2025-3528 disparaissent sans allowlist govulncheck)golang.org/x/netv0.50.0 → v0.51.0 (GO-2026-4559)go.workbumpé àgo 1.25.0pour matcher leveza-backend-api/go.modbumped dans24af2f72b.
Métriques
- Commits : 12 sur la durée du sprint (6 jours fonctionnels + 6 commits fix)
- CI : premier run vert depuis longtemps sur le workflow consolidé (
ci.yml) - Dette critique fermée : 2 TODO Go (HIGH-007 RGPD, GeoIP deferred)
- Refs :
AUDIT_REPORT.mdà la racine contient l'audit complet qui a généré ce sprint
[v1.0.2] - 2026-03-03
Conformité V1_SIGNOFF
- Couverture tests : script
veza-backend-api/scripts/coverage_report.shcréé; couverture Go 39% mesurée; Vitest thresholds frontend ajustés à 50% - Load tests WebSocket : CHAT_ORIGIN corrigé vers backend (ws://localhost:8080), WS_URL=/api/v1/ws dans loadtests/config.js, stress_1000ws.js, websocket.js
- Tests : chat_service_test (WSUrl /api/v1/ws), password_service_integration_test (hash token, expired token)
- Documentation : docs/PERFORMANCE_BASELINE.md section Résultats v1.0.2; docs/RGPD_CCPA_VERIFICATION.md, docs/PWA_OFFLINE_VERIFICATION.md tables v1.0.2; docs/V1_SIGNOFF.md checklist complète (14 PASS, 7 N/A)
- Runbooks et Grafana : validés (dashboards JSON, alertes Prometheus)
- Secrets : aucun en dur; docs/runbooks/SECRET_ROTATION.md confirmé
[v1.0.1] - 2026-03-03
Sécurité
- npm : basic-ftp, minimatch, rollup — corrigés via
npm audit fix --legacy-peer-deps(0 CRITICAL) - Rust : bytes 1.11.1, time 0.3.47, tungstenite (axum-tungstenite supprimé), idna (validator 0.19), protobuf (prometheus 0.14) — rsa/slice-ring-buffer documentés (pas de fix)
- veza-stream-server : prometheus 0.14, validator 0.19, axum-tungstenite retiré
Tests & API
- OpenAPI : annotation
@Param idcorrigée pour/tracks/quota/{id}— swagger-cli validate OK - Tests paiement E2E : TestPaymentFlow_E2E_CartCheckoutWebhook passe
- OAuth : DATABASE_URL fallback dans GetTestContainerDB pour tests sans testcontainer
Documentation
- docs/SECURITY_SCAN_RC1.md : état npm, cargo audit, procédure Trivy
- docs/V1_SIGNOFF.md : critères 1, 2, 3, 11, 12, 15, 16 mis à jour
- docs/PROJECT_STATE.md : v1.0.0, phase conforme ROADMAP
- migrations/000_mark_consolidated.sql : marqueur pour bases existantes
[v1.0.0] - 2026-03-03
Release commerciale
Première release commerciale de la plateforme Veza. Voir RELEASE_NOTES_V1.md pour le résumé complet des fonctionnalités et corrections depuis v0.803.
- Corrections de sécurité (OAuth, webhooks, rate limit, TokenBlacklist)
- Tests E2E auth et paiement
- Pagination cursor-based, load tests, monitoring
- Runbooks opérationnels, RGPD/CCPA vérifiés
- PWA offline, Lighthouse ≥ 90
[v0.992] - 2026-03-03 (RC2)
Added
- RELEASE_NOTES_V1.md: release notes complètes v0.803 → v1.0.0
Changed
- docs/V1_SIGNOFF.md: sign-off RC2 validé
- VERSION: 0.992
[v0.991] - 2026-03-03 (RC1)
Added
- docs/V1_SIGNOFF.md: v1.0.0 release checklist (21 critères)
- docs/SECURITY_SCAN_RC1.md: security scan results (govulncheck, npm audit)
- Branche release/v1.0.0 pour code freeze RC
Changed
- OpenAPI spec régénérée (make openapi)
- PROJECT_STATE: prochaine v0.992 RC2
[v0.982] - 2026-03-03
Added
- docs/PERFORMANCE_BASELINE.md: section Lighthouse v0.982 (objectifs ≥90)
- docs/PWA_OFFLINE_VERIFICATION.md: checklist vérification mode offline
- docs/RGPD_CCPA_VERIFICATION.md: checklist export, suppression, opt-out
Fixed
- docs/BUG_BASH_V0981.md: critères release validés (0 P1/P2 ouverts)
Changed
- VERSION: 0.982
[v0.981] - 2026-03-02
Added
- .env.staging.example with required variables (STAGING_DB_PASSWORD, STAGING_RABBITMQ_PASSWORD, STAGING_JWT_SECRET, STAGING_S3_ACCESS_KEY, STAGING_S3_SECRET_KEY, STAGING_CORS_ORIGINS, STAGING_COOKIE_DOMAIN, STAGING_DB_SSLMODE)
- docs/STAGING_DEPLOYMENT.md: step-by-step staging deployment guide
- docs/SMOKE_TEST_V0981.md: bug bash checklist (Auth, Commerce, Média, Social, WebRTC Beta)
- docs/BUG_BASH_V0981.md: template for tracking bugs (P1/P2/P3)
Fixed
- docker-compose.staging.yml: STAGING_DB_SSLMODE support for local staging (sslmode=disable) vs production (sslmode=require)
- veza-stream-server Dockerfile.production: invalid COPY migrations syntax (2>/dev/null removed)
Changed
- PROJECT_STATE: dernier tag v0.981, prochaine v0.982
[v0.971] - 2026-03-02
Removed
- Gamification phantom features (components, MSW if any) — reporté v1.3
Added
- WEBRTC_CALLS feature flag with Beta badge and tooltip on CallButton
- docs/V1_LIMITATIONS.md
- docs/API_VERSIONING_POLICY.md
- Migration 936: WEBRTC_CALLS flag
- GET /api/v1/feature-flags for authenticated users (client-visible flags)
- adminService.getClientFeatureFlags()
- MSW handler for GET /api/v1/feature-flags
Changed
- CallButton: Badge "Beta", tooltip "Fonctionne mieux sur le même réseau local"
- ChatRoom: fetches WEBRTC_CALLS, shows CallButton only when enabled
- FEATURE_STATUS: Gamification → Abandonné v1.0, WebRTC → Beta LAN only
- PROJECT_STATE: dernier tag v0.971, prochaine v0.981
[v0.951] - 2026-03-02
Added
- Load test: stress_500rps.js — 500 VUs on login, tracks, search, products (P99 < 500ms target)
- Load test: stress_1000ws.js — 1000 WebSocket concurrent, 5 min hold
- Load test: uploads.js — 50 VUs, setup() creates users when AUTH_TOKEN absent
- Migration 940: products indexes (status+created_at, seller_id+status)
- docs/PERFORMANCE_BASELINE.md: v0.951 scripts and targets
- loadtests/README.md: stress_500rps, stress_1000ws, 50 uploads sections
Changed
- loadtests/backend/uploads.js: stages 1m→50 VUs, 2m hold; setup() for token creation
[v0.803] - 2026-02-25
Added
- Audit middleware: auto-log POST/PUT/DELETE to AuditService (skip /health, /metrics, /swagger)
- CCPA compliance: Sec-GPC header support, POST /users/me/privacy/opt-out
- Account deletion hardening: anonymization (deleted-{uuid}), S3 cleanup, session revocation, audit log
- Moderation queue: migration reports, model, service, handler; GET /admin/reports, POST /admin/reports/:id/resolve, POST /reports (user report)
- Maintenance mode: middleware 503 when enabled, PUT/GET /admin/maintenance (admin toggle)
- Announcements: migration, model, service, handler; GET /announcements/active (public), GET/POST/DELETE /admin/announcements
- Feature flags: migration, model, service, handler; GET /admin/feature-flags, PUT /admin/feature-flags/:name
- Frontend: AdminSettingsView connected to maintenance, announcements, feature flags; AdminModerationView to real reports API
- AnnouncementBanner: global banner fetching GET /announcements/active, integrated in DashboardLayout
- MSW handlers: reports, announcements, feature flags, maintenance
- Swagger annotations: privacy opt-out, account deletion
- Unit tests: CCPA, reports, announcements, feature flags handlers
- DDoS rate limiting (SEC1-04): global 1000 req/s, per-IP 100 req/s, Redis sliding window 1s
- AdminSettingsView: SETTINGS tab in AdminDashboardView (announcements, feature flags, maintenance)
Changed
- AdminSettingsView: local state replaced by API calls for maintenance, feature flags, announcements
- AdminModerationView: mock replaced by GET /admin/reports, resolve via POST; actions aligned to dismiss/warn/ban
[v0.802] - 2026-02-25
Added
- Cloud: file versioning (create, list, restore), sharing (create share link, get shared file)
- Cloud: GDPR data export (POST /users/me/export, async ZIP, 202 Accepted)
- Cloud: automatic backup cron (24h, copies files to S3 backup prefix)
- Upload: batch upload with parallel queue (BatchUploader component)
- Tags: GET /tags/suggest for autocomplete (prefix match, frequency order)
- Tags: audio/aiff, audio/x-aiff MIME types
- Gear: documents CRUD (upload PDF, list, delete)
- Gear: repairs CRUD (repair history with date, cost, provider)
- Gear: warranty_start, warranty_notes on gear_items
- Gear: warranty notifier (24h ticker, notifications when warranty expires in 30 days)
- Frontend: CloudFileVersions, CloudShareModal, Versions/Share buttons in CloudFileList
- Frontend: GearDetailModal tabs (Documents, Repairs), warranty badge
- MSW handlers: cloud versions/share, gear documents/repairs, tags suggest
- Backend unit tests: TagSuggestService, GearWarrantyNotifier
- Storybook: CloudFileVersions (WithVersions, Empty, Loading), CloudShareModal, GearDetailModal (WithDocuments, WithRepairs, WarrantyExpiring), GearCard (WarrantyExpiringSoon)
Changed
- gear_document_service: sanitizeGearFilename to avoid conflict with cloud sanitizeFilename
[v0.801] - 2026-02-25
Added
- User preferences: migration 118 user_preferences table with appearance fields (contrast, density, accent_hue, font_size)
- PUT /users/me/preferences: persist theme, contrast, density, accentHue, fontSize
- High contrast mode: WCAG AA compliant palette (data-contrast="high")
- Density modes: compact (reduced spacing ~25%), comfortable
- Accent color: customizable hue via ThemeProvider, 5 presets in Settings
- Font size: adjustable 14–20px via slider, CSS variable --sumi-font-size-base
- useReducedMotion hook: prefers-reduced-motion media query
- useWakeLock hook: Screen Wake Lock for background playback on mobile
- PWA: re-enabled service worker with safe caching (JS/CSS never cached)
- Install App button in Settings when PWA is installable
- ARIA: aria-haspopup="menu" on dropdowns, aria-label on icon buttons (sidebar, player, modals)
- Focus visible: 2px outline with offset on :focus-visible
Changed
- ThemeProvider extended with contrast, density, accentHue, fontSize
- AppearanceSettingsView wired to ThemeProvider and backend sync
- Service worker: network-only for /assets/ and .js/.css, cache images/fonts only
[v0.703] - 2026-02-25
Added
- Go Live: page /live/go-live with stream key display, OBS/Streamlabs instructions
- Stream key management: GET /live/streams/me/key, POST /live/streams/me/key/regenerate
- GET /live/streams/me: list user's streams (includes stream_key)
- PUT /live/streams/🆔 update stream metadata (ownership check)
- Live stream chat: LiveViewChat connected to WebSocket (stream_id as room)
- Real-time viewer count: polling GET /live/streams/:id in LiveViewPlayer
- Media Session API: seekbackward/seekforward handlers (10s step)
- Room creation for live streams: chat room auto-created when stream is created
- Permissions: CanJoin/CanSend/CanRead allow public access for live stream rooms
- GoLiveView.stories.tsx: Default, Loading, Error, StreamKeyVisible
Changed
- Navbar "Go Live" navigates to /live/go-live instead of toast
- useLiveView uses real chat when authenticated, mock when not
[v0.702] - 2026-02-24
Added
- Route /marketplace/products/:id with ProductDetailPage (lazy loaded)
- MSW handlers for product reviews (GET list, POST create) and invoice download
- Unit tests: product reviews (6 tests), invoice generation (4 tests), refund order (6 tests)
- API_REFERENCE.md: documented reviews, invoices, refunds endpoints
Changed
- ProductDetailView.stories.tsx: added Error state story
[v0.701] - 2026-02-23
Added
- Transfer Retry Worker: automatic retry of failed Stripe Connect transfers (exponential backoff, max 3 retries)
- Migration 116: retry_count, next_retry_at columns on seller_transfers
- GET /admin/transfers: paginated admin view of all platform transfers (filters: status, seller, date)
- POST /admin/transfers/:id/retry: manual retry of failed transfers (admin only)
- AdminTransfersView frontend component with status badges, retry button
- GET /health/deep: deep health check (DB, Redis, S3, disk, config summary)
- Startup config validation: PlatformFeeRate range, Stripe Connect coherence, retry config
- Prometheus metrics: transfer retry (total, success, failures, permanent)
- docs/API_REFERENCE.md: API documentation with curl examples
Changed
- SellerTransfer model: added retry_count, next_retry_at fields
- Config: added TRANSFER_RETRY_ENABLED, TRANSFER_RETRY_MAX, TRANSFER_RETRY_INTERVAL
- Health handler: added DeepHealth method with disk space and config
[v0.603] - 2026-02-23
Added
- Automatic Stripe Connect transfer after successful payment (webhook Hyperswitch)
- Platform commission configurable via PLATFORM_FEE_RATE (default 10 %)
- Migration 115 seller_transfers for transfer tracking
- GET /sell/transfers endpoint for seller transfer history
- Transfer History card in SellerDashboard
- Unit tests: transfer success, multi-seller, transfer-fails
Changed
- ProcessPaymentWebhook now triggers seller transfers after license creation
- PAYOUT_MANUAL.md updated for automatic transfer flow
- Pre-v0.501 docs archived to docs/archive/
[v0.602] - 2026-02-23
Added
- Stripe Connect seller payout (onboarding, balance)
- seller_stripe_accounts migration (114)
- Commerce E2E tests (backend integration: product -> order -> review -> invoice)
- docs/SMOKE_TEST_V0602.md
- docs/PAYOUT_MANUAL.md (manual payout procedure for v0.603)
Changed
- interceptors.ts split: auth.ts and error.ts extracted (facade < 30 LOC)
- Grafana dashboards enriched with real Prometheus metrics
- sanitizer.go: fix invalid regex backreference for object/embed tags (Go regexp has no \1)
Infrastructure
- Commerce Prometheus metrics (orders_total, checkout_duration)
[v0.601] - 2026-02-23
Added
- Blue-green deployment via HAProxy (backend-api-blue/green, stream-server-blue/green, deploy-blue-green.sh)
- 3 Grafana dashboards: api-overview, chat-overview, commerce-overview
- Alertmanager config with Slack/email receivers, wired to Prometheus
- Hyperswitch LIVE_MODE configuration (HYPERSWITCH_LIVE_MODE env)
- OAuth Discord and Spotify unit tests (GetAuthURL, GetUserInfo, GetAvailableProviders)
- docs/MIGRATIONS.md documenting squash script and baseline procedure
Changed
- handler.go split into 4 sub-handlers: track_crud_handler, track_social_handler, track_search_handler, track_analytics_handler (~163 LOC facade)
- interceptors.ts split into modules: interceptors/utils, interceptors/request, interceptors/response
- squash_migrations.sh: baseline_v0601.sql, migrations 001-113, output to file
Infrastructure
- docker-compose.prod.yml: blue-green services, Alertmanager (port 9093)
- config/alertmanager/alertmanager.yml
- config/prometheus.yml: alertmanager_config
[v0.503] - 2026-02-22
Added
- HLS streaming end-to-end: backend serving routes (master.m3u8, quality playlists, segments) behind HLS_STREAMING feature flag
- Redis-backed chat rate limiter with sliding window (sorted sets) and automatic in-memory fallback
- ChatPresenceService with Redis-backed online/offline/heartbeat tracking (2min TTL)
- PostgreSQL full-text search on messages: tsvector column, GIN index, auto-update trigger
- MSW handlers for HLS endpoints (info, status, playlists)
- HLS player integration in frontend: useHLSPlayer connected to useAudioPlayerLifecycle with ABR quality switching
- StreamService.GetHLSStatus and TriggerHLSTranscode methods
Changed
- Chat rate limiter now uses Redis sliding window with in-memory fallback (was purely in-memory)
- Chat message search now uses PostgreSQL ts_rank ordering (was ILIKE pattern matching)
- Hub constructor now accepts ChatPresenceService for presence tracking
Removed
- veza-chat-server/ directory (deprecated Rust chat server)
- All chat-server references from CI/CD workflows, monitoring, proxy config, Incus scripts, GitHub templates
Infrastructure
- Shared HLS volume between backend and stream-server in all docker-compose files
- HLS_STREAMING and HLS_STORAGE_DIR environment variables added to backend service
[v0.502] - 2026-02-22
Added
- Chat Server (Go): Full WebSocket chat server integrated into veza-backend-api at
/api/v1/ws - WebSocket Hub: Client management with room-based broadcasting and user indexing
- Message Handlers: SendMessage, EditMessage, DeleteMessage with ownership checks
- Room Handlers: JoinConversation, LeaveConversation with permission enforcement
- History/Search/Sync: Cursor-based FetchHistory, ILIKE SearchMessages, SyncMessages
- Real-time Features: Typing indicators, read receipts, delivered status, message reactions
- WebRTC Signaling: CallOffer, CallAnswer, ICECandidate, CallHangup, CallReject relay
- PermissionService: CanRead, CanSend, CanJoin, CanModerate based on room_members
- RateLimiter: Per-user per-action sliding window (in-memory)
- ChatPubSubService: Redis PubSub for multi-instance broadcasting with in-memory fallback
- 4 database migrations (109-112): read_receipts, delivered_status, message_reactions, messages extra columns
- 3 new GORM models: ReadReceipt, DeliveredStatus, MessageReaction
- ChatMessageRepository enriched: cursor pagination, search, soft delete
- ValidateChatToken: JWT validation for WebSocket authentication
- 15 unit tests: Hub, message handlers, real-time handlers
- CHAT_FEATURE_PARITY.md: 25-feature checklist (all OK or IMPROVED vs Rust)
Changed
- Frontend env.ts: WS_URL auto-derived from API_URL (no separate VITE_WS_URL needed)
- Frontend types/index.ts: Added EditMessage, DeleteMessage, FetchHistory, SearchMessages, SyncMessages, MessageEdited, MessageDeleted, SearchResults, SyncChunk
- MSW handler: chat/token returns ws_url: '/api/v1/ws'
- WSUrl in ChatService.GenerateToken changed from
/wsto/api/v1/ws
Removed
- Rust chat server (
veza-chat-server) removed from docker-compose.yml, staging.yml, prod.yml - VITE_WS_URL environment variable from Docker frontend configs (auto-derived)
- Dev hack for
127.0.0.1:8081in useChat.ts
Infrastructure
- Docker: Single backend binary serves both REST API and Chat WebSocket
- Redis PubSub: Enables horizontal scaling of chat (improvement over single-instance Rust)
[v0.501] - 2026-02-22
Added
- HLS Multi-bitrate Streaming: 3-tier adaptive bitrate (128k, 256k, 320k) with hls.js ABR
- Waveform Generation: Async FFmpeg + audiowaveform pipeline with S3 storage and Redis cache
- WaveformDisplay Component: Interactive SVG waveform with seek support
- Cloud Storage MVP: Full folder/file management with 5GB quota per user
- Cloud Upload Modal: Drag-and-drop with progress and quota validation
- Cloud File Preview: Inline audio player for cloud files
- Gear Public Profiles: is_public toggle, public endpoint, GearShowcase component
- Gear Image Gallery: Multi-image support with carousel viewer
- Gear Search: ILIKE-based search with frontend SearchBar
- MinIO Integration: S3-compatible storage in all environments
- Prometheus Streaming Metrics: 4 new counters (transcode duration, segments served, active connections, errors)
- useHLSPlayer Hook: hls.js integration with ABR quality selection
- Container Scanning: Trivy CI workflow for Docker images
- 6 new database migrations (103-108): waveform, cloud, gear images
Changed
- QualitySelector updated to 256kbps medium tier
- Track handler split into 4 focused files (handler, upload, HLS, waveform)
- Production console.log replaced with structured logger
- Gear handler extended with search and image endpoints
Infrastructure
- MinIO added to docker-compose (dev, staging, prod)
- HLS segment cache headers (immutable, 1-year max-age)
- Migration squash script and MIGRATIONS.md documentation
[v0.404] - 2026-02-22
Security
- Ephemeral JWT stream-token endpoint for HLS/WebSocket auth (SEC-03)
- SSRF protection: webhook URLs require HTTPS only (SEC-07)
- IDOR fix in GetUploadStatus with ownership verification (SEC-06)
- Hyperswitch webhook secret required in production (SEC-08)
- Password reset tokens hashed with SHA-256 before storage (INF-10)
- Docker hybrid compose removed (SEC-04)
- CI credentials moved to GitHub Secrets (SEC-10)
- JWT_SECRET added to stream-server in production compose (SEC-05)
- Go version unified to 1.24 across Dockerfile and CI (SEC-09)
- CD pipeline fixed (vars.* in conditions, Dockerfile.production) (SEC-01)
- Redis authentication enabled in production compose (SEC-02)
Infrastructure
- Redis-backed rate limiter with in-memory fallback (INF-01)
- PostgreSQL aligned to v16 in test environment (INF-02)
- Frontend CI: lint, typecheck, build steps added (INF-03)
- Backend CI: go vet + gofmt check added (INF-04)
- Rust CI with clippy for chat and stream servers (INF-05)
- CodeQL SAST scanning for Go and TypeScript (INF-06)
- Complete staging compose with chat, stream, Caddy reverse proxy (INF-07)
- Prometheus alerting rules for critical conditions (INF-08)
- Docker healthchecks on all services (INF-09)
Code Quality
- 40 fmt.Printf replaced with zap structured logging (CLN-03)
- ~45
anytypes eliminated in frontend production code (CLN-04) - TypeScript unified to 5.9.3 across all packages (CLN-06)
- ~1600 LOC dead code removed (CLN-01)
- gorilla/websocket replaced with coder/websocket (INT-06)
- commerceService mock data replaced with real API calls (CLN-02)
- Protobuf definitions centralized in proto/ directory (CLN-07)
Documentation
- ADR-001: Go+Rust architecture decision (CLN-08)
- ADR-002: Chat server Rust->Go migration plan (INT-01)
- FEATURE_STATUS.md aligned with actual code state (CLN-05)
- PROJECT_STATE.md updated with v0.404 metrics (FIN-02)
Testing
- 5 cross-service E2E integration tests (INT-03)
- 51 unit tests added across Rust services (INT-05)
- 2 skipped backend tests fixed, 11 clarified (INT-04)
Integration
- HLS transcoding triggered after track upload (INT-02)
[v0.402] - 2026-02-21
Added
- Lot P1 — Checkout Hyperswitch production-ready
- Return URL with
order_idfor success/error pages - CheckoutSuccessView, CheckoutErrorView, CheckoutCompletePage
- Route
/checkout/complete(protected) - Webhook: handle
cancelledstatus in ProcessPaymentWebhook - CheckoutPaymentForm (Hyperswitch) in Cart when
client_secretreturned - marketplaceService.getOrder(orderId)
- Return URL with
- Lot P2 — Codes promo / réductions
- Migrations 099 (promo_codes), 100 (orders discount fields)
- PromoCode model, ValidatePromoCode, validatePromoCodeTx
- GET /commerce/promo/:code
- CreateOrder and Checkout accept
promo_code(percent/fixed) - PromoCodeModal connected to validatePromoCode API
- Cart: PromoCodeModal, OrderSummary with discount, promo_code at checkout
- MSW handlers for promo, orders/:id, checkout with promo_code
- Stories: CheckoutSuccessView, CheckoutErrorView, PromoCodeModal
Changed
- CreateOrder signature: promoCode string parameter
- Cart.Checkout: promoCode parameter
- OrderSummary integrated in Cart with discount support
[v0.401] - 2026-02-22
Added
- Lot M1 — Produits & Catalogue
- Migrations 095-097 : products enrichment (bpm, musical_key, category), product_previews, product_images
- ProductPreview, ProductImage models, CreateProduct/UpdateProduct accept bpm, musical_key, category
- POST /marketplace/products/:id/preview (audio preview upload)
- PUT /marketplace/products/:id/images
- GET /marketplace/products/:id/preview (stream audio)
- ListProducts filters: bpm, musical_key, category
- CreateProductView connected to enriched API, BPM/Key/Category filters in MarketplaceHome
- ProductDetailView: playable preview, image gallery
- Rich text description (sanitization backend, toolbar Bold/List frontend)
- Lot M2 — Licences & Droits
- Migration 098 : product_licenses (license_type, price_cents, terms_text)
- ProductLicense model, SetProductLicenses, GetProductLicenses
- CreateProduct/UpdateProduct accept licenses array
- GET /marketplace/licenses/mine (user's purchased licenses with download_url)
- LicenceCard, LicenceDetailsModal: license_type, price_cents, terms_text
- LicensesView in PurchasesPage with download links
- Lot M3 — Seller dashboard enrichi
- GET /sell/stats/evolution (day/week/month)
- GET /sell/stats/top-products
- GET /sell/sales (real sales data)
- commerceService: getSales, getSellerStatsEvolution, getSellerTopProducts (real API)
- SalesEvolutionChart (Recharts LineChart)
- Top Products section with real revenue/sales_count
- Conversion rate: N/A when no tracking
Changed
- Marketplace products: bpm, musical_key, category, previews, images, licenses
- SellerDashboardView: real data, evolution chart, top products from API
[v0.303] - 2026-02-22
Added
- Lot C2 — Chat appels WebRTC 1-to-1
- Chat Server : signalisation CallOffer, CallAnswer, ICECandidate, CallHangup, CallReject
- WebSocketManager.send_to_user pour livraison 1-to-1
- RateLimitAction::CallSignaling (60 req/min)
- Frontend : useWebRTC hook, CallButton, IncomingCallModal, ActiveCallBar
- Appels audio 1-to-1 dans conversations DM
[v0.302] - 2026-02-21
Added
- Lot S2 — Groupes avancés
- Demander à rejoindre (groupes privés), approbation/rejet par admin
- Inviter membres par email ou user_id
- Rôles assign/revoke (admin, moderator, member)
- Feed type=groups (posts des membres des groupes)
- GET /social/groups/mine
- Migrations 069, 089, 092
- Lot N1 — Notifications push Web
- POST /notifications/push/subscribe, PushService (webpush-go)
- Envoi push sur follow/like/comment/message (selon préférences)
- GET/PUT /notifications/preferences
- Migrations 090, 093
- Frontend : subscribePush, PushPreferencesSection, badge document.title
- Lot P2 — Présence enrichie
- PUT /users/me/presence (status_message, track_id, track_title, invisible)
- Rich presence : sync track en cours via usePresenceSync
- Mode invisible (GetPresenceForViewer masque pour les autres)
- PresenceBadge statusMessage tooltip
- Migrations 091, 094
Changed
- NotificationService : SetPushService, envoi push post-CreateNotification
- Shared NotificationService avec PushService pour profile, track, comment handlers
Deferred (v0.303)
- Lot C2 : Livré en v0.303
[v0.301] - 2026-02-20
Added
- Lot P0 — Chat Server
- Protocole typing aligné :
{ type: 'Typing', conversation_id, is_typing } - Limitation JWT auth (query param) documentée pour v0.302
- Protocole typing aligné :
- Lot C1 — Chat avancé
- Typing indicators end-to-end (UserTyping, setUserTyping)
- Read receipts (MarkAsRead, MessageRead, « Vu à HH:mm »)
- Delivered status (Delivered, MessageDelivered)
- Lot P1 — Présence
- Migration 088 user_presence (status, last_seen_at, status_message)
- PresenceService, GET /users/:id/presence
- Mise à jour last_seen_at sur chaque requête authentifiée
- PresenceBadge, usePresence, intégration ChatSidebar
- Lot S1 — Social enrichi
- Feed connecté à socialService.getFeed (remplace trackService.list)
- Backend : enrichissement actor_name, actor_avatar, track dans GetGlobalFeed
- SocialViewFeedItem : posts texte + posts avec track (mini player)
- Pagination cursor (next_cursor), useInfiniteQuery, Load More
- GET /social/explore (trending + suggested_users), onglet Explore
- Filtres feed : all | following | groups (param type, OptionalAuth pour following)
Changed
- useSocialView : socialService.getFeed, useInfiniteQuery, feedFilter
- SocialView : onglet Explore, filtres feed
- AuthMiddleware : SetPresenceService, UpdatePresence sur RequireAuth
Documented
- FEATURE_STATUS, PROJECT_STATE mis à jour pour v0.301
[v0.203] - 2026-02-20
Added
- Lot L — Social Trending
- GET /social/trending (extraction hashtags posts 7 jours, agrégation)
- Cache Redis 15 min (clé trending:hashtags)
- SocialViewTrending connecté à l’API (Loading, Error, Empty fallback)
- MSW handler GET */api/v1/social/trending
- Lot K — Recherche enrichie
- Migration 086 pg_trgm pour fuzzy search
- TrackSearchService : similarity() sur title/artist/album (PostgreSQL), fallback ILIKE (SQLite)
- query_parser.go : AND, OR, NOT, "phrase exacte"
- SearchService + TrackSearchService utilisent le parser
- SearchPageHeader : tooltip aide syntaxe
- Lot D1 — Queue collaborative
- Migration 087 queue_sessions, shared_queue_items
- Modèles QueueSession, SharedQueueItem
- QueueSessionService : Create, Get, Delete, Add/Remove items
- POST/GET/DELETE /queue/session, POST/DELETE /queue/session/:token/items
- PlayerQueue : bouton Partager, badge Queue partagée, polling 8 s
- queueSessionStore, useQueueSync mode session
- MSW handlers pour queue session
Changed
- SocialViewTrending : useQuery, skeletons, erreur → fallback tags
- TrackSearchService : dialect sqlite → LIKE, postgres → similarity
- SearchService : BuildWhereCondition pour requêtes booléennes
- PlayerQueue : mode session, partage lien, sync session
- useQueueSync : skip sync personnelle quand session active
Documented
- FEATURE_STATUS, PROJECT_STATE mis à jour pour v0.203
[v0.202] - 2026-02-20
Added
- Lot G — Recherche avancée
- Filtre musical_key dans track_search (G1)
- Tri pertinence (relevance) dans SearchService (G2)
- Autocomplete : GET /search/suggestions, dropdown debounced (G3)
- Facettes type (tracks/artistes/playlists/users) dans SearchPage (G4)
- Historique recherche localStorage (G5)
- Lot H — Analytics créateur
- GET /analytics/creator/stats, carte Completion Rate (H1)
- GET /analytics/creator/charts, graphiques (H2)
- Taux de complétion intégré dashboard (H3)
- GET /analytics/creator/export CSV/JSON (H4)
- Lot F — Seller dashboard
- GET /sell/stats, connexion commerceService (F1)
- Support seller_id=me dans ListProducts (F2)
- Lot C — Player avancé
- Crossfade configurable (1–12 s) depuis Settings (C1)
- Gapless préchargement via preloadTrack (C2)
- PiP (Picture-in-Picture) si supporté (C3)
- Lot D — Autoplay
- GET /tracks/recommendations (auth), section « À écouter ensuite » dans PlayerQueue (D2)
Changed
- SearchPage : onglets type, suggestions dropdown, historique récent
- AnalyticsViewKpiGrid : métrique Completion Rate
- AnalyticsViewChart : graphiques creator
- SettingsPage : slider crossfade
- PlayerQueue : recommandations quand queue vide (authentifié)
- PlayerStore : crossfadeSeconds, préchargement ~5 s avant fin
Documented
- D1 (queue collaborative) reporté v0.203+
- V0_202_RELEASE_SCOPE.md, FEATURE_STATUS.md, PROJECT_STATE.md mis à jour
[v0.201] - 2026-02-20
Added
- Lot E — Métadonnées enrichies
- BPM : champ dans Track model, UpdateTrack, filtre track_search (E1)
- Musical key : champ, input/select édition, affichage TrackDetailPageInfo (E2)
- Lyrics : table track_lyrics, GET/PUT /tracks/:id/lyrics, section Paroles avec toggle (E3)
- Tags suggérés : GET /tracks/suggested-tags?genre=X, migration tracks.tags, chips + dropdown (E4)
Changed
- Track model : BPM, MusicalKey, Tags (pq.StringArray)
- TrackDetailPageInfo : affichage BPM, key, tags
- TrackMetadataEditModal : édition BPM, musical_key, tags avec suggestions
Documented
- Lot G (Recherche avancée), H (Analytics), F (Seller), C (Player), D (Queue) reportés v0.202+
[v0.103] - 2026-02-20
Added
- Auth (Lot A) : OAuth Spotify (A1), page Sessions enrichie avec historique et révocation (A4)
- Profils (Lot B) : Bannière de profil éditable (B1), section liens sociaux sur profil public (B2), toggle profil privé dans Settings (B3)
- Profil privé : Vue « Profil privé » sur
/u/:usernamequand le profil est masqué ;is_publicexposé et persisté
Documented
- 2FA SMS et Passkeys/WebAuthn reportés à v0.104
[v0.102] - 2026-02-20
Added
- Queue persistante : API CRUD (
GET/PUT/POST/DELETE /api/v1/queue), sync frontend viauseQueueSync, drag & drop reorder avec @dnd-kit (B3) - Developer API Keys : CRUD clés API, X-API-Key middleware, CreateAPIKeyModal, révocation
- Playlists : activation PLAYLIST_SHARE, PLAYLIST_RECOMMENDATIONS ; boutons Export (JSON/CSV), Duplicate connectés
- Social : like/comment post connectés à l’API ; profil followers/following count ; badges rôles
- Player : playback speed (0.5x–2x), Media Session API, waveform dans progress bar
Changed
- Gear, Live, Queue, Developer : routes opérationnelles (fin des placeholders Coming Soon)
- Feature flags PLAYLIST_SHARE et PLAYLIST_RECOMMENDATIONS activés (true)
Documented
- Go Live (streaming vidéo) : non implémenté, prévu v0.703 — limitation A6
- Social Trending (tags) : statique, report v0.103 pour
GET /social/trending
[Unreleased] - 2024-12-07
Security
- chat-server: Implemented JWT Authentication Middleware for HTTP API.
- Secured
/api/messages(POST) and/api/messages/{id}(GET). - Enforced permission checks (
can_send_message,can_read_conversation). - Patched
sender_idspoofing vulnerability by enforcing User ID from Token Claims.
- Secured
- backend: Resolved
veza_errors_totalmetric collision preventing proper monitoring initialization.
Fixed
- backend: Fixed
JobWorkerstarvation issue by replacing blockingtime.Sleepwith non-blocking scheduler. - stream-server: Improved task safety by replacing unsafe
abort()with gracefuljoin/awaitfor monitoring tasks. - chat-server: Fixed resource leak by implementing 60s WebSocket inactivity/heartbeat timeout.
- chat-server: Implemented Graceful Shutdown handling for OS signals (SIGTERM/SIGINT).
- backend-tests: Fixed
RoomHandlerunit tests.- Refactored
RoomHandlerto useRoomServiceInterfacefor dependency injection. - Updated
CreateRoomtests to match actual Service signatures. - Fixed
bitrate_handler_test.gocompilation errors. - Resolved global metric registration panics during testing.
- Refactored
Removed
- backend: Deleted legacy maintenance code (
migrations_legacy/andsrc/cmd/main.go.legacy).
Known Issues
- backend: Some unit tests (
metrics_test.go,profile_handler_test.go,system_metrics_test.go) are disabled due to bitrot/missing dependencies. - stream-server: Compilation requires active Database connection (sqlx compile-time verification) or
sqlx-data.json.