# Refonte auth DA 2.0 + durcissement backend + rework notifications

**Date :** 2026-07-03
**Projet :** vulcan-aff-v2 (Symfony 7.2)
**Statut :** design validé (verbalement) — additions notifications intégrées

## 1. Contexte & problème

- **Bug bloquant signalé** : clic sur lien d'activation (et de reset mdp) →
  `TypeError: Invalid return value: callable object expected, "int" returned from router.php`.
  **Cause racine** (confirmée par lecture) : le serveur de dev est lancé via un
  `router.php` (scratchpad) qui ne fixe pas `$_SERVER['SCRIPT_FILENAME']`. Symfony
  Runtime (`vendor/autoload_runtime.php:9`) fait `require SCRIPT_FILENAME` → re-require
  du `router.php`, qui n'a pas de `return` final → renvoie `int 1` → `!is_object` →
  TypeError. **Impacte toutes les routes dynamiques**, pas seulement l'activation. Le
  code d'activation/reset lui-même n'est jamais atteint.
- **Formulaire inscription "dépassé"** : `templates/client_register/index.html.twig`
  utilise l'ancien design system (CSS atomique `dp-f-c`, `ft-f-chomsky`, `promptRegister`,
  `bg-va-degrade`), pas la DA 2.0 (`ds-v2.css`).
- **Validation serveur absente** : le controller lit `email/password/nom/prenom` en brut,
  ne lit jamais `confirm_password`, ne valide ni format email ni force mdp côté serveur
  (uniquement en JS → contournable).
- **Notifications** : bland ("hyper bateau"), collées en haut de l'écran, et deux
  implémentations divergentes (legacy globale + v2 scopée new*).

## 2. Décisions validées

| Sujet | Décision |
|-------|----------|
| Backend | **Fix + durcir en place** — garder archi custom (entité `Client`, `action_token`/`dh_token`, auth session, honeypot). Pas de bundles Symfony natifs. |
| Périmètre DA | **Suite auth complète + emails** |
| Layout auth | **Split immersif** — plein écran, sans header/footer site (aside visuel forge + panneau formulaire) |
| Background aside | Choix libre, ajusté visuellement à l'écran |
| Notifications | **Rework visuel complet + repositionnement** + unification en un seul système global |

## 3. Bugfixes

- **B1 — serveur / TypeError.** Corriger le lancement du serveur de dev pour que
  `SCRIPT_FILENAME` pointe sur `public/index.php` (router qui fixe `SCRIPT_FILENAME`
  avant le `require`, ou `symfony server:start`). C'est LA cause de l'erreur signalée.
- **B2 — `ClientRegisterController.php:355`.** Le lien de renvoi d'activation appelle
  `generateUrl('app_confirm_email', ['token' => $actionToken], 0)` sans `email` alors que
  la route `/confirm-email/{token}/{email}` l'exige → `MissingMandatoryParameters`.
  Ajouter `'email' => $existingClient->getEmail()`.
- **B3 — `EditPasswordController.php:95`.** `$email = (new Email())...` écrase la string
  email par un objet `Email` ; ensuite `reussite` (:108) et le `catch` (:117) reçoivent
  l'objet. Renommer la variable du mail (`$mail`).

## 4. Backend — durcissement (en place)

- Nouvelle méthode privée de **validation serveur** dans `ClientRegisterController`
  (inscription) et vérif équivalente côté reset :
  - email : non vide + `filter_var(FILTER_VALIDATE_EMAIL)` + longueur max
  - nom / prénom : trim, non vide, longueur max
  - password : min 8 + complexité (miroir du score JS ≥ 3 classes)
  - `confirm_password` == `password` (aujourd'hui jamais vérifié côté serveur)
- **Échec de validation → re-render du formulaire** avec erreurs inline + valeurs
  ressaisies (hors mdp) + token CSRF régénéré (au lieu de la page erreur générique).
- Conservés tels quels : honeypot, contrôle de timing, rate-limit IP hashée, flux token,
  auth session.
- Routes / entité / noms de route : **inchangés** (les pages new* pointent déjà dessus).

## 5. Front — layout auth (split immersif)

- **Nouveau layout** `templates/_auth/base_auth.html.twig` : `<head>` complet (polices
  Fraunces/Inter/IBM Plex Mono), `ds-v2.css` + `ds-v2-pages.css` + nouveau
  `ds-v2-auth.css` + `ds-v2-toast.css`, conteneur plein écran `.auth-shell`.
  **Aucun** header/footer/cookie-menu. `ds-v2-auth.js` + `ds-v2-toast.js` chargés.
- **Nouveau CSS** `public/styles/ds-v2-auth.css` :
  - `.auth-shell` — grid 2 col (aside / panneau) → 1 col < 900px
  - `.auth-aside` — image forge + voile sombre (`--v2-forge`) + logo + accroche mono
  - `.auth-panel` — colonne formulaire, centrée, scrollable
  - `.auth-strength` — jauge force mdp restylée DA 2.0
  - `.auth-alt-link`, `.auth-result` (état succès avec icône ligne)
  - **Réutilise** : `.chk-field` (labels flottants + halo vert focus + `.invalid`),
    `.nhp-btn` / `.nhp-btn--primary`, tokens `--v2-*`.
- **JS** `public/scripts/ds-v2-auth.js` : force mdp + correspondance + garde-fous submit,
  via le toast DA 2.0 (plus de legacy).
- Pages migrées (extends `base_auth.html.twig`) :
  - `client_register/index` (inscription), `client_register/reussite`,
    `client_register/activation_reussi`
  - `client-login/index` (connexion)
  - `edit_password/request_email`, `edit_password/index`,
    `edit_password/reussite`, `edit_password/password_edited`
  - `erreur/global-error` (variante auth ou version DA 2.0 partagée)

## 6. Front — rework notifications (global)

- **`public/styles/ds-v2-toast.css`** (nouveau, chargé **globalement** dans
  `base.html.twig` ET `base_auth.html.twig`) :
  - `.v2-toast-region` — `position: fixed`, **offset depuis le haut** (dégage le header),
    à droite, empilement vertical, `z-index` élevé
  - `.v2-toast` **retravaillé** — caractère forge (surface + bordure acier, label mono
    majuscule type "SUCCÈS/ATTENTION/ERREUR", accent vert/ember, icône ligne, ombre
    soignée) ; variantes `--success` / `--warn` / `--error` ; anim in/out
- **`public/scripts/ds-v2-toast.js`** (nouveau) : `window.showNotification` unique,
  émet le markup `.v2-toast`, crée `.v2-toast-region` si absente.
- `script.js` : **supprimer** l'ancienne `showNotification` (grosses icônes / CSS atomique).
- `ds-v2-app.js` : **supprimer** la redéfinition locale de `showNotification` (désormais globale).
- `ds-v2-pages.css` : **retirer** le bloc `.v2-toast` (déplacé vers `ds-v2-toast.css`).
- `base.html.twig` : remplacer le wrapper `#notification-container` (`t-0 r-0`) par
  `.v2-toast-region`.
- Signature `showNotification({success, title, message})` **inchangée** → tous les appels
  existants (script.js, pages) continuent de fonctionner.

## 7. Emails DA 2.0

Refonte de `emails/confirmation_inscription.html.twig`, `emails/activation_compte.html.twig`,
`emails/reset_password.html.twig` : gabarit HTML e-mail (tables + styles inline, compatible
clients mail), en-tête forge sombre, bouton CTA vert, typographie DA 2.0. Variables Twig
existantes conservées (`confirmationLink`, `nom`, `prenom`, `connectLink`).

## 8. Data flow (corrigé, fond inchangé)

1. `GET /inscription` → formulaire (CSRF + timestamp anti-bot).
2. `POST /inscription` → honeypot → timing → rate-limit → CSRF → **validation serveur** →
   `Client(status=NEW, action_token)` → email confirmation (lien absolu) → page réussite.
3. Lien mail → `GET /confirm-email/{token}/{email}` → délai 72 h → `status=ACTIVE` →
   email d'activation → page activation réussie.
4. Reset : `/modification-mdp` (saisie email) → email reset (lien 20 min) →
   `/entrer-nouveau-mdp/{email}/{token}` → form → `POST /modifier-mdp` → page mdp modifié.

## 9. Vérification

- Twig lint sur tous les templates touchés.
- Serveur relancé correctement (SCRIPT_FILENAME) — plus de TypeError.
- Parcours pilotés navigateur :
  - inscription → récupérer `action_token` en base → `GET /confirm-email/...` →
    activation → login
  - reset → récupérer token → `/entrer-nouveau-mdp/...` → nouveau mdp → login
  - validation serveur : POST sans JS (email invalide / mdp faible / confirm ≠) → erreurs inline
  - notifications : déclencher succès/attention/erreur, vérifier offset haut + style + empilement
- 0 erreur console. Rendu emails contrôlé (HTML capturé).

## 10. Hors périmètre

- Migration vers la sécurité native Symfony (VerifyEmail/ResetPassword/form_login).
- Refonte des autres pages déjà en DA 2.0.
- Livraison réelle des emails (SMTP) — vérif via token en base / capture HTML.

## Notes

- Le projet **n'est pas un dépôt git** → spec non committée.
