# Audit fonctionnel – FailDaily (31/10/2025)

## Synthèse rapide
- **Inscription** : bloquée sur une base neuve – la table `profiles` auto-créée par le backend ne correspond pas au schéma attendu (`backend-api/src/controllers/authController.js:38` vs `backend-api/migrations/faildaily.sql:496`), ce qui provoque une erreur SQL dès l’insertion.
- **Emails de vérification** : indisponibles – l’envoi est désactivé par défaut faute de configuration (`app_config` ne contient pas `email`) et l’endpoint `/registration/verify-email` ne traite jamais les tokens enregistrés (double définition dans `backend-api/src/routes/registration.js:496` et `:602`).
- **Publication de fails** : le flux principal fonctionne mais les images sont perdues. Le front transmet bien l’URL (`frontend/src/app/services/fail.service.ts:75-113`) mais `mysqlService.createFail` remplace systématiquement `image_url` par `null` (`frontend/src/app/services/mysql.service.ts:637-676`).
- **Déblocage de badges** : la logique serveur (fails, réactions, commentaires) est en place et alimente `user_badges`. Attention cependant au flux mineur : le front attend `requiresParentalConsent` que l’API ne renvoie pas.
- **Configuration du profil** : dépend de la même table `profiles` mal créée dynamiquement ; dans un environnement initialisé via `ensureProfilesTable`, la mise à jour / récupération échoue.

## Constats détaillés & impacts

### 1. Parcours d’inscription
- Le backend crée la table `profiles` « à la volée » sans colonne `id` (`backend-api/src/controllers/authController.js:38-52`), alors que tout le reste du code (y compris le jeu de migrations officiel) attend un identifiant primaire distinct (`backend-api/migrations/faildaily.sql:496-514`). Sur une base vierge, l’insertion `INSERT INTO profiles (id, …)` lève `ER_BAD_FIELD_ERROR`, ce qui annule l’inscription.
- Le frontend s’appuie sur `AuthService.register` qui considère deux scénarios : adulte ou `requiresParentalConsent` (`frontend/src/app/services/auth.service.ts:818-915`). Comme l’API ne renvoie jamais ce drapeau (`backend-api/src/controllers/authController.js:272-282`), un mineur est traité comme adulte côté UI, reçoit un JWT et pense être connecté alors que toutes les requêtes suivantes échoueront (`authenticateToken` refuse `account_status = 'pending'`). Impact : expérience incohérente et blocage silencieux.

**Recommandations**
1. Harmoniser le schéma `profiles` : aligner `ensureProfilesTable` sur la migration officielle (ajouter `id`, `preferences`, `stats`, clés uniques) ou supprimer cette création à la volée pour forcer l’exécution du script SQL.
2. Étendre la réponse de `/api/auth/register` pour inclure `accountStatus` / `requiresParentalConsent` et mettre à jour le frontend pour refléter l’état réel (ne pas marquer `emailConfirmed` / `registrationCompleted` tant que ce n’est pas vrai en base).

### 2. Emails de bienvenue / vérification
- L’envoi d’email est conditionné par `app_config.email.enabled`. Or la configuration fournie ne comporte aucune entrée `email` (`backend-api/migrations/faildaily.sql:83-110`), ce qui force `getEmailConfig` à renvoyer `{ enabled: false }` et `sendMail` à abandonner (`backend-api/src/utils/mailer.js:36-59`). Sans saisie manuelle en base et sans variables SMTP, aucun message ne partira.
- La confirmation d’email est impossible : Express enregistre deux handlers pour `POST /registration/verify-email`. Le premier vérifie un JWT (`backend-api/src/routes/registration.js:496-528`) et renvoie une erreur pour les tokens hexadécimaux générés lors de l’inscription. Comme il répond avant de passer la main, le second handler, qui exploite correctement la table `email_verification_tokens` (`backend-api/src/routes/registration.js:602-618`), n’est jamais exécuté.

**Recommandations**
1. Ajouter une ligne `INSERT INTO app_config` avec `{ "enabled": true, "sender": … }` et documenter la configuration (`SMTP_HOST`, `SMTP_USER`, etc.).
2. Fusionner les deux endpoints `/registration/verify-email` en conservant la version basée sur `email_verification_tokens`, puis couvrir le cas par un test d’intégration.
3. Propager l’état `email_confirmed` au frontend (actuellement forcé à `true`) pour offrir un retour utilisateur cohérent.

### 3. Publication de fails
- Côté frontend, `FailService.createFail` gère l’upload de l’image via `/api/upload/image` et transmet l’URL finale (`frontend/src/app/services/fail.service.ts:82-102`). Toutefois, `mysqlService.createFail` ignore la propriété `image_url` reçue : il ne renseigne que la variable locale `imageUrl`, initialisée à `null` tant qu’un fichier `File` n’est pas fourni (`frontend/src/app/services/mysql.service.ts:637-676`). Résultat : les fails sont créés sans image malgré l’upload réussi.
- Le backend `FailsController.createFail` fonctionne correctement (contrôles, points, badges) et nécessite simplement que l’URL soit propagée (`backend-api/src/controllers/failsController.js:62-162`).

**Recommandations**
1. Adapter `mysqlService.createFail` pour prioriser `fail.image_url` si fourni (et ne lancer un nouvel upload que s’il manque).
2. Ajouter un test e2e qui valide l’affichage d’un fail avec image.

### 4. Déblocage de badges
- Lors de la création d’un fail, `checkBadgeProgress` attribue les badges `fail_count` pertinents (`backend-api/src/controllers/failsController.js:135-210`). Les réactions et commentaires déclenchent `badgesService.checkAndUnlockBadges` (`backend-api/src/controllers/reactionsController.js:60-157`, `backend-api/src/controllers/commentsController.js:154-171`), ce qui couvre la plupart des critères.
- Le service Angular se base sur `/users/me/badges` et recalcule la liste (`frontend/src/app/services/badge.service.ts:1-120`, `frontend/src/app/services/mysql.service.ts:1120-1150`). Pas d’anomalie majeure détectée.

**Points de vigilance**
- S’assurer que les migrations chargent toutes les définitions de badges nécessaires et que `user_points` est alimentée (déjà le cas via `awardReactionPoints`).
- Vérifier que le flux mineur (compte en attente) n’empêche pas la mise à jour de badges une fois le consentement validé (tests recommandés).

### 5. Configuration du profil
- L’API `GET/PUT /api/auth/profile` repose sur la présence de `profiles.id` (sélection / update distincts, cf. `backend-api/src/controllers/authController.js:458-640`). Si la table a été mal créée par `ensureProfilesTable`, ces requêtes échouent (`Unknown column 'id'`) et la mise à jour devient impossible.
- Côté frontend, `EditProfilePage` appelle `authService.updateUserProfile`, qui relaie vers `PUT /api/auth/profile` (`frontend/src/app/pages/edit-profile/edit-profile.page.ts:330-373` & `frontend/src/app/services/mysql.service.ts:440-506`). Le flux est cohérent, sous réserve que l’API fonctionne.

**Recommandations**
- Corriger en priorité la création de `profiles`.
- Ajouter un test d’intégration simple : création d’un utilisateur, modification du `displayName`, vérification en base.

## Plan d’action priorisé
1. **Corriger le schéma `profiles`** (alignement script/ensure) puis rejouer les tests d’inscription sur une base vierge.
2. **Réparer la vérification email** (fusion handler, config `app_config.email`, documentation SMTP) et confirmer le parcours complet (inscription → mail → validation → connexion).
3. **Fixer la remontée d’images lors de la création d’un fail** côté frontend (`mysqlService.createFail`).
4. **Exposer l’état réel d’inscription et d’email** dans la réponse `/api/auth/register` et adapter l’UI (mineurs / comptes en attente).
5. **Compléter la batterie de tests** (inscription adulte/mineur, fail avec image, vérification email, édition profil) afin de verrouiller ces régressions.
