veza/docs/REMEDIATION_PROGRESS.md

170 lines
15 KiB
Markdown
Raw Normal View History

# Progression de la remédiation — Stabilisation frontend
**Référence** : [Plan de remédiation](.cursor/plans/frontend_stabilization_remediation_b9e1b51d.plan.md)
**Dernière mise à jour** : 16 février 2026 (Phase 2 audit complétée, E2E auth corrigés)
### Phase 2 — Stabilisation (Audit technique) ✅
- **P2.1 OAuth** : Vérifié — `GetUserByOAuthID` et `getOrCreateUser` en place.
- **P2.2 Education** : Vérifié — aucune route education dans `internal/`.
- **P2.3 npm** : Vérifié — `npm audit --audit-level=critical` = 0 vulnérabilités.
- **P2.4 Bypass flags** : Vérifié — `validateNoBypassFlagsInProduction` rejette en prod.
- **P2.5 E2E auth** : Corrigé — `VITE_API_URL=/api/v1` en CI, health check global-setup pour URLs relatives, timeouts et sélecteurs auth renforcés (commit 85267d2b).
---
## Audit sécurité (AUDIT_TECHNIQUE_INTEGRAL_2026_02_16)
Référence : [archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md](archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md).
**Référence** : [Plan de remédiation sécurité](.cursor/plans/remédiation_sécurité_audit_veza_0de3fd35.plan.md)
### Lot 2 — Routes Education fantômes (A01) ✅
- **Constat** : Les packages `internal/api/education/` et `internal/core/education/` étaient des répertoires vides (aucun fichier Go, aucune route enregistrée).
- **Action** : Suppression des répertoires vides. Aucune route Education n'était exposée ; le risque identifié dans l'audit ne s'appliquait pas au code actuel.
### Lot 6 — Bypass flags (A05) ✅
- **Constat** : `BYPASS_CONTENT_CREATOR_ROLE` et `CSRF_DISABLED` sont déjà rejetés en production via `validateNoBypassFlagsInProduction()`.
- **Vérification** : `NewConfig()` appelle `ValidateForEnvironment()` qui invoque `validateNoBypassFlagsInProduction(c.Env)` au démarrage. Aucun changement nécessaire.
### Lot 8 — Vulnérabilités npm (A06) ✅
- **Action** : Suppression de `@lhci/cli`, `newman`, `pa11y-ci` (devDependencies avec vulnérabilités, utilisées uniquement par Makefile.old obsolète).
- **Scripts** : `qa:postman`, `qa:lh`, `qa:a11y` redirigés vers message explicatif.
- **Résultat** : 25 vulnérabilités → 0 (npm audit fix pour lodash).
### Lot 9 — 2FA login flow (A07) ✅
- **Vérification** : Flow correct — Login → requires_2fa → TwoFactorVerify → onSuccess(code) → complete2FALogin → POST /auth/login/2fa.
- **Tests** : E2E existant dans `auth.spec.ts` (« should complete login with 2FA code ») avec E2E_2FA_CODE. Aucune correction nécessaire.
### Lot 10 — OAuth user lookup (A07) ✅
- **Vérification** : `GetUserByOAuthID(oauthID, provider)` déjà implémenté dans `database.go` (lignes 557-576). Utilise `federated_identities` avec `provider` et `provider_id`. `OAuthService.getOrCreateUser` appelle ce lookup en priorité (ligne 403). Aucune correction nécessaire.
### Lot 11 — Download tracks public (A04) ✅
- **Action** : Vérification des droits avant téléchargement pour les tracks payants. Nouveau service `TrackDownloadLicenseChecker` (`internal/services/track_download_license.go`) qui vérifie si le track est vendu comme produit et si l'utilisateur a une licence valide. Injection dans `TrackHandler.DownloadTrack` — si track vendu et utilisateur non propriétaire, 403 sans licence.
### Lot 12 — Alignement Go version (CI) ✅
- **Action** : `go-version` dans `.github/workflows/ci.yml` aligné sur `1.24` pour correspondre à `go.mod`.
### Lot 13 — .unwrap() / .expect() critiques en Rust (Stabilité) ✅
- **Action** : Remplacement des unwrap critiques dans `veza-stream-server/src/utils/mod.rs``validate_signature` et `generate_signature`. `duration_since(UNIX_EPOCH)` gère maintenant l'erreur (retourne false). `generate_signature` retourne `Option<String>` au lieu de paniquer sur HMAC invalide. ~80+ unwraps restants (tests, regex statiques) — risque accepté pour l'instant.
---
## Vulnérabilités npm (A06 — Phase 1) ✅
Référence : [archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md](archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md) section A06.
### Correctifs appliqués
- **npm audit fix** : brace-expansion, diff, undici corrigés automatiquement.
- **React Router XSS (GHSA-2w69-qvjg-hvjx)** : `react-router-dom` mis à jour vers ^6.30.3 (@remix-run/router 1.23.2).
- **Axios DoS (GHSA-43fc-jf86-j433)** : override `axios >= 1.13.5` dans `package.json` racine.
- **class-variance-authority** : réintégré (dépendance manquante pour button/card).
- **CI** : `npm audit --audit-level=high` exécuté depuis la racine du monorepo.
### Vulnérabilités restantes (devDependencies uniquement)
25 vulnérabilités dans @lhci/cli, newman, pa11y-ci (cookie, jose, lodash, node-forge, qs, semver, tar-fs, tmp, ws). **Risque accepté** : ces packages ne sont pas inclus dans le build de production. Correction via `npm audit fix --force` entraînerait des breaking changes (downgrade @lhci/cli, newman, pa11y-ci).
---
## Rate limiting (A04) ✅
Référence : [archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md](archive/AUDIT_TECHNIQUE_INTEGRAL_2026_02_16.md) — Points de rupture (ligne 170), A04 (ligne 232).
### Correctifs appliqués
- **Rate limiting toujours actif** : suppression de la condition `Env != EnvDevelopment` pour le rate limit global et register.
- **Limites assouplies en dev** : `getDefaultRateLimitLimit(env)` — 1000 req/min en dev/test, 200 en staging/prod.
- **Register assoupli en dev** : `getDefaultRegisterAttempts(env)` — 20 inscriptions/heure en dev/test, 3 en staging/prod.
- **Documentation** : README mis à jour avec tableau des limites par environnement.
---
## Phase 1 — Backend solide ✅
### 1.1 Sécurité backend ✅
- **.gitignore** : Renforcement des patterns pour `.env`, `.env.*`, `**/.env`, `**/.env.local`, `veza-*/.env`, `apps/web/.env.local` (ne jamais committer de secrets).
- **Chat server** : Dans `veza-chat-server/src/jwt_manager.rs`, `validate_access_token` vérifie désormais en base que lutilisateur existe (si `db_pool` disponible) ; pas de fallback « user » si absent en DB — connexion refusée.
- **Backend Go** : Le handler de refresh token vérifie déjà lexistence de lutilisateur en DB (voir `internal/core/auth/service.go` RefreshToken).
- **Pagination** : Contrôle strict `page >= 1` et `1 <= limit <= 100` avec retour **400** et message clair dans :
- `internal/handlers/playlist_handler.go` (GetPlaylists),
- `internal/handlers/profile_handler.go` (ListUsers),
- `internal/core/track/handler.go` (ListTracks).
### 1.2 API et contrats ✅
- **Healthcheck** : Les Dockerfiles (Dockerfile, Dockerfile.production) utilisent déjà `http://localhost:8080/api/v1/health`.
- **go-clamd** : Documenté dans `veza-backend-api/docs/CLAMAV_SETUP.md` (limitation : lib abandonnée ; désactivation via `ENABLE_CLAMAV=false` = pas de scan).
- **Search** : Contrat documenté dans `veza-backend-api/docs/API_DOCUMENTATION.md` — recherche par ressource (`/api/v1/tracks/search`, `/api/v1/playlists/search`, `/api/v1/users/search`) ; pas dendpoint unifié `GET /api/v1/search`.
- **Endpoints marketplace / social** : Routes existantes (wishlist, panier, groups) ; pas de 501 ajouté.
### 1.3 Services Rust ✅
- **Redis** : Versions alignées (redis 0.32) dans `veza-chat-server` et `veza-stream-server` (Cargo.toml).
### 1.4 Infra et CD ✅
- **Docker-compose** : Mots de passe en dur remplacés par variables denvironnement (`POSTGRES_PASSWORD`, `RABBITMQ_DEFAULT_PASS`, etc.) avec valeurs par défaut pour le dev dans `docker-compose.yml`.
- **CD** : Commentaire ajouté dans `.github/workflows/cd.yml` : pour pousser vers un registry, configurer les secrets `DOCKER_REGISTRY`, `DOCKER_REGISTRY_USERNAME`, `DOCKER_REGISTRY_PASSWORD`.
---
## Phase 2 — Frontend : bugs et comportements critiques
### 2.1 Auth et 2FA ✅
- **2FA login** : Implémenté. Backend : `POST /api/v1/auth/login/2fa` (body : `email`, `password`, `code`, `remember_me`) ; frontend : `completeLogin2FA()` dans `apps/web/src/services/api/auth.ts`, action `complete2FALogin` dans le store, flux dans LoginPage (affichage TwoFactorVerify quand `requires_2fa`, puis appel API et redirection).
- **Typage auth** : Traité dans `apps/web/src/services/api/auth.ts` (réponse typée `LoginResponse`/`RegisterResponse`, options logout typées, `isAxiosError` pour les erreurs).
- **Redirect si déjà authentifié** : LoginPage / RegisterPage utilisent `authStore` / `useUser` ; à vérifier en conditions réelles (pas de boucle login → redirect).
### 2.2 Memory leaks et logs ✅
- **setTimeout** : ChatInput, SocialViewFeedItem, PostCard ont déjà un cleanup (clearTimeout dans le return du `useEffect`).
- **console.log** : GlobalSearchBar utilise `logger.debug` ; pas de suppression massive demandée pour linstant.
### 2.3 Accessibilité ✅
- **ChatInput** : Le champ principal a déjà `aria-label="Type a message"`.
- **Sidebar (layout)** : `components/layout/Sidebar.tsx` utilise déjà `FocusTrap` quand la sidebar est ouverte en mobile (`sidebarOpen && isMobile`).
---
## Phase 3 — Tests (en cours)
- **Vitest** : Suite complète **0 échec** (265 fichiers passés, 4 skippés ; 3230 tests passés, 87 skippés). Corrections appliquées :
- **SettingsPage.test.tsx** : Load error → assertion sur `getByRole('alert')` + contenu flexible ; save error → reset de `settingsSchema.safeParse` dans `beforeEach` (évite que le test « validation errors » laisse `safeParse` en échec pour le test suivant) ; userEvent pour le clic Save.
- **RegisterPage.test.tsx** : Terms → assertion sur « handleRegister non appelé » + optionnel message terms ; username « déjà pris » → `getAllByText` (plusieurs nœuds affichent le message) ; vérification notice → `findByText` + `act` autour du mock + rerender ; email dans la notice → texte partiel + `test@example.com` (texte split dans le DOM).
- **ForgotPasswordForm.test.tsx** : « should disable form while loading » → attente après `waitFor` pour que la promesse mock se résolve avant teardown (évite « state update after unmount »).
- **usePlaybackRealtime.test.ts** : 8 tests réactivés dans un second `describe` avec vrais timers (WebSocket lifecycle) ; plus de skip.
- **Tests par groupes (machines limitées)** : Vitest configuré pour limiter RAM/CPU (`pool: 'threads'`, `maxThreads: 2`, `fileParallelism: false`). Scripts npm ajoutés pour exécuter les tests par groupe : `test:auth`, `test:tracks`, `test:playlists`, `test:player`, `test:streaming`, `test:settings-profile-chat`, `test:components-ui`, `test:components-other`, `test:services`, `test:hooks`, `test:misc`. Commande `test:groups` lance tous les groupes séquentiellement. Ordre recommandé pour le diagnostic : petits groupes d'abord (settings-profile-chat, streaming, hooks, misc) puis les plus gros.
- **Providers / mocks** : Wrappers dans `src/test/` ; MSW dans `src/mocks/`. À aligner sur les contrats API si besoin.
- **Storybook** : `npm run test:storybook` (script `scripts/audit-storybook.js`) nécessite Storybook servi sur **port 6007** ; lancer `npm run build-storybook` puis servir le dossier `storybook-static` sur 6007, puis `npm run test:storybook`.
- **E2E** : Playwright (`npm run test:e2e`). Parcours critiques et fichiers listés dans `apps/web/e2e/README.md` (auth, smoke, playlists, search, profile, upload). Test search : `e2e/tests/search.spec.ts` (navigation `/search`, saisie requête, résultats ou état vide). Test 2FA : dans `auth.spec.ts` (skippé sauf si `E2E_2FA_CODE` et compte 2FA configurés).
## Phase 4 — Dette structurante ✅
- **Loading** : Composants centralisés en place — `LoadingState`, `LoadingSpinner`, `Skeleton`, `ButtonLoading` ; guide `apps/web/src/docs/LOADING_STATES_PATTERN.md` mis à jour avec section **LoadingState** et recommandation (full-page/block → LoadingState, list/card → Skeleton).
- **Modal → Dialog** : `Modal` déprécié (S1.4) ; `Dialog` sappuie dessus. Feature modals récents utilisent déjà `Dialog`. Préférer `Dialog` pour tout nouveau code.
- **Track type** : Commentaire ajouté dans `apps/web/src/features/tracks/types.ts` — source of truth pour Track = `features/player/types` ; champs upload/backend = `features/tracks/types/track.ts`.
- **Interceptors** : Documenté en en-tête dans `interceptors.ts` ; pas de découpage supplémentaire pour linstant.
## Phase 5 — Features fantômes et cohérence ✅
- **Coming Soon** : Routes documentées dans `apps/web/docs/FEATURE_STATUS.md``/gear`, `/live`, `/education`, `/queue`, `/developer` (placeholder `ComingSoon` dans `routeConfig.tsx`).
- **Feature flags** : Référence dans `FEATURE_STATUS.md` vers `src/config/features.ts` et `VITE_FEATURE_*` ; liste des flags (TWO_FACTOR_AUTH, PLAYLIST_*, HLS_STREAMING, ROLE_MANAGEMENT, NOTIFICATIONS).
- **Marketplace / groups / search** : Mention dans `FEATURE_STATUS.md` (routes marketplace, search par ressource, groups dans Social).
- **Typo** : `useLibraryManager.ts` — message « coming soon available » corrigé en « coming soon — available in the next release ».
## Phase 6 — Maturité ✅
- **TypeScript** : `npx tsc --noEmit` exécuté — 0 erreur.
- **Docs** : `FEATURE_STATUS.md` créé (Coming Soon + feature flags + marketplace/search) ; `LOADING_STATES_PATTERN.md` enrichi ; `REMEDIATION_PROGRESS.md` à jour.
- **UX** : Checklist finale rappelée ci-dessous (skip link, aria-label, focus trap, pas de console.log en prod).
---
## Checklist de validation finale (rappel)
- **Validation légère (machine limitée)** : `./scripts/validate-light.sh` — évite `go test ./...` et Playwright qui peuvent saturer la RAM. Lance : go build, tsc, npm build, tests auth/hooks/services/misc, cargo build.
- `npx vitest run` : 0 échec (ou < 5 % skippés avec ticket). Sur machine limitée en RAM/CPU : utiliser `npm run test:groups` ou les scripts par groupe (`test:auth`, `test:tracks`, etc.) pour éviter la saturation des ressources.
- `npm run build` : succès sans warning bloquant.
- `npx tsc --noEmit` : 0 erreur.
- `npm run test:storybook` : 0 erreur. **Procédure de validation Storybook sur 6007** :
1. `cd apps/web && npm run build-storybook`
2. Démarrer le serveur sur le port **6007** : `node scripts/serve-storybook-static.cjs` (ou `npx serve storybook-static -l 6007`) et le laisser tourner
3. Dans un autre terminal : `npm run test:storybook` (le script [scripts/audit-storybook.js](apps/web/scripts/audit-storybook.js) cible `http://localhost:6007` et ne démarre pas le serveur). Option : `npm run test:storybook:playwright` démarre automatiquement le serveur via [playwright.config.storybook.ts](apps/web/playwright.config.storybook.ts).
- Aucun `console.log` / debug en prod.
- Skip link + aria-label ChatInput + focus trap Sidebar en place.
- 2FA login : backend à compléter puis frontend à brancher.