[BE-SEC-001] security: Fix ownership verification for user profile updates
- Verified RequireOwnershipOrAdmin middleware is correctly applied to PUT /users/:id - Added integration tests for ownership verification - Test: user cannot update another user's profile (403 Forbidden) - Test: admin can update any profile (200 OK) - Test: user can update own profile (200 OK) - All tests pass Phase: PHASE-1 Priority: P0 Progress: 1/267 (0.4%)
This commit is contained in:
parent
37120e8dd1
commit
b9821db707
7 changed files with 12301 additions and 0 deletions
628
VEZA_COMPLETE_AUDIT_PROMPT.md
Normal file
628
VEZA_COMPLETE_AUDIT_PROMPT.md
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
# VEZA Complete MVP Audit & Todolist Generator
|
||||
|
||||
## 🎯 Mission
|
||||
|
||||
Tu es un agent d'audit exhaustif. Ta mission est de scanner **l'intégralité** du codebase Veza et générer une **todolist de 200+ tâches** couvrant tout ce qui est nécessaire pour atteindre un **MVP stable prêt pour la production à petite échelle**.
|
||||
|
||||
**RÈGLE ABSOLUE** : Ne JAMAIS ignorer, skipper ou supprimer une feature/route/fonction. Si quelque chose existe côté frontend mais pas backend (ou inversement), **AJOUTE UNE TÂCHE** pour l'implémenter. L'objectif est la **progression**, pas la régression ni la stagnation.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Répertoires à Scanner
|
||||
|
||||
```
|
||||
veza/
|
||||
├── apps/web/ # Frontend React/TypeScript (SCAN COMPLET)
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # Composants UI
|
||||
│ │ ├── features/ # Features par domaine
|
||||
│ │ ├── hooks/ # Custom hooks
|
||||
│ │ ├── pages/ # Pages/routes
|
||||
│ │ ├── services/ # Services API
|
||||
│ │ ├── stores/ # State management
|
||||
│ │ ├── types/ # Types TypeScript
|
||||
│ │ ├── utils/ # Utilitaires
|
||||
│ │ └── schemas/ # Validation Zod
|
||||
│ ├── public/
|
||||
│ └── tests/
|
||||
│
|
||||
├── veza-backend-api/ # Backend Go/Gin (SCAN COMPLET)
|
||||
│ ├── cmd/ # Entry points
|
||||
│ ├── internal/
|
||||
│ │ ├── api/ # Routes & handlers
|
||||
│ │ ├── config/ # Configuration
|
||||
│ │ ├── dto/ # Data Transfer Objects
|
||||
│ │ ├── middleware/ # Middlewares
|
||||
│ │ ├── models/ # Database models
|
||||
│ │ ├── repository/ # Data access
|
||||
│ │ ├── services/ # Business logic
|
||||
│ │ └── errors/ # Error handling
|
||||
│ └── migrations/
|
||||
│
|
||||
├── veza-common/ # Shared code (SI EXISTE)
|
||||
├── veza-chat-server/ # Chat server Rust (SI EXISTE)
|
||||
├── veza-stream-server/ # Streaming server (SI EXISTE)
|
||||
├── docker-compose*.yml # Infrastructure
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Protocole d'Audit Exhaustif
|
||||
|
||||
### ÉTAPE 1 : Cartographie du Frontend (apps/web/)
|
||||
|
||||
```bash
|
||||
# 1.1 Lister TOUTES les routes/pages
|
||||
find apps/web/src/pages apps/web/src/features/*/pages -name "*.tsx" 2>/dev/null
|
||||
|
||||
# 1.2 Lister TOUS les services API
|
||||
find apps/web/src/services apps/web/src/features/*/services -name "*.ts" 2>/dev/null
|
||||
|
||||
# 1.3 Lister TOUS les appels API
|
||||
grep -rn "apiClient\.\|axios\.\|fetch(" apps/web/src/ --include="*.ts" --include="*.tsx"
|
||||
|
||||
# 1.4 Lister TOUS les types/interfaces
|
||||
find apps/web/src/types apps/web/src/features/*/types -name "*.ts" 2>/dev/null
|
||||
|
||||
# 1.5 Lister TOUS les stores (state management)
|
||||
find apps/web/src/stores apps/web/src/features/*/stores -name "*.ts" 2>/dev/null
|
||||
|
||||
# 1.6 Lister TOUS les hooks custom
|
||||
find apps/web/src/hooks apps/web/src/features/*/hooks -name "*.ts" 2>/dev/null
|
||||
|
||||
# 1.7 Lister TOUS les composants
|
||||
find apps/web/src/components apps/web/src/features/*/components -name "*.tsx" 2>/dev/null
|
||||
|
||||
# 1.8 Lister TOUS les schemas de validation
|
||||
find apps/web/src/schemas apps/web/src/features/*/schemas -name "*.ts" 2>/dev/null
|
||||
|
||||
# 1.9 Lister les tests existants
|
||||
find apps/web/src -name "*.test.ts" -o -name "*.test.tsx" -o -name "*.spec.ts" 2>/dev/null
|
||||
```
|
||||
|
||||
### ÉTAPE 2 : Cartographie du Backend (veza-backend-api/)
|
||||
|
||||
```bash
|
||||
# 2.1 Lister TOUTES les routes définies
|
||||
grep -rn "router\.\(GET\|POST\|PUT\|DELETE\|PATCH\)" veza-backend-api/internal/api/
|
||||
|
||||
# 2.2 Lister TOUS les handlers
|
||||
find veza-backend-api/internal/handlers veza-backend-api/internal/api -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.3 Lister TOUS les models
|
||||
find veza-backend-api/internal/models -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.4 Lister TOUS les DTOs
|
||||
find veza-backend-api/internal/dto -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.5 Lister TOUS les services
|
||||
find veza-backend-api/internal/services -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.6 Lister TOUS les repositories
|
||||
find veza-backend-api/internal/repository -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.7 Lister TOUS les middlewares
|
||||
find veza-backend-api/internal/middleware -name "*.go" 2>/dev/null
|
||||
|
||||
# 2.8 Lister les migrations
|
||||
find veza-backend-api/migrations -name "*.sql" 2>/dev/null
|
||||
|
||||
# 2.9 Lister les tests existants
|
||||
find veza-backend-api -name "*_test.go" 2>/dev/null
|
||||
```
|
||||
|
||||
### ÉTAPE 3 : Analyse de l'Intégration
|
||||
|
||||
```bash
|
||||
# 3.1 Extraire TOUS les endpoints appelés par le frontend
|
||||
grep -rohn "apiClient\.[a-z]*\s*(\s*['\"\`][^'\"\`]*" apps/web/src/ | sort | uniq
|
||||
|
||||
# 3.2 Extraire TOUTES les routes backend
|
||||
grep -rn "router\.\(GET\|POST\|PUT\|DELETE\|PATCH\)" veza-backend-api/internal/api/ | grep -o '"[^"]*"' | sort | uniq
|
||||
|
||||
# 3.3 Comparer les deux listes pour trouver les gaps
|
||||
|
||||
# 3.4 Vérifier la cohérence des types
|
||||
# Frontend types vs Backend DTOs
|
||||
|
||||
# 3.5 Vérifier les variables d'environnement
|
||||
grep -rn "VITE_" apps/web/src/
|
||||
grep -rn "os.Getenv" veza-backend-api/
|
||||
```
|
||||
|
||||
### ÉTAPE 4 : Scanner les Autres Services (si présents)
|
||||
|
||||
```bash
|
||||
# veza-common
|
||||
ls -la veza-common/ 2>/dev/null
|
||||
|
||||
# veza-chat-server
|
||||
ls -la veza-chat-server/ 2>/dev/null
|
||||
grep -rn "route\|endpoint\|handler" veza-chat-server/src/ 2>/dev/null
|
||||
|
||||
# veza-stream-server
|
||||
ls -la veza-stream-server/ 2>/dev/null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Catégories de Tâches à Générer
|
||||
|
||||
Pour chaque élément trouvé, génère des tâches dans ces catégories :
|
||||
|
||||
### 1. BACKEND - Routes API (BE-API-XXX)
|
||||
- Routes manquantes appelées par le frontend
|
||||
- Routes existantes mais incomplètes
|
||||
- Validation des inputs manquante
|
||||
- Gestion des erreurs insuffisante
|
||||
- Documentation OpenAPI manquante
|
||||
|
||||
### 2. BACKEND - Models & Database (BE-DB-XXX)
|
||||
- Models manquants ou incomplets
|
||||
- Migrations manquantes
|
||||
- Index manquants
|
||||
- Relations mal définies
|
||||
- Soft delete non implémenté
|
||||
|
||||
### 3. BACKEND - Services & Logic (BE-SVC-XXX)
|
||||
- Business logic manquante
|
||||
- Validation métier manquante
|
||||
- Transactions non gérées
|
||||
- Caching non implémenté
|
||||
|
||||
### 4. BACKEND - Security (BE-SEC-XXX)
|
||||
- Authentication gaps
|
||||
- Authorization gaps
|
||||
- Rate limiting manquant
|
||||
- Input sanitization
|
||||
- CORS issues
|
||||
|
||||
### 5. BACKEND - Tests (BE-TEST-XXX)
|
||||
- Tests unitaires manquants
|
||||
- Tests d'intégration manquants
|
||||
- Coverage insuffisante
|
||||
|
||||
### 6. FRONTEND - Pages & Routes (FE-PAGE-XXX)
|
||||
- Pages incomplètes
|
||||
- Routes mal configurées
|
||||
- Layouts manquants
|
||||
- Navigation broken
|
||||
|
||||
### 7. FRONTEND - Components (FE-COMP-XXX)
|
||||
- Composants manquants
|
||||
- Props non typées
|
||||
- Accessibilité (a11y)
|
||||
- Responsive design
|
||||
- Error boundaries
|
||||
|
||||
### 8. FRONTEND - Services & API (FE-API-XXX)
|
||||
- Services API incomplets
|
||||
- Error handling manquant
|
||||
- Loading states manquants
|
||||
- Retry logic manquant
|
||||
|
||||
### 9. FRONTEND - State Management (FE-STATE-XXX)
|
||||
- Stores incomplets
|
||||
- State sync issues
|
||||
- Cache invalidation
|
||||
- Optimistic updates
|
||||
|
||||
### 10. FRONTEND - Types & Validation (FE-TYPE-XXX)
|
||||
- Types manquants ou incorrects
|
||||
- Zod schemas manquants
|
||||
- Runtime validation
|
||||
|
||||
### 11. FRONTEND - Tests (FE-TEST-XXX)
|
||||
- Tests unitaires manquants
|
||||
- Tests de composants manquants
|
||||
- Tests E2E manquants
|
||||
|
||||
### 12. INTEGRATION (INT-XXX)
|
||||
- Contract mismatches
|
||||
- Type inconsistencies
|
||||
- Missing endpoints
|
||||
- Response format issues
|
||||
|
||||
### 13. INFRASTRUCTURE (INFRA-XXX)
|
||||
- Docker configuration
|
||||
- Environment variables
|
||||
- CI/CD pipeline
|
||||
- Monitoring/Logging
|
||||
|
||||
### 14. DOCUMENTATION (DOC-XXX)
|
||||
- API documentation
|
||||
- README updates
|
||||
- Architecture docs
|
||||
- Deployment guide
|
||||
|
||||
### 15. SECURITY (SEC-XXX)
|
||||
- Authentication issues
|
||||
- Authorization issues
|
||||
- Data exposure risks
|
||||
- Dependency vulnerabilities
|
||||
|
||||
---
|
||||
|
||||
## 📊 Format de Sortie JSON
|
||||
|
||||
Génère le fichier `VEZA_COMPLETE_MVP_TODOLIST.json` avec cette structure :
|
||||
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"title": "Veza Complete MVP Todolist",
|
||||
"description": "Exhaustive todolist for production-ready MVP",
|
||||
"generated_at": "ISO_TIMESTAMP",
|
||||
"total_tasks": 200,
|
||||
"target": "Production-ready MVP at small scale",
|
||||
"scanned_directories": [
|
||||
"apps/web/",
|
||||
"veza-backend-api/",
|
||||
"veza-common/",
|
||||
"..."
|
||||
],
|
||||
"audit_methodology": "Full codebase scan + integration analysis"
|
||||
},
|
||||
"summary": {
|
||||
"by_priority": {
|
||||
"P0_critical": 0,
|
||||
"P1_high": 0,
|
||||
"P2_medium": 0,
|
||||
"P3_low": 0
|
||||
},
|
||||
"by_category": {
|
||||
"BE-API": 0,
|
||||
"BE-DB": 0,
|
||||
"BE-SVC": 0,
|
||||
"BE-SEC": 0,
|
||||
"BE-TEST": 0,
|
||||
"FE-PAGE": 0,
|
||||
"FE-COMP": 0,
|
||||
"FE-API": 0,
|
||||
"FE-STATE": 0,
|
||||
"FE-TYPE": 0,
|
||||
"FE-TEST": 0,
|
||||
"INT": 0,
|
||||
"INFRA": 0,
|
||||
"DOC": 0,
|
||||
"SEC": 0
|
||||
},
|
||||
"by_owner": {
|
||||
"backend": 0,
|
||||
"frontend": 0,
|
||||
"fullstack": 0,
|
||||
"devops": 0
|
||||
},
|
||||
"estimated_total_hours": 0
|
||||
},
|
||||
"phases": [
|
||||
{
|
||||
"id": "PHASE-1",
|
||||
"name": "Critical Foundation",
|
||||
"description": "Must fix before any other work",
|
||||
"priority": "P0",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-2",
|
||||
"name": "Core Features Completion",
|
||||
"description": "Complete essential user-facing features",
|
||||
"priority": "P1",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-3",
|
||||
"name": "Integration & Consistency",
|
||||
"description": "Ensure frontend/backend work seamlessly",
|
||||
"priority": "P1",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-4",
|
||||
"name": "Security Hardening",
|
||||
"description": "Security measures for production",
|
||||
"priority": "P1",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-5",
|
||||
"name": "Testing & Quality",
|
||||
"description": "Test coverage and code quality",
|
||||
"priority": "P2",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-6",
|
||||
"name": "Performance & Optimization",
|
||||
"description": "Optimize for production load",
|
||||
"priority": "P2",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-7",
|
||||
"name": "Documentation & DevOps",
|
||||
"description": "Documentation and deployment readiness",
|
||||
"priority": "P2",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
},
|
||||
{
|
||||
"id": "PHASE-8",
|
||||
"name": "Polish & UX",
|
||||
"description": "UI/UX improvements and polish",
|
||||
"priority": "P3",
|
||||
"estimated_days": 0,
|
||||
"tasks": []
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "BE-API-001",
|
||||
"phase": "PHASE-2",
|
||||
"priority": "P1",
|
||||
"priority_rank": 1,
|
||||
"category": "backend-api",
|
||||
"title": "Task title",
|
||||
"description": "Detailed description",
|
||||
"owner": "backend",
|
||||
"estimated_hours": 2,
|
||||
"status": "todo",
|
||||
"files_involved": [
|
||||
{
|
||||
"path": "veza-backend-api/internal/...",
|
||||
"action": "create|modify|delete",
|
||||
"reason": "Why this file"
|
||||
}
|
||||
],
|
||||
"implementation_steps": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "What to do",
|
||||
"details": "How to do it"
|
||||
}
|
||||
],
|
||||
"acceptance_criteria": [
|
||||
"Criterion 1",
|
||||
"Criterion 2"
|
||||
],
|
||||
"dependencies": ["OTHER-TASK-ID"],
|
||||
"related_frontend": "FE-XXX-YYY",
|
||||
"related_backend": "BE-XXX-YYY",
|
||||
"test_requirements": [
|
||||
"Unit test for...",
|
||||
"Integration test for..."
|
||||
],
|
||||
"notes": "Additional context"
|
||||
}
|
||||
],
|
||||
"gap_analysis": {
|
||||
"frontend_calls_without_backend": [
|
||||
{
|
||||
"frontend_location": "apps/web/src/services/xxx.ts:42",
|
||||
"endpoint_called": "GET /api/v1/something",
|
||||
"backend_status": "NOT_FOUND",
|
||||
"task_created": "BE-API-XXX"
|
||||
}
|
||||
],
|
||||
"backend_routes_without_frontend": [
|
||||
{
|
||||
"backend_location": "veza-backend-api/internal/api/router.go:123",
|
||||
"endpoint_defined": "POST /api/v1/something-else",
|
||||
"frontend_usage": "NOT_FOUND",
|
||||
"task_created": "FE-API-XXX"
|
||||
}
|
||||
],
|
||||
"type_mismatches": [
|
||||
{
|
||||
"frontend_type": "apps/web/src/types/user.ts - id: number",
|
||||
"backend_type": "veza-backend-api/internal/dto/user.go - ID: uuid.UUID",
|
||||
"task_created": "INT-XXX"
|
||||
}
|
||||
]
|
||||
},
|
||||
"risk_register": [
|
||||
{
|
||||
"risk": "Description of risk",
|
||||
"severity": "high|medium|low",
|
||||
"mitigation_tasks": ["TASK-ID-1", "TASK-ID-2"],
|
||||
"owner": "backend|frontend|devops"
|
||||
}
|
||||
],
|
||||
"mvp_definition": {
|
||||
"must_have_features": [
|
||||
{
|
||||
"feature": "User Authentication",
|
||||
"status": "complete|partial|missing",
|
||||
"tasks_required": ["BE-API-001", "FE-PAGE-001"]
|
||||
}
|
||||
],
|
||||
"nice_to_have": [
|
||||
{
|
||||
"feature": "Advanced Search",
|
||||
"tasks_if_included": ["BE-API-050", "FE-COMP-030"]
|
||||
}
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Feature X - reason"
|
||||
]
|
||||
},
|
||||
"progress_tracking": {
|
||||
"completed": 0,
|
||||
"in_progress": 0,
|
||||
"todo": 200,
|
||||
"blocked": 0,
|
||||
"last_updated": null,
|
||||
"completion_percentage": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔢 Règles de Priorisation
|
||||
|
||||
### P0 - Critical (Blocker)
|
||||
- L'app ne démarre pas
|
||||
- Crash systématique
|
||||
- Faille de sécurité majeure
|
||||
- Perte de données possible
|
||||
- Authentication cassée
|
||||
|
||||
### P1 - High (Core Feature)
|
||||
- Feature essentielle non fonctionnelle
|
||||
- Intégration frontend/backend cassée
|
||||
- UX bloquante pour l'utilisateur
|
||||
- Performance inacceptable
|
||||
|
||||
### P2 - Medium (Important)
|
||||
- Feature secondaire non fonctionnelle
|
||||
- Inconsistances visuelles
|
||||
- Tests manquants pour code critique
|
||||
- Documentation manquante
|
||||
|
||||
### P3 - Low (Nice to Have)
|
||||
- Améliorations UX mineures
|
||||
- Refactoring non urgent
|
||||
- Tests pour code non critique
|
||||
- Optimisations mineures
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Règles Absolues
|
||||
|
||||
### NE JAMAIS :
|
||||
- ❌ Ignorer une route/feature parce qu'elle n'est pas implémentée
|
||||
- ❌ Recommander de supprimer du code qui appelle des endpoints manquants
|
||||
- ❌ Sauter des fichiers "parce qu'ils semblent obsolètes"
|
||||
- ❌ Limiter l'audit à certains dossiers seulement
|
||||
- ❌ Générer moins de 200 tâches
|
||||
|
||||
### TOUJOURS :
|
||||
- ✅ Créer une tâche pour implémenter ce qui manque
|
||||
- ✅ Documenter les deux côtés (frontend + backend) pour chaque gap
|
||||
- ✅ Lier les tâches entre elles (dependencies, related_*)
|
||||
- ✅ Inclure des critères d'acceptation testables
|
||||
- ✅ Estimer les heures de travail
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Séquence d'Exécution
|
||||
|
||||
```
|
||||
1. SCAN FRONTEND
|
||||
└── Lister tous les fichiers
|
||||
└── Extraire tous les appels API
|
||||
└── Identifier tous les types
|
||||
└── Trouver tous les composants/pages
|
||||
└── Détecter les tests manquants
|
||||
|
||||
2. SCAN BACKEND
|
||||
└── Lister toutes les routes
|
||||
└── Extraire tous les handlers
|
||||
└── Identifier tous les models/DTOs
|
||||
└── Trouver tous les services
|
||||
└── Détecter les tests manquants
|
||||
|
||||
3. ANALYSE D'INTÉGRATION
|
||||
└── Comparer endpoints frontend vs backend
|
||||
└── Comparer types frontend vs DTOs backend
|
||||
└── Identifier TOUS les gaps
|
||||
└── Créer tâches pour chaque gap
|
||||
|
||||
4. SCAN SERVICES ANNEXES
|
||||
└── veza-common
|
||||
└── veza-chat-server
|
||||
└── veza-stream-server
|
||||
└── Autres...
|
||||
|
||||
5. ANALYSE SÉCURITÉ
|
||||
└── Auth/AuthZ gaps
|
||||
└── Input validation
|
||||
└── CORS/CSRF
|
||||
└── Secrets exposure
|
||||
|
||||
6. ANALYSE INFRA
|
||||
└── Docker configs
|
||||
└── Environment vars
|
||||
└── CI/CD gaps
|
||||
|
||||
7. GÉNÉRATION TODOLIST
|
||||
└── Créer toutes les tâches
|
||||
└── Assigner les priorités
|
||||
└── Calculer les estimations
|
||||
└── Organiser en phases
|
||||
└── Générer le JSON final
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📤 Output Attendu
|
||||
|
||||
À la fin de l'audit, tu dois produire :
|
||||
|
||||
1. **`VEZA_COMPLETE_MVP_TODOLIST.json`** — Le fichier JSON avec 200+ tâches
|
||||
2. **Résumé dans la conversation** :
|
||||
```
|
||||
══════════════════════════════════════════════════════
|
||||
📊 AUDIT COMPLET VEZA - RÉSUMÉ
|
||||
══════════════════════════════════════════════════════
|
||||
|
||||
Total tâches générées: XXX
|
||||
|
||||
Par priorité:
|
||||
• P0 (Critical): XX tâches
|
||||
• P1 (High): XX tâches
|
||||
• P2 (Medium): XX tâches
|
||||
• P3 (Low): XX tâches
|
||||
|
||||
Par catégorie:
|
||||
• Backend API: XX
|
||||
• Backend DB: XX
|
||||
• Backend Services: XX
|
||||
• Frontend Pages: XX
|
||||
• Frontend Components: XX
|
||||
• Integration: XX
|
||||
• Security: XX
|
||||
• Tests: XX
|
||||
• Infrastructure: XX
|
||||
• Documentation: XX
|
||||
|
||||
Gaps critiques détectés:
|
||||
• XX endpoints appelés par frontend mais non implémentés
|
||||
• XX routes backend sans utilisation frontend
|
||||
• XX type mismatches
|
||||
|
||||
Estimation totale: XXX heures (~XX semaines)
|
||||
|
||||
Fichier généré: VEZA_COMPLETE_MVP_TODOLIST.json
|
||||
══════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 COMMENCE MAINTENANT
|
||||
|
||||
1. **Lis la structure du projet** :
|
||||
```bash
|
||||
ls -la
|
||||
find . -type d -name "src" | head -20
|
||||
```
|
||||
|
||||
2. **Scanne le frontend** (apps/web/)
|
||||
|
||||
3. **Scanne le backend** (veza-backend-api/)
|
||||
|
||||
4. **Identifie les gaps d'intégration**
|
||||
|
||||
5. **Génère les 200+ tâches**
|
||||
|
||||
6. **Produis le fichier JSON final**
|
||||
|
||||
**Première action** : Lister la structure racine du projet et identifier tous les répertoires à scanner.
|
||||
9831
VEZA_COMPLETE_MVP_TODOLIST.json
Normal file
9831
VEZA_COMPLETE_MVP_TODOLIST.json
Normal file
File diff suppressed because it is too large
Load diff
406
VEZA_MVP_INFINITE_AGENT.md
Normal file
406
VEZA_MVP_INFINITE_AGENT.md
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
# VEZA MVP Implementation Agent — Infinite Loop Protocol
|
||||
|
||||
## 🎯 Mission
|
||||
|
||||
Tu es un agent d'implémentation autonome. Ta mission est d'implémenter **toutes les 267 tâches** du fichier `VEZA_COMPLETE_MVP_TODOLIST.json` jusqu'à atteindre un MVP stable prêt pour la production.
|
||||
|
||||
Tu travailles sur une **branche dédiée** et tu **commits après chaque tâche**.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Fichier Source de Vérité
|
||||
|
||||
```
|
||||
VEZA_COMPLETE_MVP_TODOLIST.json ← Todolist complète (267 tâches)
|
||||
```
|
||||
|
||||
Ce fichier DOIT être maintenu à jour après chaque tâche terminée.
|
||||
|
||||
---
|
||||
|
||||
## 🌿 Gestion de Branche Git
|
||||
|
||||
### Au Début de la Première Session
|
||||
|
||||
```bash
|
||||
# Vérifier la branche actuelle
|
||||
git branch --show-current
|
||||
|
||||
# Si pas sur la branche MVP, la créer ou y aller
|
||||
git checkout -b feature/mvp-complete 2>/dev/null || git checkout feature/mvp-complete
|
||||
|
||||
# S'assurer d'être à jour
|
||||
git pull origin feature/mvp-complete 2>/dev/null || echo "Nouvelle branche"
|
||||
```
|
||||
|
||||
### Au Début de Chaque Session Suivante
|
||||
|
||||
```bash
|
||||
# Revenir sur la branche MVP
|
||||
git checkout feature/mvp-complete
|
||||
|
||||
# Récupérer les derniers changements
|
||||
git pull origin feature/mvp-complete 2>/dev/null || echo "OK"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Cycle d'Implémentation (Boucle Infinie)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 1. LOAD & FIND │
|
||||
│ → Lire VEZA_COMPLETE_MVP_TODOLIST.json │
|
||||
│ → Trouver la tâche avec: │
|
||||
│ • status = "todo" │
|
||||
│ • Le plus petit priority_rank │
|
||||
│ → Si toutes complétées → MISSION ACCOMPLIE 🎉 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 2. ANNOUNCE │
|
||||
│ → Afficher: "🚀 [X/267] Tâche ID: TITRE" │
|
||||
│ → Lister les fichiers à modifier │
|
||||
│ → Vérifier les dépendances │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 3. IMPLEMENT │
|
||||
│ → Suivre les implementation_steps │
|
||||
│ → Modifier/créer les fichiers listés │
|
||||
│ → Respecter les acceptance_criteria │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 4. VALIDATE │
|
||||
│ → Compiler: TypeScript (npx tsc --noEmit) │
|
||||
│ → Compiler: Go (go build ./...) │
|
||||
│ → Vérifier les acceptance_criteria │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 5. UPDATE JSON │
|
||||
│ → Mettre status = "completed" │
|
||||
│ → Ajouter bloc "completion" avec détails │
|
||||
│ → Mettre à jour progress_tracking │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 6. COMMIT │
|
||||
│ → git add -A │
|
||||
│ → git commit avec message formaté │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 7. REPORT & CONTINUE │
|
||||
│ → Afficher le résumé │
|
||||
│ → Retour à l'étape 1 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Format de Mise à Jour du JSON
|
||||
|
||||
### Quand une Tâche est Complétée
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "BE-SEC-001",
|
||||
"status": "completed",
|
||||
"completion": {
|
||||
"completed_at": "2025-01-28T14:30:00Z",
|
||||
"actual_hours": 2.5,
|
||||
"commits": ["abc1234"],
|
||||
"files_changed": [
|
||||
"veza-backend-api/internal/api/router.go",
|
||||
"veza-backend-api/internal/handlers/profile_handler.go"
|
||||
],
|
||||
"notes": "Added ownership middleware, all tests pass",
|
||||
"issues_encountered": []
|
||||
},
|
||||
// ... reste inchangé
|
||||
}
|
||||
```
|
||||
|
||||
### Mise à Jour de progress_tracking
|
||||
|
||||
```json
|
||||
{
|
||||
"progress_tracking": {
|
||||
"completed": 1,
|
||||
"in_progress": 0,
|
||||
"todo": 266,
|
||||
"blocked": 0,
|
||||
"last_updated": "2025-01-28T14:30:00Z",
|
||||
"completion_percentage": 0.37
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Format de Commit
|
||||
|
||||
```bash
|
||||
git commit -m "[TASK-ID] CATEGORY: Title
|
||||
|
||||
- Change 1
|
||||
- Change 2
|
||||
- Change 3
|
||||
|
||||
Phase: PHASE-X
|
||||
Priority: PX
|
||||
Progress: Y/267 (Z%)"
|
||||
```
|
||||
|
||||
### Exemples
|
||||
|
||||
```bash
|
||||
git commit -m "[BE-SEC-001] security: Fix ownership verification for user profile updates
|
||||
|
||||
- Added userOwnerResolver function in router.go
|
||||
- Applied RequireOwnershipOrAdmin middleware to PUT /users/:id
|
||||
- Added unit tests for ownership verification
|
||||
|
||||
Phase: PHASE-1
|
||||
Priority: P0
|
||||
Progress: 1/267 (0.4%)"
|
||||
```
|
||||
|
||||
```bash
|
||||
git commit -m "[FE-COMP-015] component: Add loading skeleton for track list
|
||||
|
||||
- Created TrackListSkeleton component
|
||||
- Integrated with useTrackList hook
|
||||
- Added storybook story
|
||||
|
||||
Phase: PHASE-2
|
||||
Priority: P1
|
||||
Progress: 45/267 (16.9%)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Séquence de Démarrage (À Chaque Session)
|
||||
|
||||
```markdown
|
||||
## DÉMARRAGE SESSION
|
||||
|
||||
1. [ ] Vérifier/créer la branche
|
||||
git checkout feature/mvp-complete 2>/dev/null || git checkout -b feature/mvp-complete
|
||||
|
||||
2. [ ] Lire VEZA_COMPLETE_MVP_TODOLIST.json
|
||||
→ Noter progress_tracking.completed
|
||||
→ Calculer: X tâches restantes
|
||||
|
||||
3. [ ] Trouver la prochaine tâche
|
||||
→ status = "todo"
|
||||
→ Plus petit priority_rank
|
||||
|
||||
4. [ ] Annoncer:
|
||||
"📍 Session démarrée
|
||||
Progression: X/267 (Y%)
|
||||
Prochaine tâche: [ID] - [TITLE]
|
||||
Phase: PHASE-Z (Priority: PW)"
|
||||
|
||||
5. [ ] Commencer l'implémentation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Format de Rapport Après Chaque Tâche
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════════
|
||||
✅ COMPLÉTÉ: [TASK-ID] — [Title]
|
||||
═══════════════════════════════════════════════════════════════
|
||||
|
||||
Phase: PHASE-X | Priorité: PY | Durée: Zh XXmin
|
||||
|
||||
Fichiers modifiés:
|
||||
✓ path/to/file1.go
|
||||
✓ path/to/file2.ts
|
||||
|
||||
Validation:
|
||||
✓ TypeScript compile
|
||||
✓ Go build OK
|
||||
✓ Critères d'acceptation respectés
|
||||
|
||||
Commit: abc1234
|
||||
|
||||
───────────────────────────────────────────────────────────────
|
||||
📊 PROGRESSION
|
||||
───────────────────────────────────────────────────────────────
|
||||
|
||||
Complétées: X/267 (Y%)
|
||||
[████████░░░░░░░░░░░░░░░░░░░░░░] Y%
|
||||
|
||||
Par phase:
|
||||
PHASE-1 (P0): X/12
|
||||
PHASE-2 (P1): X/XX
|
||||
PHASE-3 (P1): X/XX
|
||||
...
|
||||
|
||||
Prochaine tâche: [NEXT-ID] — [Next Title]
|
||||
|
||||
═══════════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Gestion des Blocages
|
||||
|
||||
### Si une Dépendance n'est pas Satisfaite
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "TASK-ID",
|
||||
"status": "blocked",
|
||||
"blocked_info": {
|
||||
"blocked_at": "2025-01-28T14:30:00Z",
|
||||
"blocked_by": ["DEPENDENCY-ID"],
|
||||
"reason": "Dependency task not completed"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
→ Passer à la tâche suivante avec priority_rank le plus bas qui n'est pas bloquée.
|
||||
|
||||
### Si l'Implémentation Échoue
|
||||
|
||||
```bash
|
||||
# Annuler les changements
|
||||
git checkout -- .
|
||||
|
||||
# Marquer comme bloquée avec raison
|
||||
# Passer à la tâche suivante
|
||||
```
|
||||
|
||||
### Si TypeScript/Go ne Compile Pas
|
||||
|
||||
1. Identifier l'erreur
|
||||
2. Corriger si possible
|
||||
3. Si non corrigeable immédiatement → marquer comme blocked avec la raison
|
||||
4. Passer à la tâche suivante
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Commandes Utiles
|
||||
|
||||
```bash
|
||||
# === GIT ===
|
||||
git checkout feature/mvp-complete
|
||||
git add -A
|
||||
git commit -m "MESSAGE"
|
||||
git push origin feature/mvp-complete
|
||||
|
||||
# === VALIDATION ===
|
||||
cd apps/web && npx tsc --noEmit
|
||||
cd veza-backend-api && go build ./...
|
||||
cd apps/web && npm test -- --watchAll=false
|
||||
cd veza-backend-api && go test ./...
|
||||
|
||||
# === RECHERCHE ===
|
||||
grep -rn "PATTERN" apps/web/src/
|
||||
grep -rn "PATTERN" veza-backend-api/
|
||||
|
||||
# === STRUCTURE ===
|
||||
find apps/web/src -name "*.ts" -o -name "*.tsx" | head -20
|
||||
find veza-backend-api/internal -name "*.go" | head -20
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Règles d'Implémentation
|
||||
|
||||
### DO ✅
|
||||
- Suivre exactement les `implementation_steps`
|
||||
- Modifier uniquement les fichiers listés dans `files_involved`
|
||||
- Respecter tous les `acceptance_criteria`
|
||||
- Compiler après chaque modification
|
||||
- Committer après chaque tâche complète
|
||||
- Mettre à jour le JSON immédiatement
|
||||
|
||||
### DON'T ❌
|
||||
- Sauter des étapes d'implémentation
|
||||
- Modifier des fichiers non listés
|
||||
- Ignorer les erreurs de compilation
|
||||
- Oublier de committer
|
||||
- Oublier de mettre à jour le JSON
|
||||
- Changer de branche sans committer
|
||||
|
||||
---
|
||||
|
||||
## 📈 Milestones
|
||||
|
||||
```
|
||||
PHASE-1 (P0): 12 tâches → Fondation sécurisée
|
||||
PHASE-2 (P1): ~64 tâches → Features core complètes
|
||||
PHASE-3 (P1): ~35 tâches → Intégration parfaite
|
||||
PHASE-4 (P1): 15 tâches → Sécurité renforcée
|
||||
PHASE-5 (P2): ~43 tâches → Tests complets
|
||||
PHASE-6 (P2): ~34 tâches → Services optimisés
|
||||
PHASE-7 (P2): 19 tâches → Docs & DevOps
|
||||
PHASE-8 (P3): ~17 tâches → Polish final
|
||||
|
||||
TOTAL: 267 tâches → MVP Production-Ready 🚀
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏁 Condition de Fin
|
||||
|
||||
La mission est terminée quand:
|
||||
|
||||
```json
|
||||
{
|
||||
"progress_tracking": {
|
||||
"completed": 267,
|
||||
"in_progress": 0,
|
||||
"todo": 0,
|
||||
"blocked": 0,
|
||||
"completion_percentage": 100
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
À ce moment, afficher:
|
||||
|
||||
```
|
||||
╔═══════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🎉 MISSION ACCOMPLIE — MVP VEZA STABLE 🎉 ║
|
||||
║ ║
|
||||
║ 267/267 tâches complétées (100%) ║
|
||||
║ ║
|
||||
║ Prochaines étapes: ║
|
||||
║ 1. Merge feature/mvp-complete → main ║
|
||||
║ 2. Tag version v1.0.0-mvp ║
|
||||
║ 3. Déploiement production ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 COMMENCE MAINTENANT
|
||||
|
||||
```bash
|
||||
# 1. Créer/checkout la branche
|
||||
git checkout -b feature/mvp-complete 2>/dev/null || git checkout feature/mvp-complete
|
||||
|
||||
# 2. Lire le JSON et trouver la première tâche todo
|
||||
```
|
||||
|
||||
**Première action**:
|
||||
1. Lis `VEZA_COMPLETE_MVP_TODOLIST.json`
|
||||
2. Trouve la tâche avec `status: "todo"` et le plus petit `priority_rank`
|
||||
3. Annonce-la et commence l'implémentation
|
||||
|
||||
---
|
||||
|
||||
## 💡 PROMPT ULTRA-COURT (réutilisable)
|
||||
|
||||
Si tu veux relancer l'agent rapidement, utilise ce prompt minimal:
|
||||
|
||||
```
|
||||
Continue l'implémentation du MVP Veza.
|
||||
|
||||
Fichier: @VEZA_COMPLETE_MVP_TODOLIST.json
|
||||
Branche: feature/mvp-complete
|
||||
|
||||
Trouve la prochaine tâche (status: todo, plus petit priority_rank).
|
||||
Implémente-la.
|
||||
Mets à jour le JSON.
|
||||
Commit.
|
||||
Continue.
|
||||
```
|
||||
674
VEZA_MVP_VALIDATION_TODOLIST.json
Normal file
674
VEZA_MVP_VALIDATION_TODOLIST.json
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
{
|
||||
"meta": {
|
||||
"title": "Veza MVP Validation & Final Audit",
|
||||
"description": "Complete validation of 15 MVP fixes + final audit to reach stable state",
|
||||
"created_at": "2025-01-28T00:00:00Z",
|
||||
"previous_phase": "MVP Stability Fixes (15/15 completed)",
|
||||
"current_phase": "Validation & Final Audit",
|
||||
"target": "Confirmed stable MVP with no regressions",
|
||||
"estimated_effort": "3-5 hours"
|
||||
},
|
||||
"phases": [
|
||||
{
|
||||
"id": "PHASE-V1",
|
||||
"name": "Technical Validation",
|
||||
"description": "Verify all 15 MVP fixes compile and pass tests",
|
||||
"priority": "CRITICAL",
|
||||
"estimated_effort": "30 min",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "VAL-001",
|
||||
"title": "TypeScript Compilation Check",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "cd apps/web && npx tsc --noEmit",
|
||||
"expected_result": "Exit code 0, no errors",
|
||||
"failure_action": "List all errors, categorize by MVP fix that may have caused them",
|
||||
"related_mvp_fixes": ["MVP-003", "MVP-004", "MVP-010", "MVP-011", "MVP-015"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-002",
|
||||
"title": "Go Compilation Check",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "cd veza-backend-api && go build ./...",
|
||||
"expected_result": "Exit code 0, no errors",
|
||||
"failure_action": "List all errors, identify which MVP fix caused them",
|
||||
"related_mvp_fixes": ["MVP-001", "MVP-005", "MVP-009", "MVP-014"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-003",
|
||||
"title": "Frontend Unit Tests",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "cd apps/web && npm test -- --passWithNoTests --watchAll=false",
|
||||
"expected_result": "All tests pass",
|
||||
"failure_action": "List failing tests, identify regression source",
|
||||
"related_mvp_fixes": ["MVP-002", "MVP-003", "MVP-004", "MVP-015"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-004",
|
||||
"title": "Backend Unit Tests",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "cd veza-backend-api && go test ./... -v",
|
||||
"expected_result": "All tests pass",
|
||||
"failure_action": "List failing tests, identify regression source",
|
||||
"related_mvp_fixes": ["MVP-001", "MVP-009", "MVP-014"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-005",
|
||||
"title": "CORS Production Validation",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "cd veza-backend-api && APP_ENV=production CORS_ALLOWED_ORIGINS='' timeout 5 go run ./cmd/api || echo 'Expected failure'",
|
||||
"expected_result": "Server fails to start with clear CORS error message",
|
||||
"failure_action": "MVP-001 fix incomplete - server should not start without CORS in prod",
|
||||
"related_mvp_fixes": ["MVP-001"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-006",
|
||||
"title": "Legacy Code Removal - ApiService",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "grep -r 'ApiService' apps/web/src/ || echo 'PASS: No ApiService found'",
|
||||
"expected_result": "0 results (no ApiService references)",
|
||||
"failure_action": "MVP-004 incomplete - remove remaining ApiService references",
|
||||
"related_mvp_fixes": ["MVP-004"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-007",
|
||||
"title": "Legacy Code Removal - Token Storage Fragmentation",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "grep -r 'auth-storage' apps/web/src/services/ || echo 'PASS: No auth-storage in services'",
|
||||
"expected_result": "0 results in services directory",
|
||||
"failure_action": "MVP-002 incomplete - remove Zustand token storage fallback",
|
||||
"related_mvp_fixes": ["MVP-002"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-008",
|
||||
"title": "Environment Variable Consistency",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "grep -r 'VITE_API_BASE_URL' apps/web/ || echo 'PASS: No VITE_API_BASE_URL found'",
|
||||
"expected_result": "0 results (only VITE_API_URL should be used)",
|
||||
"failure_action": "MVP-006 incomplete - standardize env var names",
|
||||
"related_mvp_fixes": ["MVP-006"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-009",
|
||||
"title": "User.id Type Consistency",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "grep -rn 'id:\\s*number' apps/web/src/types/ apps/web/src/features/auth/types/ 2>/dev/null || echo 'PASS: No number id types'",
|
||||
"expected_result": "0 results for User-related id: number",
|
||||
"failure_action": "MVP-003 incomplete - fix remaining number types",
|
||||
"related_mvp_fixes": ["MVP-003"]
|
||||
},
|
||||
{
|
||||
"id": "VAL-010",
|
||||
"title": "Remember Me Field Consistency",
|
||||
"type": "automated",
|
||||
"status": "todo",
|
||||
"command": "grep -rn 'rememberMe' apps/web/src/ --include='*.ts' --include='*.tsx' | grep -v node_modules || echo 'PASS: No camelCase rememberMe'",
|
||||
"expected_result": "0 results (should be remember_me everywhere)",
|
||||
"failure_action": "MVP-015 incomplete - standardize to snake_case",
|
||||
"related_mvp_fixes": ["MVP-015"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PHASE-V2",
|
||||
"name": "Functional E2E Validation",
|
||||
"description": "Manual testing of critical user flows",
|
||||
"priority": "HIGH",
|
||||
"estimated_effort": "1 hour",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "E2E-001",
|
||||
"title": "Authentication Flow - Registration",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Navigate to /register",
|
||||
"Fill form with valid data (email, username, password)",
|
||||
"Submit form",
|
||||
"Verify redirect to dashboard or confirmation page",
|
||||
"Verify user data in localStorage (TokenStorage)",
|
||||
"Verify no 'auth-storage' key in localStorage"
|
||||
],
|
||||
"expected_result": "User registered, tokens stored via TokenStorage only",
|
||||
"failure_indicators": [
|
||||
"Registration form error",
|
||||
"API 4xx/5xx response",
|
||||
"Tokens not stored",
|
||||
"Multiple storage mechanisms detected"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-002", "MVP-003"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-002",
|
||||
"title": "Authentication Flow - Login",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Logout if logged in",
|
||||
"Navigate to /login",
|
||||
"Enter valid credentials",
|
||||
"Check 'Remember me' checkbox",
|
||||
"Submit form",
|
||||
"Verify login success",
|
||||
"Check localStorage for veza_access_token and veza_refresh_token",
|
||||
"Verify remember_me was sent correctly (check Network tab)"
|
||||
],
|
||||
"expected_result": "Login succeeds, tokens stored, remember_me sent as snake_case",
|
||||
"failure_indicators": [
|
||||
"Login rejected",
|
||||
"Token not stored",
|
||||
"rememberMe sent instead of remember_me"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-002", "MVP-015"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-003",
|
||||
"title": "Authentication Flow - Persistence",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Ensure logged in",
|
||||
"Hard refresh the page (Ctrl+Shift+R / Cmd+Shift+R)",
|
||||
"Verify still logged in",
|
||||
"Open new tab, navigate to app",
|
||||
"Verify logged in in new tab",
|
||||
"Close all tabs, reopen app",
|
||||
"Verify still logged in (if remember_me was checked)"
|
||||
],
|
||||
"expected_result": "Session persists across refresh, tabs, and browser restart",
|
||||
"failure_indicators": [
|
||||
"Logged out after refresh",
|
||||
"Different auth state across tabs",
|
||||
"Token lost"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-002", "MVP-011"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-004",
|
||||
"title": "Authentication Flow - Token Refresh",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Login with short-lived token (or manually expire token in localStorage)",
|
||||
"Make API request (e.g., load profile)",
|
||||
"Check Network tab for refresh token request",
|
||||
"Verify new tokens stored",
|
||||
"Verify original request succeeded after refresh"
|
||||
],
|
||||
"expected_result": "Token auto-refreshes, request succeeds transparently",
|
||||
"failure_indicators": [
|
||||
"401 error shown to user",
|
||||
"Logged out unexpectedly",
|
||||
"Multiple refresh requests (race condition)"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-002", "MVP-011"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-005",
|
||||
"title": "Authentication Flow - Logout",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Ensure logged in",
|
||||
"Click logout",
|
||||
"Verify redirect to login page",
|
||||
"Check localStorage - tokens should be cleared",
|
||||
"Try to access protected route",
|
||||
"Verify redirected to login"
|
||||
],
|
||||
"expected_result": "Clean logout, all tokens cleared, protected routes inaccessible",
|
||||
"failure_indicators": [
|
||||
"Tokens remain in localStorage",
|
||||
"Can still access protected routes",
|
||||
"Partial state remains"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-002"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-006",
|
||||
"title": "Profile - View and Edit",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Navigate to profile page",
|
||||
"Verify all user fields displayed (id, email, username, avatar, etc.)",
|
||||
"Edit a field (e.g., username)",
|
||||
"Save changes",
|
||||
"Refresh page",
|
||||
"Verify changes persisted"
|
||||
],
|
||||
"expected_result": "Profile loads with full user data, edits persist",
|
||||
"failure_indicators": [
|
||||
"Missing fields (only id, email, role)",
|
||||
"404 on profile endpoint",
|
||||
"Edits not saved"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-007", "MVP-009"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-007",
|
||||
"title": "API Error Handling - Request ID Correlation",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Open browser DevTools Console",
|
||||
"Trigger an API error (e.g., invalid request, 404)",
|
||||
"Check console for error log",
|
||||
"Verify request_id is included in log",
|
||||
"Check Network tab for same request_id in response"
|
||||
],
|
||||
"expected_result": "Error logs include request_id matching backend response",
|
||||
"failure_indicators": [
|
||||
"No request_id in console",
|
||||
"request_id mismatch",
|
||||
"Error not logged"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-013"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-008",
|
||||
"title": "API Error Handling - Retry Logic",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"If possible: Stop backend temporarily",
|
||||
"Or: Use browser DevTools to throttle/block requests",
|
||||
"Trigger API request",
|
||||
"Check Network tab for retry attempts",
|
||||
"Verify exponential backoff timing (1s, 2s, 4s)",
|
||||
"Restart backend / remove throttle",
|
||||
"Verify request eventually succeeds or fails gracefully after max retries"
|
||||
],
|
||||
"expected_result": "Transient errors (502/503) are retried with backoff",
|
||||
"failure_indicators": [
|
||||
"No retry attempts",
|
||||
"Immediate failure on first error",
|
||||
"No backoff between retries"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-012"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-009",
|
||||
"title": "CORS - Cross-Origin Request",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Run frontend on localhost:3000",
|
||||
"Run backend on localhost:8080",
|
||||
"Make API request from frontend",
|
||||
"Check Network tab for CORS headers",
|
||||
"Verify Access-Control-Allow-Origin matches frontend origin",
|
||||
"Verify Access-Control-Allow-Credentials: true"
|
||||
],
|
||||
"expected_result": "CORS headers present and correct, requests succeed",
|
||||
"failure_indicators": [
|
||||
"CORS error in console",
|
||||
"Missing Access-Control headers",
|
||||
"Preflight (OPTIONS) fails"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-001", "MVP-014"]
|
||||
},
|
||||
{
|
||||
"id": "E2E-010",
|
||||
"title": "Console Error Check",
|
||||
"type": "manual",
|
||||
"status": "todo",
|
||||
"steps": [
|
||||
"Open DevTools Console",
|
||||
"Clear console",
|
||||
"Navigate through: Login → Dashboard → Profile → Tracks → Playlists → Logout",
|
||||
"Note any errors or warnings",
|
||||
"Specifically check for: 404 errors, CORS errors, TypeScript runtime errors"
|
||||
],
|
||||
"expected_result": "No unexpected errors in console during normal navigation",
|
||||
"failure_indicators": [
|
||||
"404 errors (missing endpoints)",
|
||||
"CORS errors",
|
||||
"Uncaught exceptions",
|
||||
"Type errors"
|
||||
],
|
||||
"related_mvp_fixes": ["MVP-008"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PHASE-V3",
|
||||
"name": "Remaining Issues Audit",
|
||||
"description": "Review issues INT-000016 to INT-000030 from original audit",
|
||||
"priority": "MEDIUM",
|
||||
"estimated_effort": "1 hour",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "AUDIT-001",
|
||||
"title": "Review P2 Issues (INT-000016 to INT-000023)",
|
||||
"type": "audit",
|
||||
"status": "todo",
|
||||
"issues_to_review": [
|
||||
{
|
||||
"id": "INT-000016",
|
||||
"title": "Field Name Mismatch: cover_art_path vs cover_art_url",
|
||||
"severity": "P2",
|
||||
"check": "Verify if cover_art naming is consistent",
|
||||
"action_if_found": "Add to next sprint backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000017",
|
||||
"title": "Inconsistent Pagination Response Format",
|
||||
"severity": "P2",
|
||||
"check": "Verify pagination format across list endpoints",
|
||||
"action_if_found": "Document and add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000018",
|
||||
"title": "Missing Rate Limit Feedback to User",
|
||||
"severity": "P2",
|
||||
"check": "Verify 429 responses show user-friendly message",
|
||||
"action_if_found": "Add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000019",
|
||||
"title": "WebSocket Connection Error Handling",
|
||||
"severity": "P2",
|
||||
"check": "Verify chat/real-time features handle disconnects",
|
||||
"action_if_found": "Add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000020",
|
||||
"title": "File Upload Progress Accuracy",
|
||||
"severity": "P2",
|
||||
"check": "Verify upload progress is accurate",
|
||||
"action_if_found": "Add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000021",
|
||||
"title": "Search Debounce Missing",
|
||||
"severity": "P2",
|
||||
"check": "Verify search inputs have debounce",
|
||||
"action_if_found": "Add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000022",
|
||||
"title": "Optimistic UI Updates Not Rolled Back on Error",
|
||||
"severity": "P2",
|
||||
"check": "Verify failed mutations roll back UI state",
|
||||
"action_if_found": "Add to backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000023",
|
||||
"title": "Date/Time Timezone Handling",
|
||||
"severity": "P2",
|
||||
"check": "Verify dates display in user's timezone",
|
||||
"action_if_found": "Add to backlog"
|
||||
}
|
||||
],
|
||||
"output": "List of P2 issues still present with severity assessment"
|
||||
},
|
||||
{
|
||||
"id": "AUDIT-002",
|
||||
"title": "Review P3 Issues (INT-000024 to INT-000030)",
|
||||
"type": "audit",
|
||||
"status": "todo",
|
||||
"issues_to_review": [
|
||||
{
|
||||
"id": "INT-000024",
|
||||
"title": "No API Versioning Strategy",
|
||||
"severity": "P3",
|
||||
"check": "Verify /api/v1 is used consistently",
|
||||
"action_if_found": "Document for future"
|
||||
},
|
||||
{
|
||||
"id": "INT-000025",
|
||||
"title": "Missing OpenAPI/Swagger Documentation",
|
||||
"severity": "P3",
|
||||
"check": "Check if API docs exist",
|
||||
"action_if_found": "Add to tech debt backlog"
|
||||
},
|
||||
{
|
||||
"id": "INT-000026",
|
||||
"title": "Inconsistent Error Message Formatting",
|
||||
"severity": "P3",
|
||||
"check": "Spot check error responses for consistency",
|
||||
"action_if_found": "Add to tech debt"
|
||||
},
|
||||
{
|
||||
"id": "INT-000027",
|
||||
"title": "No Rate Limit Headers in Responses",
|
||||
"severity": "P3",
|
||||
"check": "Check for X-RateLimit-* headers",
|
||||
"action_if_found": "Add to tech debt"
|
||||
},
|
||||
{
|
||||
"id": "INT-000028",
|
||||
"title": "Missing API Documentation Updates",
|
||||
"severity": "P3",
|
||||
"check": "Verify FRONTEND_INTEGRATION.md is current",
|
||||
"action_if_found": "Update docs"
|
||||
},
|
||||
{
|
||||
"id": "INT-000029",
|
||||
"title": "No Vite Proxy Configuration for Development",
|
||||
"severity": "P3",
|
||||
"check": "Verify dev setup works without proxy",
|
||||
"action_if_found": "Optional improvement"
|
||||
},
|
||||
{
|
||||
"id": "INT-000030",
|
||||
"title": "Missing HLS Endpoints",
|
||||
"severity": "P3",
|
||||
"check": "Verify HLS features are disabled or stubbed",
|
||||
"action_if_found": "Already handled in MVP-008"
|
||||
}
|
||||
],
|
||||
"output": "List of P3 issues with tech debt assessment"
|
||||
},
|
||||
{
|
||||
"id": "AUDIT-003",
|
||||
"title": "Regression Detection Scan",
|
||||
"type": "audit",
|
||||
"status": "todo",
|
||||
"checks": [
|
||||
{
|
||||
"name": "New TypeScript Errors",
|
||||
"command": "cd apps/web && npx tsc --noEmit 2>&1 | head -50",
|
||||
"check": "Any errors introduced by MVP fixes?"
|
||||
},
|
||||
{
|
||||
"name": "New Console Warnings",
|
||||
"command": "Manual: Check browser console during app usage",
|
||||
"check": "Any new React warnings, deprecation notices?"
|
||||
},
|
||||
{
|
||||
"name": "New Go Lint Issues",
|
||||
"command": "cd veza-backend-api && golangci-lint run 2>&1 | head -50",
|
||||
"check": "Any new lint issues from MVP fixes?"
|
||||
},
|
||||
{
|
||||
"name": "Dead Code Detection",
|
||||
"command": "grep -r 'TODO.*MVP\\|FIXME.*MVP' apps/web/src/ veza-backend-api/",
|
||||
"check": "Any incomplete TODOs from MVP work?"
|
||||
},
|
||||
{
|
||||
"name": "Duplicate Code",
|
||||
"command": "Manual: Review for copy-paste code in MVP fixes",
|
||||
"check": "Any obvious duplication introduced?"
|
||||
}
|
||||
],
|
||||
"output": "List of regressions or new issues introduced"
|
||||
},
|
||||
{
|
||||
"id": "AUDIT-004",
|
||||
"title": "Security Quick Scan",
|
||||
"type": "audit",
|
||||
"status": "todo",
|
||||
"checks": [
|
||||
{
|
||||
"name": "CSRF Token Implementation",
|
||||
"check": "Is CSRF actually preventing attacks? (was deferred in MVP-005)",
|
||||
"status": "Review if MVP-005 was fully implemented or stubbed"
|
||||
},
|
||||
{
|
||||
"name": "Token Storage Security",
|
||||
"check": "Tokens in localStorage are XSS-vulnerable",
|
||||
"status": "Accepted risk for MVP, document for future httpOnly cookie migration"
|
||||
},
|
||||
{
|
||||
"name": "CORS Wildcard Check",
|
||||
"check": "No wildcards in production CORS origins",
|
||||
"command": "grep -r 'AllowOrigins.*\\*' veza-backend-api/"
|
||||
},
|
||||
{
|
||||
"name": "Sensitive Data in Logs",
|
||||
"check": "Tokens/passwords not logged",
|
||||
"command": "grep -rn 'console.log.*token\\|console.log.*password' apps/web/src/"
|
||||
}
|
||||
],
|
||||
"output": "Security assessment with accepted risks documented"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PHASE-V4",
|
||||
"name": "Final Report Generation",
|
||||
"description": "Generate comprehensive integration health report",
|
||||
"priority": "HIGH",
|
||||
"estimated_effort": "30 min",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "REPORT-001",
|
||||
"title": "Calculate New Health Score",
|
||||
"type": "analysis",
|
||||
"status": "todo",
|
||||
"scoring_criteria": {
|
||||
"compilation": {
|
||||
"weight": 20,
|
||||
"checks": ["TypeScript compiles", "Go compiles"],
|
||||
"score_if_pass": 20,
|
||||
"score_if_fail": 0
|
||||
},
|
||||
"tests": {
|
||||
"weight": 15,
|
||||
"checks": ["Frontend tests pass", "Backend tests pass"],
|
||||
"score_if_pass": 15,
|
||||
"score_if_fail": 0
|
||||
},
|
||||
"auth_flow": {
|
||||
"weight": 20,
|
||||
"checks": ["Login", "Logout", "Token refresh", "Persistence"],
|
||||
"score_if_pass": 20,
|
||||
"score_if_fail": 5
|
||||
},
|
||||
"api_contract": {
|
||||
"weight": 15,
|
||||
"checks": ["No 404s", "Consistent response format", "Type safety"],
|
||||
"score_if_pass": 15,
|
||||
"score_if_fail": 5
|
||||
},
|
||||
"error_handling": {
|
||||
"weight": 10,
|
||||
"checks": ["Retry logic", "Error correlation", "User feedback"],
|
||||
"score_if_pass": 10,
|
||||
"score_if_fail": 3
|
||||
},
|
||||
"security": {
|
||||
"weight": 10,
|
||||
"checks": ["CORS configured", "No wildcards in prod", "CSRF exists"],
|
||||
"score_if_pass": 10,
|
||||
"score_if_fail": 2
|
||||
},
|
||||
"code_quality": {
|
||||
"weight": 10,
|
||||
"checks": ["No legacy code", "Consistent naming", "No dead code"],
|
||||
"score_if_pass": 10,
|
||||
"score_if_fail": 5
|
||||
}
|
||||
},
|
||||
"output": "Health score X/100 (converted to X/10)"
|
||||
},
|
||||
{
|
||||
"id": "REPORT-002",
|
||||
"title": "Generate Final Integration Report",
|
||||
"type": "documentation",
|
||||
"status": "todo",
|
||||
"sections": [
|
||||
"Executive Summary",
|
||||
"Health Score Breakdown",
|
||||
"MVP Fixes Verification (15/15)",
|
||||
"E2E Test Results",
|
||||
"Remaining Issues (P2/P3)",
|
||||
"Security Assessment",
|
||||
"Regressions Detected",
|
||||
"Recommendations for Next Phase",
|
||||
"Deployment Readiness Checklist"
|
||||
],
|
||||
"output_file": "VEZA_INTEGRATION_FINAL_REPORT.md"
|
||||
},
|
||||
{
|
||||
"id": "REPORT-003",
|
||||
"title": "Generate Next Phase Todolist (if needed)",
|
||||
"type": "planning",
|
||||
"status": "todo",
|
||||
"condition": "If health score < 8/10 or critical issues found",
|
||||
"output_file": "VEZA_POST_MVP_TODOLIST.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"total_tasks": 27,
|
||||
"by_phase": {
|
||||
"PHASE-V1 (Technical)": 10,
|
||||
"PHASE-V2 (E2E)": 10,
|
||||
"PHASE-V3 (Audit)": 4,
|
||||
"PHASE-V4 (Report)": 3
|
||||
},
|
||||
"by_type": {
|
||||
"automated": 10,
|
||||
"manual": 10,
|
||||
"audit": 4,
|
||||
"analysis": 1,
|
||||
"documentation": 1,
|
||||
"planning": 1
|
||||
},
|
||||
"estimated_total_hours": "3-5 hours"
|
||||
},
|
||||
"progress_tracking": {
|
||||
"completed": 0,
|
||||
"in_progress": 0,
|
||||
"todo": 27,
|
||||
"failed": 0,
|
||||
"last_updated": null,
|
||||
"completion_percentage": 0
|
||||
},
|
||||
"validation_results": {
|
||||
"technical": {
|
||||
"typescript_compiles": null,
|
||||
"go_compiles": null,
|
||||
"frontend_tests_pass": null,
|
||||
"backend_tests_pass": null,
|
||||
"legacy_code_removed": null
|
||||
},
|
||||
"functional": {
|
||||
"auth_flow_works": null,
|
||||
"profile_works": null,
|
||||
"error_handling_works": null,
|
||||
"cors_works": null
|
||||
},
|
||||
"audit": {
|
||||
"p2_issues_remaining": null,
|
||||
"p3_issues_remaining": null,
|
||||
"regressions_found": null,
|
||||
"security_issues": null
|
||||
},
|
||||
"final_health_score": null,
|
||||
"mvp_stable": null
|
||||
}
|
||||
}
|
||||
495
VEZA_VALIDATION_AGENT_PROMPT.md
Normal file
495
VEZA_VALIDATION_AGENT_PROMPT.md
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
# VEZA MVP Validation & Final Audit Agent
|
||||
|
||||
## 🎯 Mission
|
||||
|
||||
Tu es un agent de validation et d'audit. Les 15 tâches MVP ont été implémentées. Ta mission est de :
|
||||
|
||||
1. **VALIDER** que les 15 fixes fonctionnent réellement
|
||||
2. **TESTER** les flows critiques E2E
|
||||
3. **AUDITER** les problèmes restants
|
||||
4. **GÉNÉRER** un rapport final avec score de santé
|
||||
|
||||
---
|
||||
|
||||
## 📁 Fichiers de Référence
|
||||
|
||||
```
|
||||
VEZA_MVP_VALIDATION_TODOLIST.json ← Source de vérité pour cette phase
|
||||
VEZA_MVP_STABILITY_TODOLIST.json ← Référence des 15 fixes implémentés
|
||||
VEZA_MVP_TODOLIST_TRACKING.md ← Journal des implémentations
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Cycle d'Exécution
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE-V1: VALIDATION TECHNIQUE (10 checks automatiques) │
|
||||
│ → Exécuter chaque commande │
|
||||
│ → Noter PASS/FAIL │
|
||||
│ → Si FAIL: identifier la cause et documenter │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ PHASE-V2: TESTS E2E (10 tests manuels) │
|
||||
│ → Guider l'utilisateur à travers chaque test │
|
||||
│ → Collecter les résultats │
|
||||
│ → Documenter les échecs │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ PHASE-V3: AUDIT DES ISSUES RESTANTES │
|
||||
│ → Vérifier INT-000016 à INT-000030 │
|
||||
│ → Détecter les régressions │
|
||||
│ → Scan de sécurité │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ PHASE-V4: RAPPORT FINAL │
|
||||
│ → Calculer le score de santé │
|
||||
│ → Générer VEZA_INTEGRATION_FINAL_REPORT.md │
|
||||
│ → Décider si MVP est stable │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 PHASE-V1 : Validation Technique
|
||||
|
||||
Exécute ces 10 commandes et enregistre les résultats :
|
||||
|
||||
### VAL-001: TypeScript Compilation
|
||||
```bash
|
||||
cd apps/web && npx tsc --noEmit
|
||||
```
|
||||
**Attendu**: Exit 0, aucune erreur
|
||||
**Si échec**: Lister les erreurs, identifier le MVP fix responsable
|
||||
|
||||
### VAL-002: Go Compilation
|
||||
```bash
|
||||
cd veza-backend-api && go build ./...
|
||||
```
|
||||
**Attendu**: Exit 0, aucune erreur
|
||||
**Si échec**: Lister les erreurs, identifier le MVP fix responsable
|
||||
|
||||
### VAL-003: Frontend Tests
|
||||
```bash
|
||||
cd apps/web && npm test -- --passWithNoTests --watchAll=false
|
||||
```
|
||||
**Attendu**: Tous les tests passent
|
||||
**Si échec**: Noter les tests qui échouent
|
||||
|
||||
### VAL-004: Backend Tests
|
||||
```bash
|
||||
cd veza-backend-api && go test ./... -v
|
||||
```
|
||||
**Attendu**: Tous les tests passent
|
||||
**Si échec**: Noter les tests qui échouent
|
||||
|
||||
### VAL-005: CORS Production Check
|
||||
```bash
|
||||
cd veza-backend-api && APP_ENV=production CORS_ALLOWED_ORIGINS='' timeout 5 go run ./cmd/api 2>&1 || echo "Expected failure - check output above"
|
||||
```
|
||||
**Attendu**: Serveur refuse de démarrer avec message d'erreur CORS clair
|
||||
**Si échec**: MVP-001 incomplet
|
||||
|
||||
### VAL-006: ApiService Removed
|
||||
```bash
|
||||
grep -r 'ApiService' apps/web/src/ 2>/dev/null || echo "PASS: No ApiService found"
|
||||
```
|
||||
**Attendu**: 0 résultats
|
||||
**Si échec**: MVP-004 incomplet, lister les fichiers
|
||||
|
||||
### VAL-007: Token Storage Unified
|
||||
```bash
|
||||
grep -r 'auth-storage' apps/web/src/services/ 2>/dev/null || echo "PASS: No auth-storage in services"
|
||||
```
|
||||
**Attendu**: 0 résultats dans services/
|
||||
**Si échec**: MVP-002 incomplet
|
||||
|
||||
### VAL-008: Env Vars Standardized
|
||||
```bash
|
||||
grep -r 'VITE_API_BASE_URL' apps/web/ 2>/dev/null || echo "PASS: No VITE_API_BASE_URL"
|
||||
```
|
||||
**Attendu**: 0 résultats
|
||||
**Si échec**: MVP-006 incomplet
|
||||
|
||||
### VAL-009: User.id Type Fixed
|
||||
```bash
|
||||
grep -rn 'id:\s*number' apps/web/src/types/ apps/web/src/features/auth/types/ 2>/dev/null || echo "PASS: No number id types"
|
||||
```
|
||||
**Attendu**: 0 résultats pour User id
|
||||
**Si échec**: MVP-003 incomplet
|
||||
|
||||
### VAL-010: remember_me Standardized
|
||||
```bash
|
||||
grep -rn 'rememberMe' apps/web/src/ --include='*.ts' --include='*.tsx' 2>/dev/null | grep -v node_modules || echo "PASS: No camelCase rememberMe"
|
||||
```
|
||||
**Attendu**: 0 résultats
|
||||
**Si échec**: MVP-015 incomplet
|
||||
|
||||
---
|
||||
|
||||
## 📋 PHASE-V2 : Tests E2E
|
||||
|
||||
Guide l'utilisateur à travers ces tests. Demande confirmation après chaque test.
|
||||
|
||||
### E2E-001: Registration Flow
|
||||
```
|
||||
Instructions pour l'utilisateur:
|
||||
1. Navigue vers /register
|
||||
2. Remplis le formulaire (email, username, password)
|
||||
3. Soumets
|
||||
4. Vérifie la redirection
|
||||
5. Ouvre DevTools > Application > localStorage
|
||||
6. Vérifie que veza_access_token existe
|
||||
7. Vérifie qu'il n'y a PAS de clé 'auth-storage'
|
||||
|
||||
Questions à poser:
|
||||
- Registration réussie? (oui/non)
|
||||
- Tokens dans localStorage? (oui/non)
|
||||
- Clé 'auth-storage' absente? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-002: Login Flow
|
||||
```
|
||||
Instructions:
|
||||
1. Déconnecte-toi si connecté
|
||||
2. Va sur /login
|
||||
3. Entre des credentials valides
|
||||
4. Coche "Remember me"
|
||||
5. Soumets
|
||||
6. Ouvre DevTools > Network
|
||||
7. Trouve la requête POST /auth/login
|
||||
8. Vérifie le body: remember_me (snake_case) et non rememberMe
|
||||
|
||||
Questions:
|
||||
- Login réussi? (oui/non)
|
||||
- remember_me envoyé en snake_case? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-003: Session Persistence
|
||||
```
|
||||
Instructions:
|
||||
1. Assure-toi d'être connecté
|
||||
2. Fais un hard refresh (Ctrl+Shift+R)
|
||||
3. Es-tu toujours connecté?
|
||||
4. Ouvre un nouvel onglet sur l'app
|
||||
5. Es-tu connecté dans le nouvel onglet?
|
||||
|
||||
Questions:
|
||||
- Session persiste après refresh? (oui/non)
|
||||
- Session partagée entre onglets? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-004: Token Refresh
|
||||
```
|
||||
Instructions:
|
||||
1. Connecte-toi
|
||||
2. Dans DevTools > Application > localStorage
|
||||
3. Modifie veza_access_token (ajoute des caractères pour l'invalider)
|
||||
4. Fais une action qui appelle l'API (ex: charger le profil)
|
||||
5. Observe Network tab
|
||||
6. Y a-t-il une requête vers /auth/refresh?
|
||||
7. Le token a-t-il été renouvelé dans localStorage?
|
||||
|
||||
Questions:
|
||||
- Token refresh automatique? (oui/non)
|
||||
- Nouveaux tokens stockés? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-005: Logout Flow
|
||||
```
|
||||
Instructions:
|
||||
1. Assure-toi d'être connecté
|
||||
2. Clique sur Logout
|
||||
3. Vérifie la redirection vers /login
|
||||
4. Vérifie localStorage - tokens effacés?
|
||||
5. Essaie d'accéder à une route protégée
|
||||
6. Es-tu redirigé vers login?
|
||||
|
||||
Questions:
|
||||
- Logout réussi? (oui/non)
|
||||
- Tokens effacés de localStorage? (oui/non)
|
||||
- Routes protégées inaccessibles? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-006: Profile View/Edit
|
||||
```
|
||||
Instructions:
|
||||
1. Va sur la page profil
|
||||
2. Tous les champs sont-ils affichés? (id, email, username, avatar, etc.)
|
||||
3. Modifie un champ (ex: username)
|
||||
4. Sauvegarde
|
||||
5. Refresh la page
|
||||
6. Le changement est-il persisté?
|
||||
|
||||
Questions:
|
||||
- Tous les champs user affichés? (oui/non)
|
||||
- Modifications sauvegardées? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-007: Error Request ID
|
||||
```
|
||||
Instructions:
|
||||
1. Ouvre DevTools > Console
|
||||
2. Provoque une erreur API (ex: accède à une ressource inexistante)
|
||||
3. Regarde le log d'erreur dans la console
|
||||
4. Contient-il un request_id?
|
||||
5. Vérifie dans Network si le même request_id est dans la réponse
|
||||
|
||||
Questions:
|
||||
- request_id présent dans les logs? (oui/non)
|
||||
- request_id correspond à la réponse backend? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-008: Retry Logic (si testable)
|
||||
```
|
||||
Instructions:
|
||||
1. Si possible: arrête le backend temporairement
|
||||
2. Ou: utilise DevTools > Network > Throttling > Offline
|
||||
3. Déclenche une requête API
|
||||
4. Observe Network - y a-t-il des retry?
|
||||
5. Remets la connexion
|
||||
6. La requête finit-elle par réussir?
|
||||
|
||||
Questions:
|
||||
- Retry automatique observé? (oui/non/non testable)
|
||||
- Backoff exponentiel? (oui/non/non testable)
|
||||
```
|
||||
|
||||
### E2E-009: CORS Headers
|
||||
```
|
||||
Instructions:
|
||||
1. Frontend sur localhost:3000, Backend sur localhost:8080
|
||||
2. Fais une requête API
|
||||
3. Ouvre Network > trouve la requête
|
||||
4. Regarde les Response Headers
|
||||
5. Access-Control-Allow-Origin présent?
|
||||
6. Access-Control-Allow-Credentials: true?
|
||||
|
||||
Questions:
|
||||
- Headers CORS présents? (oui/non)
|
||||
- Pas d'erreur CORS dans console? (oui/non)
|
||||
```
|
||||
|
||||
### E2E-010: Console Error Scan
|
||||
```
|
||||
Instructions:
|
||||
1. Ouvre DevTools > Console
|
||||
2. Clear console
|
||||
3. Navigue: Login → Dashboard → Profile → Tracks → Playlists → Logout
|
||||
4. Note toutes les erreurs/warnings
|
||||
|
||||
Questions:
|
||||
- Erreurs 404? (oui/non, lesquelles?)
|
||||
- Erreurs CORS? (oui/non)
|
||||
- Exceptions JavaScript? (oui/non, lesquelles?)
|
||||
- Warnings React? (oui/non, lesquels?)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 PHASE-V3 : Audit Issues Restantes
|
||||
|
||||
### Vérifier les issues P2 (INT-000016 à INT-000023)
|
||||
|
||||
Pour chaque issue, vérifie si elle existe encore et note la sévérité actuelle:
|
||||
|
||||
| ID | Issue | Commande/Check | Statut |
|
||||
|----|-------|----------------|--------|
|
||||
| INT-000016 | cover_art_path vs cover_art_url | `grep -rn 'cover_art' apps/web/src/types/` | |
|
||||
| INT-000017 | Pagination inconsistante | Spot check des endpoints de liste | |
|
||||
| INT-000018 | Rate limit feedback | Vérifier gestion du 429 | |
|
||||
| INT-000019 | WebSocket error handling | Si chat existe, tester déconnexion | |
|
||||
| INT-000020 | Upload progress accuracy | Tester upload de fichier | |
|
||||
| INT-000021 | Search debounce | Tester champs de recherche | |
|
||||
| INT-000022 | Optimistic UI rollback | Tester échec de mutation | |
|
||||
| INT-000023 | Timezone handling | Vérifier affichage des dates | |
|
||||
|
||||
### Vérifier les issues P3 (INT-000024 à INT-000030)
|
||||
|
||||
| ID | Issue | Statut |
|
||||
|----|-------|--------|
|
||||
| INT-000024 | API versioning | /api/v1 utilisé partout? |
|
||||
| INT-000025 | OpenAPI docs | Swagger existe? |
|
||||
| INT-000026 | Error message format | Cohérent? |
|
||||
| INT-000027 | Rate limit headers | X-RateLimit-* présents? |
|
||||
| INT-000028 | API docs à jour | FRONTEND_INTEGRATION.md actuel? |
|
||||
| INT-000029 | Vite proxy | Fonctionne sans? |
|
||||
| INT-000030 | HLS endpoints | Désactivés dans MVP-008? |
|
||||
|
||||
### Détection de Régressions
|
||||
|
||||
```bash
|
||||
# TODOs/FIXMEs liés au MVP
|
||||
grep -rn 'TODO.*MVP\|FIXME.*MVP' apps/web/src/ veza-backend-api/
|
||||
|
||||
# Code mort potentiel
|
||||
grep -rn 'ApiService\|apiService' apps/web/src/
|
||||
|
||||
# Sensitive data in logs
|
||||
grep -rn 'console.log.*token\|console.log.*password' apps/web/src/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 PHASE-V4 : Rapport Final
|
||||
|
||||
### Calcul du Score de Santé
|
||||
|
||||
```
|
||||
SCORING (sur 100 points, converti en /10):
|
||||
|
||||
Compilation (20 pts)
|
||||
├── TypeScript compile: 10 pts
|
||||
└── Go compile: 10 pts
|
||||
|
||||
Tests (15 pts)
|
||||
├── Frontend tests pass: 7 pts
|
||||
└── Backend tests pass: 8 pts
|
||||
|
||||
Auth Flow (20 pts)
|
||||
├── Login works: 5 pts
|
||||
├── Logout works: 5 pts
|
||||
├── Token refresh works: 5 pts
|
||||
└── Session persists: 5 pts
|
||||
|
||||
API Contract (15 pts)
|
||||
├── No 404 errors: 5 pts
|
||||
├── Consistent format: 5 pts
|
||||
└── Type safety: 5 pts
|
||||
|
||||
Error Handling (10 pts)
|
||||
├── Retry logic: 4 pts
|
||||
├── Error correlation: 3 pts
|
||||
└── User feedback: 3 pts
|
||||
|
||||
Security (10 pts)
|
||||
├── CORS configured: 4 pts
|
||||
├── No wildcards prod: 3 pts
|
||||
└── CSRF exists: 3 pts
|
||||
|
||||
Code Quality (10 pts)
|
||||
├── No legacy code: 4 pts
|
||||
├── Consistent naming: 3 pts
|
||||
└── No dead code: 3 pts
|
||||
|
||||
TOTAL: ___ / 100 = ___ / 10
|
||||
```
|
||||
|
||||
### Template du Rapport Final
|
||||
|
||||
Génère ce fichier: `VEZA_INTEGRATION_FINAL_REPORT.md`
|
||||
|
||||
```markdown
|
||||
# Veza Integration Final Report
|
||||
|
||||
**Date**: [DATE]
|
||||
**Auditeur**: [Agent]
|
||||
**Phase précédente**: MVP Stability Fixes (15/15)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Health Score**: X/10 (était 4/10 avant MVP fixes)
|
||||
**MVP Stable**: OUI/NON
|
||||
**Prêt pour Production**: OUI/NON/AVEC RÉSERVES
|
||||
|
||||
[Résumé en 3-4 phrases]
|
||||
|
||||
---
|
||||
|
||||
## MVP Fixes Verification
|
||||
|
||||
| ID | Fix | Validation | Statut |
|
||||
|----|-----|------------|--------|
|
||||
| MVP-001 | CORS Config | VAL-005 | ✅/❌ |
|
||||
| MVP-002 | Token Storage | VAL-007 | ✅/❌ |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
**Résultat**: X/15 fixes vérifiés fonctionnels
|
||||
|
||||
---
|
||||
|
||||
## E2E Test Results
|
||||
|
||||
| Test | Résultat | Notes |
|
||||
|------|----------|-------|
|
||||
| E2E-001 Registration | ✅/❌ | |
|
||||
| E2E-002 Login | ✅/❌ | |
|
||||
| ... | ... | ... |
|
||||
|
||||
**Résultat**: X/10 tests passent
|
||||
|
||||
---
|
||||
|
||||
## Issues Restantes
|
||||
|
||||
### P2 (Medium - à traiter prochainement)
|
||||
- [ ] INT-000016: ...
|
||||
- [ ] INT-000017: ...
|
||||
|
||||
### P3 (Low - tech debt)
|
||||
- [ ] INT-000024: ...
|
||||
- [ ] INT-000025: ...
|
||||
|
||||
---
|
||||
|
||||
## Régressions Détectées
|
||||
|
||||
[Liste des régressions trouvées, ou "Aucune régression détectée"]
|
||||
|
||||
---
|
||||
|
||||
## Security Assessment
|
||||
|
||||
| Check | Statut | Risque Accepté? |
|
||||
|-------|--------|-----------------|
|
||||
| CORS configuré | ✅/❌ | |
|
||||
| Pas de wildcards | ✅/❌ | |
|
||||
| CSRF implémenté | ✅/❌ | |
|
||||
| Tokens en localStorage | ⚠️ | Oui (MVP) |
|
||||
|
||||
---
|
||||
|
||||
## Recommandations
|
||||
|
||||
### Immédiat (avant déploiement)
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
### Court terme (sprint suivant)
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
### Moyen terme (backlog)
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
---
|
||||
|
||||
## Deployment Readiness Checklist
|
||||
|
||||
- [ ] Tous les tests passent
|
||||
- [ ] CORS_ALLOWED_ORIGINS configuré pour prod
|
||||
- [ ] Variables d'environnement documentées
|
||||
- [ ] Pas de secrets dans le code
|
||||
- [ ] Docker build fonctionne
|
||||
- [ ] Rollback plan en place
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
[Score final, décision MVP stable ou non, prochaines étapes]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 COMMENCE
|
||||
|
||||
1. Lis `VEZA_MVP_VALIDATION_TODOLIST.json`
|
||||
2. Annonce: "🔍 Démarrage de la validation MVP Veza"
|
||||
3. Exécute PHASE-V1 (commandes automatiques)
|
||||
4. Guide l'utilisateur pour PHASE-V2 (tests manuels)
|
||||
5. Effectue PHASE-V3 (audit)
|
||||
6. Génère PHASE-V4 (rapport final)
|
||||
|
||||
**Première action**: Exécuter VAL-001 (TypeScript compilation)
|
||||
|
|
@ -108,3 +108,4 @@ export default globalSetup;
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,266 @@
|
|||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"veza-backend-api/internal/models"
|
||||
"veza-backend-api/internal/repositories"
|
||||
"veza-backend-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// setupProfileIntegrationTestRouter crée un router de test pour les tests de profile
|
||||
// BE-SEC-001: Tests d'intégration pour vérification ownership
|
||||
func setupProfileIntegrationTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, func()) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
// Setup in-memory SQLite database
|
||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Enable foreign keys for SQLite
|
||||
db.Exec("PRAGMA foreign_keys = ON")
|
||||
|
||||
// Auto-migrate - include all models needed for PermissionService
|
||||
err = db.AutoMigrate(
|
||||
&models.User{},
|
||||
&models.Role{},
|
||||
&models.Permission{},
|
||||
&models.UserRole{},
|
||||
&models.RolePermission{},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup logger
|
||||
logger := zap.NewNop()
|
||||
|
||||
// Setup services
|
||||
userRepo := repositories.NewGormUserRepository(db)
|
||||
userService := services.NewUserServiceWithDB(userRepo, db)
|
||||
profileHandler := NewProfileHandler(userService, logger)
|
||||
|
||||
// Setup PermissionService for admin checks
|
||||
permissionService := services.NewPermissionService(db)
|
||||
profileHandler.SetPermissionService(permissionService)
|
||||
|
||||
// Create router
|
||||
router := gin.New()
|
||||
v1 := router.Group("/api/v1")
|
||||
{
|
||||
// Protected routes with mock auth middleware
|
||||
protected := v1.Group("/users")
|
||||
protected.Use(func(c *gin.Context) {
|
||||
// Mock auth middleware - set user_id from header
|
||||
// This simulates RequireAuth() middleware
|
||||
userIDStr := c.GetHeader("X-User-ID")
|
||||
if userIDStr == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
uid, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid user id"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Set("user_id", uid)
|
||||
c.Next()
|
||||
})
|
||||
{
|
||||
// Note: In real router, RequireOwnershipOrAdmin middleware would be here
|
||||
// For this test, we're testing the handler's ownership check directly
|
||||
protected.PUT("/:id", profileHandler.UpdateProfile)
|
||||
}
|
||||
}
|
||||
|
||||
cleanup := func() {
|
||||
// Database will be closed automatically
|
||||
}
|
||||
|
||||
return router, db, cleanup
|
||||
}
|
||||
|
||||
// createTestUser crée un utilisateur de test
|
||||
func createTestUserForProfile(t *testing.T, db *gorm.DB, userID uuid.UUID, username string, isAdmin bool) *models.User {
|
||||
user := &models.User{
|
||||
ID: userID,
|
||||
Username: username,
|
||||
Slug: username,
|
||||
Email: username + "@example.com",
|
||||
PasswordHash: "hashed_password",
|
||||
IsActive: true,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if isAdmin {
|
||||
user.Role = "admin"
|
||||
user.IsAdmin = true
|
||||
} else {
|
||||
user.Role = "user"
|
||||
}
|
||||
// Create user first
|
||||
err := db.Create(user).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
// Then create admin role and assign it if admin
|
||||
if isAdmin {
|
||||
// Create admin role and assign it to user
|
||||
adminRole := &models.Role{
|
||||
Name: "admin",
|
||||
DisplayName: "Administrator",
|
||||
IsSystem: true,
|
||||
IsActive: true,
|
||||
}
|
||||
err = db.FirstOrCreate(adminRole, models.Role{Name: "admin"}).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
userRole := &models.UserRole{
|
||||
UserID: userID,
|
||||
RoleID: adminRole.ID,
|
||||
RoleName: "admin",
|
||||
IsActive: true,
|
||||
}
|
||||
err = db.Create(userRole).Error
|
||||
require.NoError(t, err)
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
// BE-SEC-001: Test that user cannot update another user's profile
|
||||
func TestUpdateProfile_UserCannotUpdateOtherUserProfile(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
router, db, cleanup := setupProfileIntegrationTestRouter(t)
|
||||
defer cleanup()
|
||||
|
||||
// Create two users
|
||||
ownerID := uuid.New()
|
||||
otherUserID := uuid.New()
|
||||
createTestUserForProfile(t, db, ownerID, "owner", false)
|
||||
createTestUserForProfile(t, db, otherUserID, "otheruser", false)
|
||||
|
||||
// Try to update owner's profile as otherUser
|
||||
updateReq := UpdateProfileRequest{
|
||||
FirstName: "Hacked",
|
||||
Bio: "I shouldn't be able to do this",
|
||||
}
|
||||
body, _ := json.Marshal(updateReq)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/api/v1/users/"+ownerID.String(), bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", otherUserID.String()) // otherUser is authenticated
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// Should return 403 Forbidden
|
||||
assert.Equal(t, http.StatusForbidden, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
// Error can be a string or a map, check both
|
||||
if errorStr, ok := response["error"].(string); ok {
|
||||
assert.Contains(t, errorStr, "cannot update other user's profile")
|
||||
} else if errorMap, ok := response["error"].(map[string]interface{}); ok {
|
||||
if message, ok := errorMap["message"].(string); ok {
|
||||
assert.Contains(t, message, "cannot update other user's profile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BE-SEC-001: Test that admin can update any profile
|
||||
func TestUpdateProfile_AdminCanUpdateAnyProfile(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
router, db, cleanup := setupProfileIntegrationTestRouter(t)
|
||||
defer cleanup()
|
||||
|
||||
// Create two users: owner and admin
|
||||
ownerID := uuid.New()
|
||||
adminID := uuid.New()
|
||||
createTestUserForProfile(t, db, ownerID, "owner", false)
|
||||
createTestUserForProfile(t, db, adminID, "admin", true)
|
||||
|
||||
// Admin tries to update owner's profile
|
||||
updateReq := UpdateProfileRequest{
|
||||
FirstName: "Updated by Admin",
|
||||
Bio: "Admin updated this profile",
|
||||
}
|
||||
body, _ := json.Marshal(updateReq)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/api/v1/users/"+ownerID.String(), bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", adminID.String()) // admin is authenticated
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// Admin should be able to update
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, response["data"])
|
||||
}
|
||||
|
||||
// BE-SEC-001: Test that user can update their own profile
|
||||
func TestUpdateProfile_UserCanUpdateOwnProfile(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
router, db, cleanup := setupProfileIntegrationTestRouter(t)
|
||||
defer cleanup()
|
||||
|
||||
// Create a user
|
||||
userID := uuid.New()
|
||||
createTestUserForProfile(t, db, userID, "testuser", false)
|
||||
|
||||
// User tries to update their own profile
|
||||
updateReq := UpdateProfileRequest{
|
||||
FirstName: "Updated First Name",
|
||||
Bio: "Updated bio",
|
||||
}
|
||||
body, _ := json.Marshal(updateReq)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/api/v1/users/"+userID.String(), bytes.NewBuffer(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-User-ID", userID.String()) // user is authenticated
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// User should be able to update their own profile
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, response["data"])
|
||||
|
||||
// Verify the profile was actually updated
|
||||
profileData := response["data"].(map[string]interface{})
|
||||
profile := profileData["profile"].(map[string]interface{})
|
||||
assert.Equal(t, "Updated First Name", profile["first_name"])
|
||||
}
|
||||
Loading…
Reference in a new issue