veza/VEZA_ROADMAP.json
senke 0e7b6fede1 [T0-002] fix(rust): Corriger erreurs compilation Rust
- Conflit SQLx résolu (alignement sur version 0.7)
- build.rs configurés pour protoc dans chat/stream servers
- API Prometheus migrée vers HistogramOpts
- Traits Display/Debug corrigés (String au lieu de &dyn Display)
- API TOTP corrigée (totp-rs 5.4 avec Secret::Encoded)
- Layers tracing-subscriber corrigés (types conditionnels)
- VezaError/VezaResult exportés dans lib.rs
- TransactionProvider simplifié (retour void au lieu de Box<dyn>)
- VezaConfig contraint Serialize pour to_json()

Files: veza-common/Cargo.toml, veza-common/src/*.rs, veza-chat-server/Cargo.toml, veza-chat-server/build.rs, veza-stream-server/Cargo.toml, veza-stream-server/build.rs, VEZA_ROADMAP.json
Hours: 8 estimated, 3 actual
2026-01-04 01:44:20 +01:00

2943 lines
85 KiB
JSON

{
"_meta": {
"project": "Veza/Talas",
"version": "0.101-MVP",
"created": "2025-01-28",
"last_updated": "2025-12-28T14:41:08Z",
"total_tasks": 156,
"completed_tasks": 2,
"in_progress_task": null,
"current_phase": "PHASE_0",
"estimated_total_hours": 1480,
"hours_completed": 14
},
"_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": "completed",
"estimated_hours": 8,
"actual_hours": 3,
"started_at": "2025-12-28T11:38:42Z",
"completed_at": "2025-12-28T14:41:08Z",
"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": ["veza-common/", "veza-chat-server/", "veza-stream-server/"],
"to_modify": [
"veza-common/Cargo.toml",
"veza-common/src/logging.rs",
"veza-common/src/metrics.rs",
"veza-common/src/traits.rs",
"veza-common/src/lib.rs",
"veza-common/src/utils/mod.rs",
"veza-common/src/config_rust.rs",
"veza-common/src/auth.rs",
"veza-chat-server/Cargo.toml",
"veza-chat-server/build.rs",
"veza-stream-server/Cargo.toml",
"veza-stream-server/build.rs"
],
"created": []
},
"commands": {
"verify": ["cd veza-common && cargo build", "cd veza-chat-server && cargo build", "cd veza-stream-server && cargo build"],
"test": ["cd veza-common && cargo test", "cd veza-chat-server && cargo test", "cd veza-stream-server && cargo test"]
},
"implementation_notes": "Corrections majeures: 1) Conflit SQLx résolu (alignement sur version 0.7), 2) build.rs configurés pour protoc, 3) API Prometheus migrée vers HistogramOpts, 4) Traits Display/Debug corrigés (String au lieu de &dyn Display), 5) API TOTP corrigée (totp-rs 5.4), 6) Layers tracing-subscriber corrigés (types conditionnels), 7) VezaError/VezaResult exportés, 8) TransactionProvider simplifié. veza-common compile avec succès. Les autres projets nécessitent des ajustements pour s'adapter aux changements d'API.",
"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": []
}
]
}