[Front] Page de connexion #25

Closed
opened 2026-09-01 09:28:54 +00:00 by florian · 2 comments
Member

Exigence couverte

00

Épreuve servie

EC01 — Architecture

Charge estimée

No response

Ce qu'on veut obtenir

Faire une page de connexion avec mail et mot de passe

Fonctionnalité :

  • Champs Email et Password pour la connexion
  • Bouton reset Password

Critères d'acceptation

  • L'utilisateur peut se connecter
  • Respecter la RGAA
  • Respecter le responsive

Comment on le vérifie

Tests Unitaires
Capture d'écran

Hors périmètre

No response

### Exigence couverte 00 ### Épreuve servie EC01 — Architecture ### Charge estimée _No response_ ### Ce qu'on veut obtenir Faire une page de connexion avec mail et mot de passe **Fonctionnalité :** - Champs Email et Password pour la connexion - Bouton reset Password ### Critères d'acceptation - [ ] L'utilisateur peut se connecter - [ ] Respecter la RGAA - [ ] Respecter le responsive ### Comment on le vérifie Tests Unitaires Capture d'écran ### Hors périmètre _No response_
florian added this to the EnerVision project 2026-09-01 09:28:57 +00:00
olivier self-assigned this 2026-09-01 13:26:11 +00:00
Member

Maquettes de la page de connexion

Les quatre écrans sont validés côté charte graphique et disponibles dans Figma : EnerVision — Maquettes web, page « Connexion (#25) ».

Au repos

Connexion au repos

Identifiants refusés

Connexion, identifiants refusés

Mobile, 390 px

Connexion mobile 390

Variante — identification déléguée

Variante, identification déléguée


La charte appliquée

Rôle Valeur
Panneau d'identité #0A210F — vert très sombre
Bouton primaire #000000, libellé blanc
Bouton secondaire blanc, bordure et libellé noirs
Liens #016FB9
Erreur #C2141A
États de mesure #14591D sous la cible · #E8710A à surveiller · #C2141A dépassement

Tout est branché sur des variables Figma (33 au total) : changer une valeur change les quatre écrans d'un coup. Le noir du bouton a son propre jeton couleur/bouton-primaire, distinct du bleu des liens.

Sur les critères d'acceptation

Respecter la RGAA — les contrastes sont mesurés, pas estimés. Libellé blanc sur bouton noir 21:1, texte blanc sur panneau 16,97:1, lien bleu sur blanc 5,28:1, message d'erreur 6,16:1, bordure de champ #7E8C99 3,44:1 (la valeur claire d'origine échouait à 1,37:1). L'erreur est signalée par icône et texte, jamais par la couleur seule. Anneau de focus spécifié à 2 px, cibles tactiles à 48 px (52 px sur mobile).

Reste à la charge de l'implémentation : association label/for, aria-describedby vers le message d'erreur, role="alert" sur le bandeau, ordre de tabulation, lang="fr", et le libellé accessible du bouton « Voir ».

Respecter le responsive — l'écran mobile 390 est maquetté. Point de rupture à 840 px : en dessous, le panneau d'identité passe en bandeau horizontal.

Deux points ouverts

Un arbitrage est nécessaire avant d'implémenter. Ce ticket demande un formulaire courriel + mot de passe hébergé par l'application. Le contrat d'API gelé (ADR-006) prévoit l'inverse : l'application délègue l'identification au domaine d'identité du parc et ne détient qu'un cookie de session. Les deux options sont maquettées — la quatrième image est la variante conforme au contrat. Le formulaire demande de modifier le contrat ou de faire transiter le mot de passe par l'API ; la délégation est conforme à ENF-01 mais oblige à réécrire ce ticket et fait partir le lien « mot de passe oublié » chez le fournisseur d'identité.

Il manque l'état de chargement du bouton pendant la vérification. Il ne change ni la mise en page ni les jetons. L'état « vide » est sans objet ici : le défaut est l'état vide.

Maquettes issues du ticket #53. Ce commentaire est la référence de conception, pas la preuve de fermeture : le ticket se ferme quand l'écran est implémenté et testé.

## Maquettes de la page de connexion Les quatre écrans sont validés côté charte graphique et disponibles dans Figma : **[EnerVision — Maquettes web](https://www.figma.com/design/Ys2ioZbXpJfHUolek00iQL)**, page « Connexion (#25) ». ### Au repos ![Connexion au repos](/attachments/b477c522-96fa-49b0-ade6-2c365976b5e1) ### Identifiants refusés ![Connexion, identifiants refusés](/attachments/9081c654-bb39-4d1d-8816-39e61ac77dfc) ### Mobile, 390 px ![Connexion mobile 390](/attachments/1a9b552f-4b4e-4d30-8c52-572622abed6b) ### Variante — identification déléguée ![Variante, identification déléguée](/attachments/4575c72a-392f-41ec-b9e5-698aaf12f58b) --- ### La charte appliquée | Rôle | Valeur | |---|---| | Panneau d'identité | `#0A210F` — vert très sombre | | Bouton primaire | `#000000`, libellé blanc | | Bouton secondaire | blanc, bordure et libellé noirs | | Liens | `#016FB9` | | Erreur | `#C2141A` | | États de mesure | `#14591D` sous la cible · `#E8710A` à surveiller · `#C2141A` dépassement | Tout est branché sur des **variables Figma** (33 au total) : changer une valeur change les quatre écrans d'un coup. Le noir du bouton a son propre jeton `couleur/bouton-primaire`, distinct du bleu des liens. ### Sur les critères d'acceptation **Respecter la RGAA** — les contrastes sont mesurés, pas estimés. Libellé blanc sur bouton noir 21:1, texte blanc sur panneau 16,97:1, lien bleu sur blanc 5,28:1, message d'erreur 6,16:1, bordure de champ `#7E8C99` 3,44:1 (la valeur claire d'origine échouait à 1,37:1). L'erreur est signalée par icône **et** texte, jamais par la couleur seule. Anneau de focus spécifié à 2 px, cibles tactiles à 48 px (52 px sur mobile). Reste à la charge de l'implémentation : association `label`/`for`, `aria-describedby` vers le message d'erreur, `role="alert"` sur le bandeau, ordre de tabulation, `lang="fr"`, et le libellé accessible du bouton « Voir ». **Respecter le responsive** — l'écran mobile 390 est maquetté. Point de rupture à 840 px : en dessous, le panneau d'identité passe en bandeau horizontal. ### Deux points ouverts **Un arbitrage est nécessaire avant d'implémenter.** Ce ticket demande un formulaire courriel + mot de passe hébergé par l'application. Le contrat d'API gelé (ADR-006) prévoit l'inverse : l'application délègue l'identification au domaine d'identité du parc et ne détient qu'un cookie de session. Les deux options sont maquettées — la quatrième image est la variante conforme au contrat. Le formulaire demande de modifier le contrat ou de faire transiter le mot de passe par l'API ; la délégation est conforme à ENF-01 mais oblige à réécrire ce ticket et fait partir le lien « mot de passe oublié » chez le fournisseur d'identité. **Il manque l'état de chargement** du bouton pendant la vérification. Il ne change ni la mise en page ni les jetons. L'état « vide » est sans objet ici : le défaut *est* l'état vide. Maquettes issues du ticket #53. Ce commentaire est la référence de conception, pas la preuve de fermeture : le ticket se ferme quand l'écran est implémenté et testé.
Member

Intégration de la page de connexion — livrée en relecture

Demande de fusion : #75, olivier/25-page-connexiondevelop.

Trois des quatre cadres du fichier Figma sont intégrés : « Connexion — au
repos », « Connexion — identifiants refusés » et « Connexion — mobile 390 ».
Le quatrième, « Variante — identification déléguée », ne l'est pas : voir le
point ouvert en fin de commentaire.

Comment l'essayer

cd services/dashboard
npm ci
npm run dev            # http://localhost:5173/connexion

Aucune API à lancer : six comptes de démonstration la remplacent en
développement. Ils vivent dans src/api/comptes-de-demonstration.json, en JSON
simple, sans aucune dépendance ajoutée. Ajouter ou retirer quelqu'un ne demande
de toucher à aucun code.

Mot de passe commun aux six : mdp-44

Adresse Rôle Sites autorisés
lenaic.g2@enervision.fr administrateur 1, 2, 3, 4, 5, 6, 7
olivier.g2@enervision.fr administrateur 1, 2, 3, 4, 5, 6, 7
marvin.g2@enervision.fr gestionnaire 1, 2, 3, 4
justine.g2@enervision.fr gestionnaire 4, 5, 6, 7
gabriel.g2@enervision.fr lecteur 1, 2
florian.g2@enervision.fr lecteur 6, 7

Les rôles sont ceux de l'énumération du contrat gelé (schemas/commun.py) :
lecteur, gestionnaire, administrateur. Leur répartition est arbitraire,
elle sert à ce que les trois chemins d'autorisation soient démontrables sans
changer de compte de place.

Pour atteindre le cadre « identifiants refusés » : une adresse de la liste
avec n'importe quel autre mot de passe. Le décompte descend à chaque essai
(« Il reste 3 tentatives… »), et au quatrième le compte répond 429 et affiche
le blocage temporaire. Une connexion réussie remet le compteur à zéro.

Ce mot de passe n'ouvre rien

Ni la forge, ni le serveur, ni un environnement déployé : c'est une donnée de
jeu, au même titre que les sept sites qu'elle autorise. Elle n'entre jamais
dans une construction de production.

Ce point mérite d'être dit parce que je me suis fait avoir : la première
version gardait le jeu derrière un if (MOCK_ACTIF) et laissait pourtant le
mot de passe et les six adresses dans le paquet livré. Une garde if ne suffit
pas, il faut que le module ne soit pas importé statiquement. C'est maintenant
un import dynamique sous import.meta.env.DEV, et
tests/unit/paquet-de-production.test.js construit pour de vrai à chaque
exécution et échoue si quoi que ce soit fuit.

Preuve

$ npm run test:unit
 Test Files  5 passed (5)
      Tests  42 passed (42)

$ npm run build
✓ built in 70ms

$ grep -rlE "mdp-44|g2@enervision" dist/
(aucun résultat)

Vérifié dans Chrome cadre par cadre : « au repos » et « identifiants refusés »
en 1440×900, « mobile 390 » en 390×844. Le refus affiche le bandeau, le
décompte, la bordure rouge, le message rattaché au champ, et le focus revient
au mot de passe.

Critères d'acceptation

  • Respecter la RGAA. Libellés rattachés par for et id (le texte de
    substitution vient en plus, jamais à la place), erreurs rattachées par
    aria-describedby, échec annoncé une seule fois dans une zone
    role="alert", focus rendu au champ à corriger, bascule de révélation
    avec aria-pressed, titre de page mis à jour à chaque navigation, cibles
    tactiles à 44 px, anneau de focus jamais supprimé.
    Contrastes : tous conformes AA, relevé complet dans
    services/dashboard/README.md. Attention, le tableau joint à la planche
    « Socle visuel » a été calculé sur les valeurs de la planche et non sur
    les variables réellement appliquées — je l'ai recalculé sur les
    variables.
  • Respecter le responsive. Point de rupture unique à 900 px, comme la
    maquette. Colonne d'identité dans la proportion 620 / 820 du cadre 1440,
    bandeau en tête en dessous.
  • Tests unitaires. 42 cas : champ, dépôt de session, vue, jeu de
    comptes, et le contrôle du paquet de production.
  • L'utilisateur peut se connecter. Vrai contre le jeu de comptes, pas
    contre l'API. Voir ci-dessous.

Le point qui reste ouvert

La maquette dessine un formulaire adresse + mot de passe. Le contrat d'API gelé
dit l'inverse : ADR-006 pose Keycloak et un mandataire OIDC confidentiel, et
aucune des 21 routes de openapi.json n'accepte de mot de passe — « aucun mot
de passe ne transite par EnerVision ». Le cadre Figma « Variante —
identification déléguée » est celui qui correspond au contrat.

Les deux chemins sont écrits dans src/api/authentification.js, c'est le seul
fichier à changer une fois la décision prise. À mon sens c'est la maquette qui
doit céder, pas ADR-006 : le cadre existe déjà, il suffit de le promouvoir.

Je laisse donc ce ticket ouvert : le dernier critère n'est pas tenable tant
que le groupe n'a pas arbitré.

Deux autres écarts relevés au passage, à trancher au #53 :

  1. La planche « Socle visuel » diverge des variables Figma sur six couleurs,
    dont un accent annoncé cuivre (#A8501B) et appliqué bleu (#016FB9).
  2. Le pied de la maquette annonce « Deux rôles : exploitant, administrateur ».
    Le contrat en compte trois, et « exploitant » n'en fait pas partie.
## Intégration de la page de connexion — livrée en relecture Demande de fusion : **#75**, `olivier/25-page-connexion` → `develop`. Trois des quatre cadres du fichier Figma sont intégrés : « Connexion — au repos », « Connexion — identifiants refusés » et « Connexion — mobile 390 ». Le quatrième, « Variante — identification déléguée », ne l'est pas : voir le point ouvert en fin de commentaire. ### Comment l'essayer ```bash cd services/dashboard npm ci npm run dev # http://localhost:5173/connexion ``` Aucune API à lancer : six comptes de démonstration la remplacent en développement. Ils vivent dans `src/api/comptes-de-demonstration.json`, en JSON simple, sans aucune dépendance ajoutée. Ajouter ou retirer quelqu'un ne demande de toucher à aucun code. **Mot de passe commun aux six : `mdp-44`** | Adresse | Rôle | Sites autorisés | |---|---|---| | `lenaic.g2@enervision.fr` | administrateur | 1, 2, 3, 4, 5, 6, 7 | | `olivier.g2@enervision.fr` | administrateur | 1, 2, 3, 4, 5, 6, 7 | | `marvin.g2@enervision.fr` | gestionnaire | 1, 2, 3, 4 | | `justine.g2@enervision.fr` | gestionnaire | 4, 5, 6, 7 | | `gabriel.g2@enervision.fr` | lecteur | 1, 2 | | `florian.g2@enervision.fr` | lecteur | 6, 7 | Les rôles sont ceux de l'énumération du contrat gelé (`schemas/commun.py`) : `lecteur`, `gestionnaire`, `administrateur`. Leur répartition est arbitraire, elle sert à ce que les trois chemins d'autorisation soient démontrables sans changer de compte de place. **Pour atteindre le cadre « identifiants refusés »** : une adresse de la liste avec n'importe quel autre mot de passe. Le décompte descend à chaque essai (« Il reste 3 tentatives… »), et au quatrième le compte répond 429 et affiche le blocage temporaire. Une connexion réussie remet le compteur à zéro. ### Ce mot de passe n'ouvre rien Ni la forge, ni le serveur, ni un environnement déployé : c'est une donnée de jeu, au même titre que les sept sites qu'elle autorise. Elle n'entre **jamais** dans une construction de production. Ce point mérite d'être dit parce que je me suis fait avoir : la première version gardait le jeu derrière un `if (MOCK_ACTIF)` et laissait pourtant le mot de passe et les six adresses dans le paquet livré. Une garde `if` ne suffit pas, il faut que le module ne soit pas importé statiquement. C'est maintenant un import dynamique sous `import.meta.env.DEV`, et `tests/unit/paquet-de-production.test.js` construit pour de vrai à chaque exécution et échoue si quoi que ce soit fuit. ### Preuve ``` $ npm run test:unit Test Files 5 passed (5) Tests 42 passed (42) $ npm run build ✓ built in 70ms $ grep -rlE "mdp-44|g2@enervision" dist/ (aucun résultat) ``` Vérifié dans Chrome cadre par cadre : « au repos » et « identifiants refusés » en 1440×900, « mobile 390 » en 390×844. Le refus affiche le bandeau, le décompte, la bordure rouge, le message rattaché au champ, et le focus revient au mot de passe. ### Critères d'acceptation - [x] **Respecter la RGAA.** Libellés rattachés par `for` et `id` (le texte de substitution vient en plus, jamais à la place), erreurs rattachées par `aria-describedby`, échec annoncé une seule fois dans une zone `role="alert"`, focus rendu au champ à corriger, bascule de révélation avec `aria-pressed`, titre de page mis à jour à chaque navigation, cibles tactiles à 44 px, anneau de focus jamais supprimé. Contrastes : **tous conformes AA**, relevé complet dans `services/dashboard/README.md`. Attention, le tableau joint à la planche « Socle visuel » a été calculé sur les valeurs de la planche et non sur les variables réellement appliquées — je l'ai recalculé sur les variables. - [x] **Respecter le responsive.** Point de rupture unique à 900 px, comme la maquette. Colonne d'identité dans la proportion 620 / 820 du cadre 1440, bandeau en tête en dessous. - [x] **Tests unitaires.** 42 cas : champ, dépôt de session, vue, jeu de comptes, et le contrôle du paquet de production. - [ ] **L'utilisateur peut se connecter.** Vrai contre le jeu de comptes, pas contre l'API. Voir ci-dessous. ### Le point qui reste ouvert La maquette dessine un formulaire adresse + mot de passe. Le contrat d'API gelé dit l'inverse : ADR-006 pose Keycloak et un mandataire OIDC confidentiel, et aucune des 21 routes de `openapi.json` n'accepte de mot de passe — « aucun mot de passe ne transite par EnerVision ». Le cadre Figma « Variante — identification déléguée » est celui qui correspond au contrat. Les deux chemins sont écrits dans `src/api/authentification.js`, c'est le seul fichier à changer une fois la décision prise. À mon sens c'est la maquette qui doit céder, pas ADR-006 : le cadre existe déjà, il suffit de le promouvoir. **Je laisse donc ce ticket ouvert** : le dernier critère n'est pas tenable tant que le groupe n'a pas arbitré. Deux autres écarts relevés au passage, à trancher au **#53** : 1. La planche « Socle visuel » diverge des variables Figma sur six couleurs, dont un accent annoncé cuivre (`#A8501B`) et appliqué bleu (`#016FB9`). 2. Le pied de la maquette annonce « Deux rôles : exploitant, administrateur ». Le contrat en compte trois, et « exploitant » n'en fait pas partie.
marvin self-assigned this 2026-09-03 11:20:20 +00:00
gabriel added the due date 2026-09-09 2026-09-03 12:41:01 +00:00
gabriel added this to the Post-jury milestone 2026-09-03 15:06:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
2026-09-09
Dependencies

No dependencies set

Reference
g2/enervision#25
No description provided.