veza/veza-backend-api/docs/AUDIT_FINDINGS.json

383 lines
13 KiB
JSON
Raw Normal View History

2025-12-16 16:23:49 +00:00
{
"audit_date": "2025-12-15",
"module": "veza-backend-api",
"go_version": "1.23.8",
"total_findings": 18,
"findings": [
{
"id": "MOD-P0-001",
"title": "Erreur compilation: uuid.New() utilisé comme *uuid.UUID",
"priority": "P0",
"category": "Tests",
"severity": "Critique",
"probability": "Élevée",
"files": [
"internal/core/track/service_async_test.go:219",
"internal/core/track/service_n1_test.go:48",
"internal/core/track/service_n1_test.go:114"
],
"summary": "Les tests utilisent uuid.New() (array) comme *uuid.UUID (pointeur) dans struct literals",
"fix_minimal": "Remplacer uuid.New() par &uuid.New() ou créer variable intermédiaire",
"effort": "S",
"effort_hours": 0.5,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P0-002",
"title": "Panic dans test: interface conversion nil",
"priority": "P0",
"category": "Tests",
"severity": "Critique",
"probability": "Élevée",
"files": [
"internal/handlers/playlist_handler_integration_test.go:139"
],
"summary": "Test panique avec 'interface conversion: interface {} is nil, not map[string]interface {}'",
"fix_minimal": "Ajouter vérification type avec require.True() avant assertion",
"effort": "S",
"effort_hours": 0.25,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P1-001",
"title": "57 occurrences c.MustGet() sans vérification",
"priority": "P1",
"category": "Correctness",
"severity": "Haute",
"probability": "Moyenne",
"files": [
"internal/core/track/handler.go:17",
"internal/handlers/playback_analytics_handler.go:2",
"internal/handlers/playback_websocket_handler.go:1",
"internal/handlers/settings_handler.go:2",
"internal/handlers/social.go:3",
"internal/handlers/marketplace.go:3",
"internal/handlers/playlist_handler.go:1",
"internal/handlers/comment_handler.go:3",
"internal/handlers/hls_handler.go:1",
"internal/handlers/playlist_export_handler.go:13",
"internal/handlers/password_reset_handler.go:5",
"internal/handlers/role_handler.go:21",
"internal/handlers/oauth_handlers.go:3"
],
"summary": "c.MustGet() panique si clé absente. 57 occurrences dans 13 fichiers",
"fix_minimal": "Remplacer par c.Get() avec vérification exists et type",
"effort": "M",
"effort_hours": 6,
"risk": "Medium",
"dependencies": []
},
{
"id": "MOD-P1-002",
"title": "534 occurrences gin.H{\"error\"} (format non standardisé)",
"priority": "P1",
"category": "Correctness",
"severity": "Haute",
"probability": "Élevée",
"files": [
"internal/handlers/room_handler.go:14",
"internal/handlers/social.go:6",
"internal/handlers/webhook_handlers.go:14",
"internal/handlers/session.go:31",
"internal/handlers/settings_handler.go:5",
"internal/handlers/playlist_export_handler.go:13",
"internal/handlers/password_reset_handler.go:5",
"internal/handlers/notification_handlers.go:9",
"internal/handlers/hls_handler.go:13",
"internal/handlers/role_handler.go:21",
"internal/handlers/comment_handler.go:26",
"internal/handlers/oauth_handlers.go:3",
"internal/handlers/chat_handler.go:3",
"internal/handlers/audit.go:27",
"internal/handlers/analytics_handler.go:24",
"internal/handlers/avatar_handler.go:12",
"internal/handlers/auth.go:13"
],
"summary": "Format d'erreur non standardisé. 534 occurrences dans 43 fichiers",
"fix_minimal": "Remplacer par RespondWithAppError() ou RespondWithError()",
"effort": "L",
"effort_hours": 20,
"risk": "Medium",
"dependencies": []
},
{
"id": "MOD-P1-003",
"title": "969 occurrences fmt.Errorf sans %w",
"priority": "P1",
"category": "DX",
"severity": "Moyenne",
"probability": "Élevée",
"files": [
"internal/services/playback_export_service.go:26",
"internal/services/playback_comparison_service.go:39",
"internal/services/playback_analytics_service.go:47",
"internal/services/hls_service.go:28",
"internal/services/track_version_service.go:16",
"internal/services/playlist_service.go:25",
"internal/services/rbac_service.go:24"
],
"summary": "Erreurs non wrap, perte de contexte. 969 occurrences dans 107 fichiers",
"fix_minimal": "Ajouter %w dans fmt.Errorf pour permettre errors.Is()/errors.As()",
"effort": "L",
"effort_hours": 30,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P1-004",
"title": "Pas de timeout context dans tous handlers",
"priority": "P1",
"category": "Robustness",
"severity": "Haute",
"probability": "Moyenne",
"files": [
"Multiple handlers"
],
"summary": "Seulement 32 timeouts explicites pour centaines d'appels DB/Redis/HTTP",
"fix_minimal": "Ajouter context.WithTimeout() pour opérations I/O critiques",
"effort": "M",
"effort_hours": 8,
"risk": "Medium",
"dependencies": []
},
{
"id": "MOD-P1-005",
"title": "Stack traces dans logs production",
"priority": "P1",
"category": "Security",
"severity": "Moyenne",
"probability": "Moyenne",
"files": [
"internal/middleware/error_handler.go:145"
],
"summary": "Stack traces loggés même en production, expose info sensible",
"fix_minimal": "Utiliser includeStackTrace (déjà présent) pour conditionner logs",
"effort": "S",
"effort_hours": 0.5,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P1-006",
"title": "/readyz échoue si Redis/RabbitMQ down",
"priority": "P1",
"category": "Robustness",
"severity": "Haute",
"probability": "Moyenne",
"files": [
"internal/handlers/health.go:143-159"
],
"summary": "Readiness échoue si services optionnels down, Kubernetes peut tuer pod",
"fix_minimal": "Mode dégradé: logger warning mais ne pas échouer si services optionnels down",
"effort": "S",
"effort_hours": 1,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-001",
"title": "201 occurrences TODO/FIXME/HACK/XXX",
"priority": "P2",
"category": "DX",
"severity": "Faible",
"probability": "Élevée",
"files": [
"internal/api/api_manager.go:4",
"internal/services/job_service.go:3",
"cmd/modern-server/main.go:7",
"internal/database/database.go:4"
],
"summary": "Dette technique importante. 201 occurrences dans 49 fichiers",
"fix_minimal": "Créer tickets pour chaque TODO et prioriser",
"effort": "L",
"effort_hours": "Variable",
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-002",
"title": "81 tests skippés",
"priority": "P2",
"category": "Tests",
"severity": "Faible",
"probability": "Élevée",
"files": [
"tests/integration/api_health_test.go:6",
"tests/integration/upload_async_polling_test.go:4",
"internal/handlers/playlist_handler_integration_test.go:12",
"internal/handlers/playlist_collaboration_integration_test.go:6",
"internal/handlers/playlist_track_handler_integration_test.go:9"
],
"summary": "Couverture incomplète. 81 skips dans 23 fichiers",
"fix_minimal": "Réactiver progressivement ou supprimer si obsolètes",
"effort": "M",
"effort_hours": "Variable",
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-003",
"title": "37 occurrences quarantine",
"priority": "P2",
"category": "Tests",
"severity": "Faible",
"probability": "Moyenne",
"files": [
"tests/integration/QUARANTINE.md",
"internal/services/upload_validator.go:11",
"docs/INTEGRATION_TESTS_HARDENING_REPORT.md:4"
],
"summary": "Tests en quarantaine. 37 occurrences dans 14 fichiers",
"fix_minimal": "Réactiver progressivement ou supprimer si obsolètes",
"effort": "M",
"effort_hours": "Variable",
"risk": "Medium",
"dependencies": []
},
{
"id": "MOD-P2-004",
"title": "Métriques DB pool manquantes",
"priority": "P2",
"category": "Observability",
"severity": "Faible",
"probability": "Élevée",
"files": [
"internal/metrics/prometheus.go"
],
"summary": "Pas de métriques pour DB pool stats (connections, idle, wait time)",
"fix_minimal": "Ajouter métriques Prometheus pour DB pool (StartDBPoolStatsCollector existe mais métriques non exposées)",
"effort": "M",
"effort_hours": 2,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-005",
"title": "Pas de redaction PII dans logs",
"priority": "P2",
"category": "Security",
"severity": "Faible",
"probability": "Moyenne",
"files": [
"internal/middleware/request_logger.go"
],
"summary": "Aucune redaction automatique PII (emails, user_ids, tokens)",
"fix_minimal": "Ajouter fonction redaction pour emails, user_ids, tokens",
"effort": "M",
"effort_hours": 4,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-006",
"title": "33 occurrences panic() (principalement tests)",
"priority": "P2",
"category": "Robustness",
"severity": "Faible",
"probability": "Faible",
"files": [
"internal/testutils/db.go:4",
"internal/testutils/fixtures.go:3",
"internal/middleware/recovery_test.go:6"
],
"summary": "33 panics dans 11 fichiers, principalement tests (acceptable)",
"fix_minimal": "Vérifier que panics production sont justifiés (fail-fast)",
"effort": "S",
"effort_hours": 1,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-007",
"title": "5 occurrences log.Fatal (cmd/*)",
"priority": "P2",
"category": "Robustness",
"severity": "Faible",
"probability": "Faible",
"files": [
"cmd/api/main.go:1",
"cmd/modern-server/main.go:1",
"cmd/migrate_tool/main.go:3"
],
"summary": "5 log.Fatal dans cmd/*, acceptable pour erreurs démarrage",
"fix_minimal": "Aucun (comportement attendu pour erreurs démarrage)",
"effort": "N/A",
"effort_hours": 0,
"risk": "N/A",
"dependencies": []
},
{
"id": "MOD-P2-008",
"title": "2 occurrences os.Exit",
"priority": "P2",
"category": "Robustness",
"severity": "Faible",
"probability": "Faible",
"files": [
"cmd/generate-config-docs/main.go:2"
],
"summary": "2 os.Exit dans tools CLI, acceptable",
"fix_minimal": "Aucun (comportement attendu pour outils CLI)",
"effort": "N/A",
"effort_hours": 0,
"risk": "N/A",
"dependencies": []
},
{
"id": "MOD-P2-009",
"title": "Pas de versioning API",
"priority": "P2",
"category": "DX",
"severity": "Faible",
"probability": "Élevée",
"files": [
"internal/api/router.go:102"
],
"summary": "Toutes routes sous /api/v1/*, pas de mécanisme versioning",
"fix_minimal": "Prévoir structure pour /api/v2/* quand nécessaire",
"effort": "M",
"effort_hours": 4,
"risk": "Low",
"dependencies": []
},
{
"id": "MOD-P2-010",
"title": "Tests flaky (playlist collaboration)",
"priority": "P2",
"category": "Tests",
"severity": "Faible",
"probability": "Moyenne",
"files": [
"internal/handlers/playlist_collaboration_integration_test.go"
],
"summary": "4 tests échouent: AddCollaborator, RemoveCollaborator, UpdatePermission, GetCollaborators",
"fix_minimal": "Corriger assertions et vérifier format réponse",
"effort": "M",
"effort_hours": 2,
"risk": "Low",
"dependencies": []
}
],
"statistics": {
"panic_count": 33,
"log_fatal_count": 5,
"os_exit_count": 2,
"must_get_count": 57,
"todo_count": 201,
"skip_count": 81,
"quarantine_count": 37,
"gin_error_count": 534,
"fmt_errorf_count": 969,
"timeout_count": 32
},
"summary": {
"p0_count": 2,
"p1_count": 6,
"p2_count": 10,
"total_effort_hours": 99.25,
"estimated_weeks": 3
}
}