From 6e8d797d824e40598ddb784ad6a835170dd2681c Mon Sep 17 00:00:00 2001 From: senke Date: Sun, 28 Dec 2025 12:19:34 +0100 Subject: [PATCH] [T0-001] fix(backend): Corriger erreurs compilation Go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - go build ./... réussit sans erreur - go vet ./... retourne 0 warnings critiques - Aucune erreur de type dans les handlers - go mod verify et go mod tidy exécutés avec succès Files: VEZA_ROADMAP.json, veza-backend-api/go.mod, veza-backend-api/go.sum Hours: 6 estimated, 1 actual Le code compile déjà correctement, aucune correction nécessaire. Vérifications effectuées: - go build -a ./... ✓ - go vet -all ./... ✓ - go mod verify ✓ - go mod tidy ✓ --- VEZA_ROADMAP.json | 2930 +++++++++++++++++++++++++++++++++++++++ veza-backend-api/go.mod | 12 +- veza-backend-api/go.sum | 4 + 3 files changed, 2940 insertions(+), 6 deletions(-) create mode 100644 VEZA_ROADMAP.json diff --git a/VEZA_ROADMAP.json b/VEZA_ROADMAP.json new file mode 100644 index 000000000..af98f9c6b --- /dev/null +++ b/VEZA_ROADMAP.json @@ -0,0 +1,2930 @@ +{ + "_meta": { + "project": "Veza/Talas", + "version": "0.101-MVP", + "created": "2025-01-28", + "last_updated": "2025-12-28T11:19:17Z", + "total_tasks": 156, + "completed_tasks": 1, + "in_progress_task": null, + "current_phase": "PHASE_0", + "estimated_total_hours": 1480, + "hours_completed": 6 + }, + + "_instructions": { + "how_to_use": "Ce fichier est lu et modifié automatiquement par le prompt Cursor", + "status_values": ["pending", "in_progress", "completed", "blocked", "skipped"], + "priority_order": ["P0", "P1", "P2", "P3"], + "next_task_logic": "Prendre la première tâche 'pending' dont toutes les dépendances sont 'completed'" + }, + + "tasks": [ + { + "id": "T0-001", + "phase": "PHASE_0", + "type": "FIX", + "domain": "BACKEND", + "title": "Corriger erreurs compilation Go", + "description": "Résoudre toutes les erreurs de compilation dans le backend Go", + "priority": "P0", + "status": "completed", + "estimated_hours": 6, + "actual_hours": 1, + "started_at": "2025-12-28T11:19:17Z", + "completed_at": "2025-12-28T11:19:17Z", + "dependencies": [], + "acceptance_criteria": [ + "go build ./... réussit sans erreur", + "go vet ./... retourne 0 warnings critiques", + "Aucune erreur de type dans les handlers" + ], + "files": { + "to_check": ["veza-backend-api/"], + "to_modify": ["veza-backend-api/go.mod", "veza-backend-api/go.sum"], + "created": [] + }, + "commands": { + "verify": ["cd veza-backend-api && go build ./...", "cd veza-backend-api && go vet ./..."], + "test": ["cd veza-backend-api && go test ./... -short"] + }, + "implementation_notes": "Vérification complète effectuée: go build, go vet, go mod verify et go mod tidy tous réussis sans erreur. Le code compile déjà correctement, aucune correction nécessaire.", + "blockers": [] + }, + { + "id": "T0-002", + "phase": "PHASE_0", + "type": "FIX", + "domain": "RUST", + "title": "Corriger erreurs compilation Rust", + "description": "Résoudre toutes les erreurs de compilation dans les modules Rust", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": [], + "acceptance_criteria": [ + "cargo build --release réussit pour chat/", + "cargo build --release réussit pour streaming/", + "cargo clippy ne retourne aucune erreur" + ], + "files": { + "to_check": ["rust/chat/", "rust/streaming/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd rust/chat && cargo build", "cd rust/streaming && cargo build"], + "test": ["cd rust/chat && cargo test", "cd rust/streaming && cargo test"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-003", + "phase": "PHASE_0", + "type": "FIX", + "domain": "FRONTEND", + "title": "Corriger erreurs TypeScript/React", + "description": "Résoudre toutes les erreurs TypeScript et de build React", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": [], + "acceptance_criteria": [ + "npm run build réussit sans erreur", + "npm run lint retourne 0 erreurs", + "npm run typecheck réussit" + ], + "files": { + "to_check": ["frontend/src/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd frontend && npm run build", "cd frontend && npm run lint"], + "test": ["cd frontend && npm run test -- --run"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-004", + "phase": "PHASE_0", + "type": "CONFIG", + "domain": "DEVOPS", + "title": "Valider Docker Compose", + "description": "S'assurer que tous les services Docker démarrent correctement", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-001", "T0-002", "T0-003"], + "acceptance_criteria": [ + "docker-compose up -d démarre tous les services", + "Healthchecks passent pour tous les containers", + "Pas d'erreurs critiques dans les logs" + ], + "files": { + "to_check": ["docker-compose.yml", "docker-compose.dev.yml"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["docker-compose config", "docker-compose up -d", "docker-compose ps"], + "test": ["docker-compose logs --tail=50"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-005", + "phase": "PHASE_0", + "type": "CONFIG", + "domain": "DATABASE", + "title": "Valider migrations PostgreSQL", + "description": "S'assurer que toutes les migrations s'appliquent correctement", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-004"], + "acceptance_criteria": [ + "Migrations up s'appliquent sans erreur", + "Migrations down fonctionnent (rollback)", + "Schéma cohérent avec ORIGIN_DATABASE_SCHEMA.md" + ], + "files": { + "to_check": ["backend/migrations/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["make migrate-up", "make migrate-status"], + "test": ["make migrate-down", "make migrate-up"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-006", + "phase": "PHASE_0", + "type": "TEST", + "domain": "BACKEND", + "title": "Tests Go - Couverture 80%", + "description": "Atteindre 80% de couverture de tests sur le backend Go", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-001", "T0-005"], + "acceptance_criteria": [ + "go test -cover ./... >= 80%", + "Tous les handlers ont des tests", + "Tous les services ont des tests" + ], + "files": { + "to_check": ["backend/internal/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd backend && go test -cover ./..."], + "test": ["cd backend && go test -coverprofile=coverage.out ./...", "go tool cover -html=coverage.out"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-007", + "phase": "PHASE_0", + "type": "TEST", + "domain": "RUST", + "title": "Tests Rust - Couverture 75%", + "description": "Atteindre 75% de couverture de tests sur les modules Rust", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-002"], + "acceptance_criteria": [ + "cargo test passe à 100%", + "Tests WebSocket fonctionnels", + "Tests streaming fonctionnels" + ], + "files": { + "to_check": ["rust/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd rust/chat && cargo test", "cd rust/streaming && cargo test"], + "test": ["cargo tarpaulin --out Html"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-008", + "phase": "PHASE_0", + "type": "TEST", + "domain": "FRONTEND", + "title": "Tests Frontend - Couverture 70%", + "description": "Atteindre 70% de couverture de tests sur le frontend", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-003"], + "acceptance_criteria": [ + "npm run test:coverage >= 70%", + "Composants critiques testés", + "Stores testés" + ], + "files": { + "to_check": ["frontend/src/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd frontend && npm run test -- --coverage --run"], + "test": ["cd frontend && npm run test:coverage"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-009", + "phase": "PHASE_0", + "type": "CONFIG", + "domain": "DEVOPS", + "title": "CI/CD GitHub Actions", + "description": "Configurer pipeline CI/CD complet", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-006", "T0-007", "T0-008"], + "acceptance_criteria": [ + "Workflow CI déclenché sur PR", + "Tests automatiques passent", + "Build Docker automatique" + ], + "files": { + "to_check": [".github/workflows/"], + "to_modify": [".github/workflows/ci.yml"], + "created": [] + }, + "commands": { + "verify": ["gh workflow list", "gh run list"], + "test": ["gh workflow run ci.yml"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T0-010", + "phase": "PHASE_0", + "type": "DOC", + "domain": "DOCS", + "title": "README et documentation setup", + "description": "Mettre à jour README avec instructions de démarrage", + "priority": "P1", + "status": "pending", + "estimated_hours": 3, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-004"], + "acceptance_criteria": [ + "README avec quick start", + "CONTRIBUTING.md à jour", + "Architecture documentée" + ], + "files": { + "to_check": ["README.md", "CONTRIBUTING.md"], + "to_modify": ["README.md"], + "created": [] + }, + "commands": { + "verify": [], + "test": [] + }, + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T1-001", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Register", + "description": "POST /auth/register avec validation et email de confirmation", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-006"], + "acceptance_criteria": [ + "Validation email format + unicité", + "Hash bcrypt du password (cost=12)", + "Email de confirmation envoyé", + "Token de vérification (24h expiry)", + "Réponse 201 avec user sans password" + ], + "files": { + "to_check": ["backend/internal/handlers/", "backend/internal/services/"], + "to_modify": [ + "backend/internal/handlers/auth_handler.go", + "backend/internal/services/auth_service.go", + "backend/internal/services/email_service.go" + ], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v"] + }, + "api": { + "method": "POST", + "path": "/api/v1/auth/register", + "request_body": { + "email": "string", + "password": "string", + "username": "string" + }, + "response": { + "201": {"user": {}}, + "400": {"error": "validation_error"}, + "409": {"error": "email_already_exists"} + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-002", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Login", + "description": "POST /auth/login avec JWT access + refresh token", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-001"], + "acceptance_criteria": [ + "Validation credentials", + "JWT access token (15min expiry)", + "Refresh token (7 jours, httpOnly cookie)", + "Rate limiting (5/min par IP)" + ], + "files": { + "to_check": [], + "to_modify": [ + "backend/internal/handlers/auth_handler.go", + "backend/internal/services/jwt_service.go", + "backend/internal/middleware/rate_limiter.go" + ], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v -run TestLogin"] + }, + "api": { + "method": "POST", + "path": "/api/v1/auth/login", + "request_body": { + "email": "string", + "password": "string" + }, + "response": { + "200": {"access_token": "string", "expires_in": 900}, + "401": {"error": "invalid_credentials"}, + "429": {"error": "rate_limit_exceeded"} + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-003", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Refresh Token", + "description": "POST /auth/refresh pour renouveler l'access token", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "Lecture refresh token depuis cookie", + "Validation du refresh token", + "Rotation du refresh token", + "Nouveau access token généré" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/auth_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v -run TestRefresh"] + }, + "api": { + "method": "POST", + "path": "/api/v1/auth/refresh", + "response": { + "200": {"access_token": "string", "expires_in": 900}, + "401": {"error": "invalid_refresh_token"} + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-004", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Logout", + "description": "POST /auth/logout pour invalider les tokens", + "priority": "P0", + "status": "pending", + "estimated_hours": 2, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-003"], + "acceptance_criteria": [ + "Refresh token ajouté à blacklist Redis", + "Cookie refresh_token supprimé", + "Réponse 204" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/auth_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v -run TestLogout"] + }, + "api": { + "method": "POST", + "path": "/api/v1/auth/logout", + "response": { + "204": null + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-005", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Verify Email", + "description": "GET /auth/verify/:token pour confirmer l'email", + "priority": "P0", + "status": "pending", + "estimated_hours": 3, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-001"], + "acceptance_criteria": [ + "Validation token", + "Mise à jour user.verified = true", + "Redirection vers frontend" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/auth_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v -run TestVerifyEmail"] + }, + "api": { + "method": "GET", + "path": "/api/v1/auth/verify/:token", + "response": { + "302": "redirect to frontend", + "400": {"error": "invalid_token"}, + "410": {"error": "token_expired"} + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-006", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Password Reset", + "description": "Flux complet de reset password", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-001"], + "acceptance_criteria": [ + "POST /auth/password/forgot - envoie email", + "POST /auth/password/reset - reset avec token", + "Token temporaire 1h", + "Invalidation anciens tokens" + ], + "files": { + "to_check": [], + "to_modify": [ + "backend/internal/handlers/auth_handler.go", + "backend/internal/services/auth_service.go" + ], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/auth_handler_test.go -v -run TestPasswordReset"] + }, + "api": { + "method": "POST", + "path": "/api/v1/auth/password/forgot", + "request_body": {"email": "string"}, + "response": {"200": {"message": "email_sent"}} + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-007", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "OAuth Google", + "description": "Authentification via Google OAuth2", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "GET /auth/google - redirection OAuth", + "GET /auth/google/callback - traitement callback", + "Création compte si nouveau", + "Liaison si compte existe" + ], + "files": { + "to_check": [], + "to_modify": [ + "backend/internal/handlers/oauth_handler.go", + "backend/internal/services/oauth_service.go" + ], + "created": ["backend/internal/handlers/oauth_handler.go"] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/oauth_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/auth/google" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-008", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "OAuth GitHub", + "description": "Authentification via GitHub OAuth2", + "priority": "P1", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-007"], + "acceptance_criteria": [ + "GET /auth/github - redirection OAuth", + "GET /auth/github/callback - traitement callback", + "Récupération email primary" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/oauth_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/oauth_handler_test.go -v -run TestGitHub"] + }, + "api": { + "method": "GET", + "path": "/api/v1/auth/github" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-009", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API User Profile CRUD", + "description": "Endpoints pour gestion profil utilisateur", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "GET /users/me - profil courant", + "PATCH /users/me - mise à jour", + "GET /users/:id - profil public", + "DELETE /users/me - suppression compte" + ], + "files": { + "to_check": [], + "to_modify": [ + "backend/internal/handlers/user_handler.go", + "backend/internal/services/user_service.go" + ], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/user_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/users/me" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-010", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Avatar Upload", + "description": "Upload et gestion de l'avatar utilisateur", + "priority": "P1", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-009"], + "acceptance_criteria": [ + "POST /users/me/avatar - upload image", + "Validation format (jpg, png, webp)", + "Resize automatique (400x400)", + "Stockage S3/MinIO" + ], + "files": { + "to_check": [], + "to_modify": [ + "backend/internal/handlers/user_handler.go", + "backend/internal/services/storage_service.go" + ], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/user_handler_test.go -v -run TestAvatar"] + }, + "api": { + "method": "POST", + "path": "/api/v1/users/me/avatar" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-011", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Login", + "description": "Interface de connexion complète", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002", "T0-008"], + "acceptance_criteria": [ + "Formulaire email/password", + "Boutons OAuth (Google, GitHub)", + "Validation temps réel", + "Messages d'erreur clairs", + "Lien vers register/forgot" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/auth/LoginPage.tsx", + "frontend/src/components/auth/LoginForm.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run LoginForm"] + }, + "ui_components": ["Button", "Input", "Card", "Alert", "Divider", "Link"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-012", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Register", + "description": "Interface d'inscription complète", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-001", "T0-008"], + "acceptance_criteria": [ + "Formulaire (email, password, username)", + "Indicateur force mot de passe", + "Validation temps réel", + "Checkbox CGU", + "Confirmation envoi email" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/auth/RegisterPage.tsx", + "frontend/src/components/auth/RegisterForm.tsx", + "frontend/src/components/auth/PasswordStrength.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run RegisterForm"] + }, + "ui_components": ["Button", "Input", "Checkbox", "PasswordStrength", "Alert"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-013", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Auth Store (Zustand)", + "description": "Gestion globale de l'état d'authentification", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002", "T1-003"], + "acceptance_criteria": [ + "Store Zustand auth", + "Actions: login, logout, refresh", + "Persistance localStorage", + "Refresh automatique token" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/stores/authStore.ts", + "frontend/src/hooks/useAuth.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run authStore"] + }, + "ui_components": [], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-014", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Protected Routes", + "description": "Composant pour protéger les routes authentifiées", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-013"], + "acceptance_criteria": [ + "Redirection vers /login si non-auth", + "Loading state pendant vérification", + "Préservation URL destination" + ], + "files": { + "to_check": [], + "to_modify": ["frontend/src/router/index.tsx"], + "created": [ + "frontend/src/components/auth/ProtectedRoute.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run ProtectedRoute"] + }, + "ui_components": ["Spinner"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-015", + "phase": "PHASE_1", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Profile", + "description": "Page de profil utilisateur avec édition", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-009", "T1-010", "T1-013"], + "acceptance_criteria": [ + "Affichage infos profil", + "Upload/change avatar", + "Édition bio, links", + "Changement mot de passe", + "Suppression compte" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/profile/ProfilePage.tsx", + "frontend/src/components/profile/ProfileHeader.tsx", + "frontend/src/components/profile/ProfileForm.tsx", + "frontend/src/components/profile/AvatarUpload.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run Profile"] + }, + "ui_components": ["Avatar", "Button", "Input", "Textarea", "ImageUpload", "Tabs", "Modal"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T1-016", + "phase": "PHASE_1", + "type": "TEST", + "domain": "E2E", + "title": "Tests E2E Auth Flow", + "description": "Tests Playwright pour le flux d'authentification complet", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-011", "T1-012", "T1-015"], + "acceptance_criteria": [ + "Test register complet", + "Test login/logout", + "Test password reset", + "Test profile edit" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/tests/e2e/auth.spec.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npx playwright test auth --reporter=list"], + "test": ["cd frontend && npx playwright test auth"] + }, + "ui_components": [], + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T2-001", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Upload Init", + "description": "Initier un upload multipart pour gros fichiers audio", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "POST /tracks/upload/init", + "Validation format (mp3, wav, flac, aac)", + "Validation taille (max 500MB)", + "Génération upload_id unique", + "Création entrée DB pending" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/upload_handler.go", + "backend/internal/services/upload_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/upload_handler_test.go -v"] + }, + "api": { + "method": "POST", + "path": "/api/v1/tracks/upload/init", + "request_body": { + "filename": "string", + "size": "number", + "content_type": "string" + }, + "response": { + "200": {"upload_id": "string", "chunk_size": 5242880} + } + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-002", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Upload Chunk", + "description": "Upload des chunks individuels", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-001"], + "acceptance_criteria": [ + "PUT /tracks/upload/:id/chunk/:index", + "Validation checksum MD5", + "Stockage temporaire chunks", + "Tracking progression" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/upload_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/upload_handler_test.go -v -run TestChunk"] + }, + "api": { + "method": "PUT", + "path": "/api/v1/tracks/upload/:id/chunk/:index" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-003", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Upload Complete", + "description": "Finaliser l'upload et déclencher le traitement", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-002"], + "acceptance_criteria": [ + "POST /tracks/upload/:id/complete", + "Assemblage des chunks", + "Stockage S3 final", + "Job processing en queue" + ], + "files": { + "to_check": [], + "to_modify": ["backend/internal/handlers/upload_handler.go"], + "created": [] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/upload_handler_test.go -v -run TestComplete"] + }, + "api": { + "method": "POST", + "path": "/api/v1/tracks/upload/:id/complete" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-004", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "Service S3/MinIO", + "description": "Service de stockage compatible S3", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-004"], + "acceptance_criteria": [ + "Upload vers bucket", + "Download avec presigned URL", + "Delete fichier", + "Configuration multi-bucket" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/services/storage_service.go", + "backend/internal/config/storage.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/services/storage_service_test.go -v"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-005", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "Worker Metadata Extraction", + "description": "Job pour extraire les métadonnées audio", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-003"], + "acceptance_criteria": [ + "Extraction ID3/Vorbis tags", + "Durée, bitrate, sample rate", + "Format, codec detection", + "Cover art extraction" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/workers/metadata_worker.go", + "backend/internal/services/metadata_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/workers/metadata_worker_test.go -v"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-006", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "Worker Waveform Generation", + "description": "Générer les données de waveform", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-003"], + "acceptance_criteria": [ + "Peaks data JSON (1000 points)", + "Cache Redis", + "Endpoint GET /tracks/:id/waveform" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/workers/waveform_worker.go", + "backend/internal/services/waveform_service.go", + "backend/internal/handlers/waveform_handler.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/workers/waveform_worker_test.go -v"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-007", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "Worker HLS Transcoding", + "description": "Transcoder audio en HLS pour streaming adaptatif", + "priority": "P0", + "status": "pending", + "estimated_hours": 18, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-003", "T2-004"], + "acceptance_criteria": [ + "Génération segments HLS", + "Multiple qualités (128k, 256k, 320k)", + "Playlist master.m3u8", + "Stockage segments S3" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/workers/transcoding_worker.go", + "backend/internal/services/transcoding_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/workers/transcoding_worker_test.go -v"] + }, + "implementation_notes": "Utiliser FFmpeg via exec ou go-ffmpeg wrapper", + "blockers": [] + }, + { + "id": "T2-008", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Track CRUD", + "description": "Endpoints pour gestion des tracks", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-005"], + "acceptance_criteria": [ + "GET /tracks - liste avec pagination", + "GET /tracks/:id - détails", + "PATCH /tracks/:id - update metadata", + "DELETE /tracks/:id" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/track_handler.go", + "backend/internal/services/track_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/track_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/tracks" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-009", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant UploadZone", + "description": "Zone d'upload avec drag & drop", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-003", "T0-008"], + "acceptance_criteria": [ + "Drag & drop zone", + "Click to select", + "Multi-file support", + "Validation types/taille", + "Preview fichiers" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/upload/UploadZone.tsx", + "frontend/src/components/upload/FilePreview.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run UploadZone"] + }, + "ui_components": ["DropZone", "FileList", "Icon", "Badge"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-010", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant UploadProgress", + "description": "Barre de progression avec états", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-009"], + "acceptance_criteria": [ + "Barre progression animée", + "États: uploading, processing, complete, error", + "Bouton annuler/retry", + "Vitesse upload affichée" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/upload/UploadProgress.tsx", + "frontend/src/hooks/useUpload.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run UploadProgress"] + }, + "ui_components": ["ProgressBar", "Button", "Badge", "Spinner"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-011", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Upload", + "description": "Page complète d'upload avec métadonnées", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-009", "T2-010"], + "acceptance_criteria": [ + "Upload + formulaire métadonnées", + "Tags, genre, BPM", + "Cover art upload", + "Preview avant publish" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/upload/UploadPage.tsx", + "frontend/src/components/upload/MetadataForm.tsx", + "frontend/src/components/upload/CoverUpload.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run Upload"] + }, + "ui_components": ["UploadZone", "Input", "Select", "TagInput", "ImageUpload", "Button"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-012", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant WaveformViewer", + "description": "Visualisation waveform avec Canvas", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-006"], + "acceptance_criteria": [ + "Rendu Canvas responsive", + "Indicateur position lecture", + "Click to seek", + "Hover preview time", + "Couleurs personnalisables" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/audio/WaveformViewer.tsx", + "frontend/src/hooks/useWaveform.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run WaveformViewer"] + }, + "ui_components": [], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T2-013", + "phase": "PHASE_2", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page My Tracks", + "description": "Liste des tracks de l'utilisateur", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008"], + "acceptance_criteria": [ + "Liste avec pagination", + "Filtres (status, date)", + "Actions (edit, delete)", + "Stats basiques" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/library/MyTracksPage.tsx", + "frontend/src/components/track/TrackListItem.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run MyTracks"] + }, + "ui_components": ["Table", "Pagination", "Button", "Badge", "ContextMenu"], + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T3-001", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "RUST", + "title": "Serveur HLS Streaming", + "description": "Serveur Rust pour delivery HLS haute performance", + "priority": "P0", + "status": "pending", + "estimated_hours": 20, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-007", "T0-007"], + "acceptance_criteria": [ + "Serving .m3u8 et .ts", + "Range requests support", + "Signed URL validation", + "Rate limiting par user" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "rust/streaming/src/handlers/hls.rs", + "rust/streaming/src/auth/verify.rs" + ] + }, + "commands": { + "verify": ["cd rust/streaming && cargo build"], + "test": ["cd rust/streaming && cargo test"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-002", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Stream URL", + "description": "Générer URL signée pour accès au stream", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-001"], + "acceptance_criteria": [ + "GET /tracks/:id/stream", + "URL signée (1h expiry)", + "Vérification droits d'accès", + "Log play event" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/stream_handler.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/stream_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/tracks/:id/stream" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-003", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Audio Engine", + "description": "Moteur audio avec HLS.js", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-002"], + "acceptance_criteria": [ + "Playback HLS via hls.js", + "Fallback audio natif", + "Events: timeupdate, ended, error", + "Quality switching" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/lib/audioEngine.ts", + "frontend/src/hooks/useAudioEngine.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run audioEngine"] + }, + "implementation_notes": "npm install hls.js", + "blockers": [] + }, + { + "id": "T3-004", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Player Store", + "description": "State management global pour le player", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-003"], + "acceptance_criteria": [ + "Current track state", + "Playback state", + "Volume state", + "Queue management", + "Shuffle/Repeat" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/stores/playerStore.ts", + "frontend/src/hooks/usePlayer.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run playerStore"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-005", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant PlayerBar", + "description": "Barre de lecture persistante", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-004", "T2-012"], + "acceptance_criteria": [ + "Cover, title, artist", + "Play/pause, prev/next", + "Progress bar cliquable", + "Volume slider", + "Expand vers full player" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/player/PlayerBar.tsx", + "frontend/src/components/player/PlayerControls.tsx", + "frontend/src/components/player/VolumeControl.tsx", + "frontend/src/components/player/ProgressBar.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run PlayerBar"] + }, + "ui_components": ["Button", "Slider", "Avatar", "WaveformViewer"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-006", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant FullPlayer", + "description": "Player plein écran", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-005"], + "acceptance_criteria": [ + "Waveform grande taille", + "Cover art large", + "Contrôles avancés", + "Queue visible", + "Animation transition" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/player/FullPlayer.tsx", + "frontend/src/components/player/QueuePanel.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run FullPlayer"] + }, + "ui_components": ["WaveformViewer", "Button", "Avatar", "List"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-007", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Playlists CRUD", + "description": "Endpoints pour gestion des playlists", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008"], + "acceptance_criteria": [ + "CRUD playlists", + "Add/remove tracks", + "Reorder tracks", + "Public/private visibility" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/playlist_handler.go", + "backend/internal/services/playlist_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/playlist_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/playlists" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-008", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Playlist", + "description": "Vue playlist avec tracks", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-007"], + "acceptance_criteria": [ + "Header playlist", + "Liste tracks ordonnée", + "Play all / Shuffle", + "Reorder drag & drop", + "Share" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/playlist/PlaylistPage.tsx", + "frontend/src/components/playlist/PlaylistHeader.tsx", + "frontend/src/components/playlist/PlaylistTrackList.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run Playlist"] + }, + "ui_components": ["Avatar", "Button", "DraggableList", "TrackListItem"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T3-009", + "phase": "PHASE_3", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Keyboard Shortcuts & Media Session", + "description": "Raccourcis clavier et intégration OS", + "priority": "P1", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T3-004"], + "acceptance_criteria": [ + "Space = play/pause", + "Arrows = seek/volume", + "Media Session API", + "Notifications OS" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/hooks/useKeyboardShortcuts.ts", + "frontend/src/lib/mediaSession.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run useKeyboardShortcuts"] + }, + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T4-001", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "RUST", + "title": "WebSocket Server Core", + "description": "Serveur WebSocket avec Tokio/Axum", + "priority": "P0", + "status": "pending", + "estimated_hours": 20, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-007"], + "acceptance_criteria": [ + "Connexion WS authentifiée (JWT)", + "Heartbeat/Ping-Pong", + "Reconnexion handling", + "Connection pool management" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "rust/chat/src/ws/server.rs", + "rust/chat/src/ws/connection.rs", + "rust/chat/src/auth/jwt.rs" + ] + }, + "commands": { + "verify": ["cd rust/chat && cargo build"], + "test": ["cd rust/chat && cargo test"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-002", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "RUST", + "title": "Room Management", + "description": "Gestion des rooms de chat", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-001"], + "acceptance_criteria": [ + "Join/Leave room", + "Broadcast to room", + "Room state tracking", + "Member list" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "rust/chat/src/room/manager.rs", + "rust/chat/src/room/room.rs" + ] + }, + "commands": { + "verify": ["cd rust/chat && cargo build"], + "test": ["cd rust/chat && cargo test room"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-003", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "RUST", + "title": "Message Handling", + "description": "Traitement et broadcast des messages", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-002"], + "acceptance_criteria": [ + "Send/Receive messages", + "Message validation", + "Rate limiting", + "Persistence via Go API" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "rust/chat/src/message/handler.rs", + "rust/chat/src/message/types.rs" + ] + }, + "commands": { + "verify": ["cd rust/chat && cargo build"], + "test": ["cd rust/chat && cargo test message"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-004", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "RUST", + "title": "Presence System", + "description": "Tracking présence utilisateurs", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-001"], + "acceptance_criteria": [ + "Online/Offline status", + "Typing indicators", + "Last seen", + "Broadcast presence" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "rust/chat/src/presence/tracker.rs", + "rust/chat/src/presence/types.rs" + ] + }, + "commands": { + "verify": ["cd rust/chat && cargo build"], + "test": ["cd rust/chat && cargo test presence"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-005", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Rooms & Messages", + "description": "REST API pour rooms et messages", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "CRUD rooms", + "GET messages history", + "Pagination cursor-based" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/room_handler.go", + "backend/internal/handlers/message_handler.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/room_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/rooms" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-006", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "WebSocket Client", + "description": "Client WebSocket avec reconnexion", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-001"], + "acceptance_criteria": [ + "Connexion avec JWT", + "Reconnexion exponentielle", + "Queue messages offline", + "Events handling" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/lib/websocket.ts", + "frontend/src/hooks/useWebSocket.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run websocket"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-007", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Chat Store", + "description": "State management pour le chat", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-006"], + "acceptance_criteria": [ + "Rooms list", + "Messages par room", + "Presence state", + "Unread counts" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/stores/chatStore.ts", + "frontend/src/hooks/useChat.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run chatStore"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-008", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composant ChatWindow", + "description": "Fenêtre de chat complète", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-007"], + "acceptance_criteria": [ + "Liste messages virtualisée", + "Input avec validation", + "Typing indicator", + "Load more historique", + "Auto-scroll" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/chat/ChatWindow.tsx", + "frontend/src/components/chat/MessageList.tsx", + "frontend/src/components/chat/ChatInput.tsx", + "frontend/src/components/chat/MessageBubble.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run ChatWindow"] + }, + "ui_components": ["Input", "Button", "Avatar", "Spinner", "VirtualList"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T4-009", + "phase": "PHASE_4", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Chat", + "description": "Page principale de chat", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T4-008"], + "acceptance_criteria": [ + "Layout sidebar + main", + "Room list", + "Create room modal", + "Responsive mobile" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/chat/ChatPage.tsx", + "frontend/src/components/chat/RoomList.tsx", + "frontend/src/components/chat/RoomItem.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run ChatPage"] + }, + "ui_components": ["ChatWindow", "RoomList", "Modal", "Button"], + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T5-001", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "BACKEND", + "title": "Meilisearch Integration", + "description": "Intégration moteur de recherche", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008"], + "acceptance_criteria": [ + "Index tracks, users, playlists", + "Sync automatique", + "Recherche fuzzy", + "Facettes (genre, BPM)" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/services/search_service.go", + "backend/internal/workers/indexer_worker.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/services/search_service_test.go -v"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-002", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Search", + "description": "Endpoint de recherche unifié", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T5-001"], + "acceptance_criteria": [ + "GET /search?q=...", + "Filtres: type, genre, bpm", + "Pagination", + "Highlighting" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/search_handler.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/search_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/search" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-003", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "SearchBar avec Autocomplete", + "description": "Barre de recherche globale", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T5-002"], + "acceptance_criteria": [ + "Input avec debounce", + "Dropdown suggestions", + "Keyboard navigation", + "Recent searches" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/search/SearchBar.tsx", + "frontend/src/components/search/SuggestionList.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run SearchBar"] + }, + "ui_components": ["Input", "Dropdown", "List", "Avatar"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-004", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Search Results", + "description": "Page de résultats de recherche", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T5-002"], + "acceptance_criteria": [ + "Tabs: All, Tracks, Users, Playlists", + "Filtres sidebar", + "Sort options", + "Pagination" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/search/SearchPage.tsx", + "frontend/src/components/search/SearchFilters.tsx", + "frontend/src/components/search/SearchResults.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run SearchPage"] + }, + "ui_components": ["Tabs", "Select", "Pagination", "Card", "TrackCard", "UserCard"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-005", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Explore", + "description": "Contenu à découvrir", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008"], + "acceptance_criteria": [ + "GET /explore/trending", + "GET /explore/new", + "GET /explore/genres" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/explore_handler.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/explore_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/explore/trending" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-006", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Explore/Home", + "description": "Page d'accueil avec découverte", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T5-005"], + "acceptance_criteria": [ + "Hero section", + "Trending carousel", + "New releases", + "Genre grid", + "Featured playlists" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/explore/ExplorePage.tsx", + "frontend/src/components/explore/TrendingSection.tsx", + "frontend/src/components/explore/GenreGrid.tsx", + "frontend/src/components/explore/FeaturedPlaylists.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run ExplorePage"] + }, + "ui_components": ["Carousel", "Card", "Grid", "TrackCard", "PlaylistCard"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T5-007", + "phase": "PHASE_5", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page Track Detail", + "description": "Page détail d'un track", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008", "T2-012"], + "acceptance_criteria": [ + "Waveform large", + "Metadata complètes", + "Actions (play, add, share)", + "Related tracks" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/track/TrackPage.tsx", + "frontend/src/components/track/TrackHeader.tsx", + "frontend/src/components/track/RelatedTracks.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run TrackPage"] + }, + "ui_components": ["WaveformViewer", "Button", "Avatar", "Card"], + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T6-001", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Notifications", + "description": "Système de notifications", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-002"], + "acceptance_criteria": [ + "GET /notifications", + "PATCH /notifications/:id/read", + "Types: follow, like, comment" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/notification_handler.go", + "backend/internal/services/notification_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/notification_handler_test.go -v"] + }, + "api": { + "method": "GET", + "path": "/api/v1/notifications" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T6-002", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Notification Bell", + "description": "Composant notification header", + "priority": "P0", + "status": "pending", + "estimated_hours": 8, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-001"], + "acceptance_criteria": [ + "Badge unread count", + "Dropdown liste", + "Mark all as read", + "Link vers page" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/notification/NotificationBell.tsx", + "frontend/src/components/notification/NotificationDropdown.tsx", + "frontend/src/stores/notificationStore.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run NotificationBell"] + }, + "ui_components": ["Badge", "Dropdown", "List", "Button"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T6-003", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Follow", + "description": "Système de follow/unfollow", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-009"], + "acceptance_criteria": [ + "POST /users/:id/follow", + "DELETE /users/:id/follow", + "GET followers/following" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/follow_handler.go", + "backend/internal/services/follow_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/follow_handler_test.go -v"] + }, + "api": { + "method": "POST", + "path": "/api/v1/users/:id/follow" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T6-004", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "BACKEND", + "title": "API Likes", + "description": "Système de likes", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T2-008"], + "acceptance_criteria": [ + "POST /tracks/:id/like", + "DELETE /tracks/:id/like", + "GET /users/me/likes" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/internal/handlers/like_handler.go", + "backend/internal/services/like_service.go" + ] + }, + "commands": { + "verify": ["cd backend && go build ./..."], + "test": ["cd backend && go test ./internal/handlers/like_handler_test.go -v"] + }, + "api": { + "method": "POST", + "path": "/api/v1/tracks/:id/like" + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T6-005", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Composants Social", + "description": "FollowButton et LikeButton", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-003", "T6-004"], + "acceptance_criteria": [ + "FollowButton avec états", + "LikeButton avec animation", + "Optimistic updates" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/social/FollowButton.tsx", + "frontend/src/components/social/LikeButton.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run Social"] + }, + "ui_components": ["Button"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T6-006", + "phase": "PHASE_6", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Page User Profile Public", + "description": "Profil public d'un utilisateur", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T1-009", "T6-003"], + "acceptance_criteria": [ + "Header profil", + "Tabs: Tracks, Playlists, Likes", + "Follow button", + "Stats followers" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/user/UserProfilePage.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run UserProfile"] + }, + "ui_components": ["Avatar", "Button", "Tabs", "Grid", "FollowButton"], + "implementation_notes": null, + "blockers": [] + }, + + { + "id": "T7-001", + "phase": "PHASE_7", + "type": "PERF", + "domain": "FRONTEND", + "title": "Performance Optimization", + "description": "Optimisation performance frontend", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "Lighthouse >= 90", + "FCP < 1.5s", + "Bundle size optimisé", + "Code splitting" + ], + "files": { + "to_check": ["frontend/src/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd frontend && npm run build:analyze"], + "test": ["npx lighthouse http://localhost:3000 --output=json"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-002", + "phase": "PHASE_7", + "type": "A11Y", + "domain": "FRONTEND", + "title": "Accessibility Audit", + "description": "Validation accessibilité WCAG AA", + "priority": "P0", + "status": "pending", + "estimated_hours": 16, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "0 erreurs Axe", + "Navigation clavier complète", + "ARIA labels", + "Focus visible" + ], + "files": { + "to_check": ["frontend/src/"], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["cd frontend && npm run test:a11y"], + "test": ["npx axe-core http://localhost:3000"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-003", + "phase": "PHASE_7", + "type": "SEO", + "domain": "FRONTEND", + "title": "SEO Implementation", + "description": "Optimisation SEO", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "Meta tags dynamiques", + "Open Graph", + "Sitemap.xml", + "robots.txt" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/components/SEO.tsx", + "frontend/public/sitemap.xml", + "frontend/public/robots.txt" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": [] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-004", + "phase": "PHASE_7", + "type": "SECURITY", + "domain": "ALL", + "title": "Security Audit", + "description": "Audit sécurité complet", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "OWASP Top 10 vérifié", + "Dependencies scan", + "Secrets management", + "CSP headers" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [] + }, + "commands": { + "verify": ["npm audit", "cd backend && go mod verify"], + "test": ["trivy fs ."] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-005", + "phase": "PHASE_7", + "type": "CONFIG", + "domain": "DEVOPS", + "title": "Production Deployment", + "description": "Configuration déploiement production", + "priority": "P0", + "status": "pending", + "estimated_hours": 14, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T0-009"], + "acceptance_criteria": [ + "HTTPS configuré", + "CDN pour assets", + "Monitoring (Prometheus/Grafana)", + "Backups automatiques" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "docker-compose.prod.yml", + "deploy/kubernetes/", + "monitoring/" + ] + }, + "commands": { + "verify": ["make deploy-prod"], + "test": ["curl -I https://veza.app"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-006", + "phase": "PHASE_7", + "type": "DOC", + "domain": "DOCS", + "title": "API Documentation", + "description": "Documentation Swagger/OpenAPI", + "priority": "P0", + "status": "pending", + "estimated_hours": 10, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "Swagger UI accessible", + "Tous endpoints documentés", + "Exemples requêtes/réponses", + "Auth documentation" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "backend/docs/swagger.yaml" + ] + }, + "commands": { + "verify": ["make swagger"], + "test": ["curl http://localhost:8080/swagger/"] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-007", + "phase": "PHASE_7", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Landing Page", + "description": "Page d'accueil marketing", + "priority": "P0", + "status": "pending", + "estimated_hours": 12, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": [], + "acceptance_criteria": [ + "Hero section", + "Features showcase", + "CTA inscription", + "Responsive" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/LandingPage.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": ["cd frontend && npm run test -- --run LandingPage"] + }, + "ui_components": ["Button", "Card", "Carousel"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-008", + "phase": "PHASE_7", + "type": "FEATURE", + "domain": "FRONTEND", + "title": "Error Pages", + "description": "Pages d'erreur personnalisées", + "priority": "P0", + "status": "pending", + "estimated_hours": 4, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": [], + "acceptance_criteria": [ + "404 avec suggestions", + "500 avec retry", + "Offline page" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/errors/NotFoundPage.tsx", + "frontend/src/pages/errors/ServerErrorPage.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": [] + }, + "ui_components": ["Button", "Card"], + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-009", + "phase": "PHASE_7", + "type": "LEGAL", + "domain": "FRONTEND", + "title": "Pages Légales", + "description": "CGU, Privacy, RGPD", + "priority": "P0", + "status": "pending", + "estimated_hours": 6, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": [], + "acceptance_criteria": [ + "CGU/CGV", + "Politique confidentialité", + "Cookie banner RGPD" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/src/pages/legal/TermsPage.tsx", + "frontend/src/pages/legal/PrivacyPage.tsx", + "frontend/src/components/CookieBanner.tsx" + ] + }, + "commands": { + "verify": ["cd frontend && npm run build"], + "test": [] + }, + "implementation_notes": null, + "blockers": [] + }, + { + "id": "T7-010", + "phase": "PHASE_7", + "type": "TEST", + "domain": "E2E", + "title": "Tests E2E Complets", + "description": "Suite complète tests Playwright", + "priority": "P0", + "status": "pending", + "estimated_hours": 20, + "actual_hours": null, + "started_at": null, + "completed_at": null, + "dependencies": ["T6-006"], + "acceptance_criteria": [ + "Tous flows critiques testés", + "Tests cross-browser", + "CI integration" + ], + "files": { + "to_check": [], + "to_modify": [], + "created": [ + "frontend/tests/e2e/critical-flows.spec.ts" + ] + }, + "commands": { + "verify": ["cd frontend && npx playwright test"], + "test": ["cd frontend && npx playwright test --reporter=html"] + }, + "implementation_notes": null, + "blockers": [] + } + ] +} diff --git a/veza-backend-api/go.mod b/veza-backend-api/go.mod index d2e944420..e7fdbe2f9 100644 --- a/veza-backend-api/go.mod +++ b/veza-backend-api/go.mod @@ -3,6 +3,11 @@ module veza-backend-api go 1.23.8 require ( + github.com/aws/aws-sdk-go-v2 v1.41.0 + github.com/aws/aws-sdk-go-v2/config v1.32.6 + github.com/aws/aws-sdk-go-v2/credentials v1.19.6 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18 + github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e @@ -18,6 +23,7 @@ require ( github.com/pquerna/otp v1.5.0 github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_model v0.6.2 + github.com/prometheus/common v0.63.0 github.com/rabbitmq/amqp091-go v1.10.0 github.com/redis/go-redis/v9 v9.16.0 github.com/sony/gobreaker v1.0.0 @@ -45,12 +51,8 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/aws/aws-sdk-go-v2 v1.41.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.6 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.6 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect @@ -59,7 +61,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect @@ -126,7 +127,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect diff --git a/veza-backend-api/go.sum b/veza-backend-api/go.sum index 14c9e3a52..f00aeb95d 100644 --- a/veza-backend-api/go.sum +++ b/veza-backend-api/go.sum @@ -177,6 +177,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -230,6 +232,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=