# FailDaily - Guide operationnel pour agents IA

**Langue : tous les echanges avec l'agent se font en francais.**

## 1) Objectif de ce fichier

Ce document est une base de travail **concrete** pour un agent IA qui doit modifier ce repo sans casser le produit.
Regle de priorite en cas de conflit:

1. Code runtime (`backend-api/src`, `frontend/src`) et migrations SQL recentes
2. CI (`.gitlab-ci.yml`)
3. Ce fichier
4. Le reste de la doc (souvent utile, mais parfois obsolete)

## 2) Environnement de developpement

- OS : Windows 11 + WSL2 (Ubuntu)
- **Toutes les commandes bash sont a executer dans WSL**, jamais dans PowerShell ou cmd
- Projet situe dans `~/projects/FailDaily` (filesystem WSL ext4, pas sur /mnt/d/)
- Terminal VSCode : WSL bash
- Ne jamais utiliser de chemins Windows (`D:\...`), toujours des chemins Linux
- Gestionnaire de paquets : `pnpm`
- Exception : scripts `scripts/*.ps1` → PowerShell Windows uniquement

## 3) Snapshot reel du repo

Monorepo PNPM avec 3 workspaces:

- `backend-api` — Node.js 22, Express 5, MySQL 8, CommonJS
- `frontend` — Angular 21, Ionic 8, Capacitor (iOS/Android), ESM
- `e2e` — Cypress via Docker Compose

Fichiers structurants:

- `package.json` (root workspaces + scripts communs)
- `pnpm-workspace.yaml`
- `backend-api/server.js` (bootstrap app, secrets, middlewares, route mounting)
- `backend-api/migrations/faildaily_bdd.sql` (dump prod = seule source de verite SQL, bake dans l'image Docker)
- `docker/docker-compose.local.yml` (stack locale)
- `docker/docker-stack.ovh-cloud.yml` (stack prod Swarm)
- `.gitlab-ci.yml` (pipeline valide/build/deploy)

## 4) Avant tout changement

1. Lire `git status --short` (toujours verifier, l'etat peut changer)
2. Ne pas annuler les changements existants sans demande explicite
3. Isoler ton patch sur les fichiers cibles

Note: la migration OVH CloudDB → MySQL embarque Docker Swarm est terminee. Une seule DB en prod.

## 5) Architecture runtime

### Backend

- Entree: `backend-api/server.js`
- Secrets: `backend-api/src/config/loadSecrets.js`
- DB principale: `backend-api/src/config/database.js`
- DB logs (pool secondaire optionnel): `backend-api/src/config/database-logs.js`
  - En **prod Swarm** : LOGS_DB_NAME = `faildaily_bdd` (meme base que la principale → 1 seule DB physique)
  - En **local** : docker-compose prevoit encore un conteneur `logs_db` separe (config locale legacy, a unifier)
  - Desactivable via `LOGS_DB_DISABLED=true`
- Routes montees (completes) :
  - `/api/auth`
  - `/api/registration`, `/api/age-verification`, `/parent-consent` (page HTML parental)
  - `/api/legal`
  - `/api/fails`, `/api/comments`, `/api/reactions`
  - `/api/badges`
  - `/api/users`, `/api/follows`
  - `/api/consents`, `/api/privacy-settings`
  - `/api/upload`
  - `/api/push`
  - `/api/support`
  - `/api/share`
  - `/api/admin`, `/api/admin/moderation`, `/api/admin/logs`, `/api/logs`
  - `/api/health`, `/health`, `/api/info`

### Frontend

- Entree routing: `frontend/src/app/app.routes.ts`
- API base URL: `environment.api.baseUrl` (majoritairement `"/api"`)
- Service legal: `frontend/src/app/services/legal.service.ts`
- Inscription : `AuthService.register()` → `POST /auth/register` (seul flow utilise par le front, via `auth-book.page.ts`)
- Reset password : `AuthService.requestPasswordReset()` → `POST /auth/password-reset`
- Verification email : `VerifyEmailPage` → `POST /registration/verify-email`
- Messages temps reel : `ChatService` → Socket.IO + `/api/messages/*`

### Data / SQL

- **Source de verite unique : `backend-api/migrations/faildaily_bdd.sql`** (dump prod complet, 49 tables)
- Ce dump est bake dans l'image Docker `faildaily-mysql` via `docker/mysql.Dockerfile`
- C'est le **seul fichier SQL utilise en prod**. Les autres fichiers SQL du repo (`database-schema.sql`, `faildaily.sql`) sont historiques/obsoletes — les ignorer.
- **Pas de fichiers de migration separes** : quand on ajoute une migration en prod, on regenere le dump et on le commite. Le dump sert aussi a **verifier si une migration a bien ete appliquee** (si c'est pas dans le dump, c'est pas en prod).
- Script de regeneration (WSL) : `scripts/dump-bdd-local.sh` (voir section 15)
- **Backup automatique VPS** : cron quotidien 3h dans `/home/ubuntu/backups/`, retention 7 jours

## 6) Commandes de travail fiables

Installation:

```bash
pnpm install --frozen-lockfile
```

Dev Node (sans Docker):

```bash
pnpm -C backend-api dev
pnpm -C frontend start
```

Lint/build:

```bash
pnpm -C backend-api lint
pnpm -C frontend lint
pnpm -r build
```

Tests backend (Jest, sequentiel avec --runInBand):

```bash
pnpm -C backend-api test                              # tous les tests (necessite DB)
pnpm -C backend-api test -- --testPathPatterns=auth    # un test specifique par pattern
```

Tests frontend (Karma/Jasmine):

```bash
pnpm -C frontend test
```

Smoke backend en mode CI-like (sans DB reelle):

```bash
TMPDIR=/tmp TMP=/tmp TEMP=/tmp \
NODE_ENV=test DB_DISABLED=true JWT_SECRET=test_jwt_secret_ci \
SMTP_PASS=fake_smtp_pass OPENAI_API_KEY=fake_openai_key \
LOGS_DB_PASSWORD=fake_logs_db_pass DB_PASSWORD=fake_db_pass \
pnpm -C backend-api test:smoke
```

Note: dans certains sandboxes, Jest peut echouer avec `EPERM listen 0.0.0.0` ou erreurs de dossier temp.  
Ce n'est pas forcement un bug applicatif.

Local Docker stack:

```bash
docker compose -f docker/docker-compose.local.yml up --build -d
```

## 7) Variables d'environnement critiques

Le backend charge via Docker secrets puis env vars.

Obligatoires au demarrage (validation explicite):

- `DB_HOST`
- `DB_USER`
- `DB_PASSWORD`
- `DB_NAME`
- `JWT_SECRET`

Importantes:

- `DB_PORT`
- `LOGS_DB_HOST|PORT|USER|PASSWORD|NAME` — En prod Swarm, tous pointent vers la **meme instance** MySQL embarquee (base `faildaily_bdd`). Le pool logs reste optionnel et desactivable.
- `SMTP_HOST|PORT|SECURE|USER|PASS|FROM`
- `OPENAI_API_KEY`
- `FRONTEND_URL` (aussi propagee dans `APP_WEB_URL` par `server.js`)
- `CORS_ORIGIN` (optionnel, origines supplementaires separees par virgules)
- `LOGS_DB_DISABLED` (mettre a `true` si on ne veut pas de pool logs separee)

Regles prod:

- `JWT_SECRET` min 64 caracteres
- pas de pattern faible (`dev`, `test`, `changeme`, etc.)

## 8) Contrats et invariants critiques

### Auth/inscription

**Flow d'inscription unique** : le front utilise exclusivement `POST /api/auth/register` (via `AuthService.register()`).
Ce endpoint gere tout : creation user, profil, detection mineur, envoi email parental.

Le module `/api/registration/*` fournit des **endpoints utilitaires** complementaires :

- `GET /registration/check-display-name` — verifie disponibilite pseudo (appele par `AuthService` avant inscription)
- `POST /registration/generate-display-name` — genere un pseudo unique si collision (appele par `AuthService`)
- `POST /registration/verify-email` — confirmation email (appele par `VerifyEmailPage`)
- `GET /registration/parent-consent` — page HTML consentement parental (lien dans l'email envoye au parent)
- `POST /registration/parent-consent/confirm` — validation consentement (formulaire JS dans la page HTML ci-dessus)

Endpoints backend **orphelins** (existent mais aucun appel front) :

- `POST /registration/register` — doublon non branche, le front n'utilise que `/auth/register`
- `GET /registration/check-email` — le front utilise `/auth/check-email`
- `POST /registration/resend-verification` — pas de bouton "renvoyer" dans l'UI
- `GET /registration/validate-referral` — stub, retourne toujours `false`
- `GET /registration/stats` — admin seulement, aucun appel front

Invariants age:

- `<13`: refus
- `13-16`: compte pending / consentement parental requis (email envoye au parent avec vrai token crypto)
- `>=17`: compte actif

Unicite `display_name` geree contre `profiles` et `pending_profiles`.

### Legal documents

- Backend: `GET /api/legal` et `GET /api/legal/:slug`
- Front attend ces slugs:  
  `legal-notice`, `terms-of-service`, `privacy-policy`, `moderation-charter`, `help-resources`, `age-restrictions`
- Migration 2026-03-02 convertit `legal_documents.document_type` vers `VARCHAR` + upsert des 6 docs

### Health

- `/health` simple
- `/api/health` detaille (DB, logs DB, memoire, response time, JWT, SMTP)

## 9) Ce qui est en cours / fragile / casse

1. **Outils admin d'analyse partiellement stubbes**

- `MysqlService.analyzeDatabaseIntegrity()` retourne "indisponible".
- `analyzeSpecificFail`, `fixInvalidReactionCounts`, `deleteOrphanedReaction` sont des stubs/throws.
- Cote backend, pas d'endpoint d'analyse equivalent observe.

2. **Documentation heterogene**

- Plusieurs docs historiques ne refletent plus exactement l'etat runtime.
- **Source de verite SQL : uniquement `backend-api/migrations/faildaily_bdd.sql`**.
- Toujours verifier dans le code avant d'agir.

3. **DB logs locale non unifiee**

- Le fichier `docker/docker-compose.local.yml` provisionne encore un conteneur MySQL separe `faildaily_logs_db_local`.
- En prod OVH, les variables `LOGS_DB_*` pointent vers la meme base `faildaily_bdd`.
- La config locale est donc desynchronisee avec la prod → a unifier si besoin (ou laisser avec `LOGS_DB_DISABLED=true` en local).

4. **Dump BDD potentiellement desynchronise**

- Le dump peut etre desynchronise si le schema evolue en prod sans regeneration.
- Mettre a jour regulierement via `scripts/dump-bdd-local.sh` (voir section 15).

5. **Endpoints backend orphelins dans `/registration`**

- `POST /registration/register`, `GET /check-email`, `POST /resend-verification`, `GET /validate-referral`, `GET /stats` existent mais ne sont appeles par aucun code front. Les garder ou les supprimer est un choix delibere (utilite future possible pour admin/API).

## 10) Decisions explicitement non retenues (ou suspendues)

1. **Codes de parrainage**

- Mentionnes mais non implementes (table absente, logique ignoree).

2. **Dependance aux triggers DB pour profils**

- Le code cree/met a jour des profils manuellement dans plusieurs flux (commentaires "remplace le trigger ... OVH Cloud").
- Intention: reduire la dependance a des triggers pas toujours garantis selon environnement.

3. **"Public fails" vraiment publics**

- Les routes `fails/public` restent protegees par auth dans l'etat actuel.

## 11) Fichiers a NE PAS toucher en premier

Modifier seulement avec raison explicite + verification complete:

- `.gitlab-ci.yml`
- `docker/docker-stack.ovh-cloud.yml`
- `backend-api/server.js`
- `backend-api/src/config/loadSecrets.js`
- `backend-api/src/config/database.js`
- `backend-api/migrations/faildaily_bdd.sql` (dump reel prod — ne jamais editer a la main, regenerer via script)
- tous les `.env*` (jamais commiter de secret)

## 12) Protocole agent recommande

Comportement attendu:

- pragmatique, conservateur sur la prod
- patchs petits et cibles
- pas de refactor massif sans demande
- executer les checks relies au perimetre touche
- signaler explicitement les limites de verification

Sequence minimale:

1. `git status --short`
2. Lire les fichiers concernes + routes/contrats relies
3. Implementer
4. Lancer au moins lint/test local pertinent
5. Donner un resume: fichiers modifies, risques, tests lances/non lances

## 13) Matrice d'impact rapide

Si tu modifies `backend-api/src/routes/auth.js` ou `authController.js`:

- verifier `frontend/src/app/services/auth.service.ts`
- verifier tests auth backend

Si tu modifies `backend-api/src/routes/registration.js`:

- verifier `frontend/src/app/services/mysql.service.ts` (appelle `check-display-name`, `generate-display-name`)
- verifier `frontend/src/app/services/auth.service.ts` (appelle `check-display-name` via `MysqlService`)
- verifier `frontend/src/app/pages/verify-email/` (appelle `verify-email`)
- verifier flow mineur/parental (page HTML `parent-consent` + `parent-consent/confirm`)

Si tu modifies legal (`/api/legal`, migrations legal):

- verifier `frontend/src/app/services/legal.service.ts`
- verifier pages `legal` et `legal-document`

Si tu modifies schema SQL:

- ajouter migration idempotente
- verifier compat route + controllers
- verifier import local/CI

## 14) Maintenance de ce fichier (anti-doc qui ment)

Mettre a jour `claude.md` a chaque changement sur:

- contrats API
- scripts de run/test/build
- variables d'env obligatoires
- migrations structurantes
- zones casses / stubs / decisions suspendues

Toujours dater la mise a jour en haut du fichier.

## 15) Systeme auto-dump BDD (local WSL)

Le dump `backend-api/migrations/faildaily_bdd.sql` est la **seule source de verite schema**.
Il doit etre regenere regulierement depuis OVH Cloud.

### Important

- Le script recommande est `scripts/dump-bdd-local.sh` (bash natif WSL).
- Le script PowerShell `scripts/dump-bdd-local.ps1` reste disponible seulement en fallback Windows.

### Script manuel

```bash
# Dump depuis le MySQL embarque dans Swarm (via SSH vers le VPS)
./scripts/dump-bdd-local.sh
# Parametre optionnel si l'alias SSH est different :
./scripts/dump-bdd-local.sh --ssh-host ubuntu@141.94.42.172
```

### Backup automatique VPS (cron)

Le VPS fait un backup quotidien automatique via `/home/ubuntu/scripts/dump-faildaily.sh` (cron a 3h, retention 7 jours) :
```
0 3 * * * /home/ubuntu/scripts/dump-faildaily.sh >> /home/ubuntu/backups/dump.log 2>&1
```
Fichiers dans `/home/ubuntu/backups/` sur le VPS. Logs dans `/home/ubuntu/backups/dump.log`.

Le script utilise `set -o pipefail` + validation de taille minimale (100 KB) + logging explicite.

### Workflow apres dump

1. Verifier que le fichier a bien ete mis a jour
2. `git add backend-api/migrations/faildaily_bdd.sql && git commit -m "chore: update db dump $(date +%F)"`
3. Mettre a jour la date `Last verified` dans ce fichier

### A noter

- Le script passe par SSH vers le VPS et execute le dump dans le conteneur MySQL Docker.
- Prerequis : acces SSH configure vers le VPS (`ssh ovh` doit fonctionner depuis WSL).
- Le mot de passe DB est lu depuis le Docker secret sur le VPS, pas besoin de le connaitre localement.
- **Le cron VPS tourne a 3h du matin** : le dump commite en journee contient les donnees jusqu'a 3h du matin du meme jour, pas les donnees creees dans la journee.

## 16) Regles de communication agent

Ces regles s'appliquent a tout echange avec un agent IA sur ce projet :

### Honnetete sur les donnees

- Ne jamais affirmer qu'une donnee est "a jour" sans avoir verifie la date du dernier enregistrement dans la **table concernee** (pas juste la date du dump)
- Toujours indiquer explicitement jusqu'a quelle date les donnees locales sont synchronisees
- Si une verification echoue (SSH inaccessible, token invalide, etc.), le dire immediatement sans contourner silencieusement
- Faire exactement ce qui est demandé, rien de plus
- Si je ne sais pas, je le dis — point
- Ne jamais inventer une information, une fonction, une API, un comportement
- Vérifier le code avant de le donner — s'il est incorrect, ne pas le donner
- Ne jamais créer de failles de sécurité (injections, secrets exposés, auth bypassée, etc.)
- Quand je me trompe et que tu me corriges, j'assume et je corrige — sans justification ni excuses dramatiques
- Ne pas compléter, "améliorer" ou reformuler ce qui n'a pas été demandé
- Si une chose a plusieurs solutions, les présenter brièvement — sans choisir à ta place sauf si tu le demandes
- Ne pas répéter ce que tu viens de dire pour "confirmer" — ça rallonge pour rien
- Si une tâche est ambiguë, poser UNE seule question claire avant d'agir
### Limites a declarer explicitement

- Si l'acces SSH au VPS echoue : le dire clairement, ne pas essayer une autre methode sans mentionner l'echec
- Si le dump local est potentiellement desynchronise : le mentionner AVANT de tirer des conclusions sur les donnees
- Si une route API retourne des donnees inconsistantes avec la prod visible : chercher POURQUOI avant de conclure que ca marche

### Synchronisation DB locale

- Le dump local (`faildaily_bdd.sql`) reflète la prod **jusqu'à 3h du matin du jour du dernier dump**
- Les données créées dans la journée ne sont PAS dans le dump local
- Avant toute affirmation sur l'état des données d'un utilisateur, vérifier `SELECT MAX(created_at) FROM fails` (ou la table concernée) pour savoir jusqu'où les données locales s'étendent
