From 372c1befc1428b0987463403cc9531bbc140c8fb Mon Sep 17 00:00:00 2001 From: decarvalhoe Date: Thu, 2 Jul 2026 16:23:25 +0200 Subject: [PATCH] =?UTF-8?q?release:=201.4.0=20=E2=80=94=20sanification=20&?= =?UTF-8?q?=20standards=20web=20(EPIC=2010)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Garde i18n, a11y outillée (axe-core), CSP stricte, styles inline → classes, lint étendu à tout src/. CHANGELOG + badges README (FR/EN) à jour. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ README.en.md | 7 ++++--- README.md | 7 ++++--- package.json | 2 +- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb64e9..d198f1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,30 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) · versioning : [SemVer](https://semver.org/lang/fr/). Démo : . +## [1.4.0] — 2026-07-02 + +Sanification & meilleurs standards du web (EPIC 10) : le code de la couche UI/jeu rejoint la +barre de qualité du moteur. + +### Ajouté +- **Garde i18n** (E10-1) : un test échoue si une chaîne visible par le joueur est en dur — + soit non enregistrée dans le pack EN, soit une clé `t()` orpheline. A révélé et corrigé des + fuites invisibles à l'audit précédent (carte EN « tu es ici / verrouillé », `title`/ + `aria-label` du réordonnancement). Nouvel écran visuel **carte EN**. +- **A11y WCAG 2.2 AA outillée** (E10-4) : **axe-core** exécuté en CI sur 3 vues (0 violation) ; + focus visible sur tous les interactifs ; lien d'évitement bilingue ; hiérarchie de titres + `h1→h2→h3` réelle ; `prefers-contrast`. Contraste du label d'adresse corrigé. Voir + [`docs/A11Y.md`](docs/A11Y.md). +- **CSP stricte** (E10-5) sans `'unsafe-inline'`, vérifiée en CI (écoute + `securitypolicyviolation`) ; en-têtes serveur recommandés. Voir + [`docs/SECURITY.md`](docs/SECURITY.md). + +### Modifié +- **Styles inline → classes** (E10-2) : plus aucun `style=""` statique dans les vues (nouveau + `styles/views.css`) ; états dynamiques via classes modificatrices. Rendu pixel-identique. +- **Lint étendu à tout `src/` et `tests/`** (E10-3) — cause racine des fuites — avec refactors + sous 50 lignes/fonction et `eqeqeq` (idiome `== null` préservé). + ## [1.3.1] — 2026-07-02 Finition bilingue et durcissement du process. diff --git a/README.en.md b/README.en.md index e75fea8..3daa9dd 100644 --- a/README.en.md +++ b/README.en.md @@ -8,7 +8,7 @@ [![CI](https://github.com/decarvalhoe/MemoForge/actions/workflows/ci.yml/badge.svg)](https://github.com/decarvalhoe/MemoForge/actions/workflows/ci.yml) [![Deploy](https://github.com/decarvalhoe/MemoForge/actions/workflows/deploy.yml/badge.svg)](https://github.com/decarvalhoe/MemoForge/actions/workflows/deploy.yml) -![Version](https://img.shields.io/badge/version-1.3.1-46E08A) +![Version](https://img.shields.io/badge/version-1.4.0-46E08A) ![Engine coverage](https://img.shields.io/badge/engine_coverage-100%25-46E08A) ![Runtime dependencies](https://img.shields.io/badge/runtime_dependencies-0-46E08A) @@ -105,9 +105,10 @@ Every PR passes four gates in CI: | Gate | Content | |---|---| -| **Tests** | 621 `node:test` tests — engine, levels (each lure verified as *teaching*), world, medals, pitfalls, a11y · **engine coverage ≥ 90 % required (100 % effective)** | +| **Tests** | 655 `node:test` tests — engine, levels (each lure verified as *teaching*), world, medals, pitfalls, a11y, i18n guard · **engine coverage ≥ 90 % required (100 % effective)** | | **Non-regression** | data-driven sweep: every level must stay solvable via its canonical path | -| **Key screens** | Puppeteer harness: 8 screens captured (incl. mobile and EN), structural invariants + pixel diff ([`docs/TESTING.md`](docs/TESTING.md)) | +| **Key screens** | Puppeteer harness: 9 screens captured (incl. mobile, EN, EN map), structural invariants + pixel diff ([`docs/TESTING.md`](docs/TESTING.md)) | +| **A11y & security** | axe-core (WCAG 2.x AA, 0 violations) + strict-CSP guard, both enforced in CI ([`docs/A11Y.md`](docs/A11Y.md), [`docs/SECURITY.md`](docs/SECURITY.md)) | | **Perf budgets** | weight ≤ 280 KB, render ≤ 16 ms — measured and enforced ([`docs/PERF.md`](docs/PERF.md)) | The production artifact (`npm run build` → `dist/`) is re-verified by the same harness before diff --git a/README.md b/README.md index b8fb8be..84d43d0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![CI](https://github.com/decarvalhoe/MemoForge/actions/workflows/ci.yml/badge.svg)](https://github.com/decarvalhoe/MemoForge/actions/workflows/ci.yml) [![Deploy](https://github.com/decarvalhoe/MemoForge/actions/workflows/deploy.yml/badge.svg)](https://github.com/decarvalhoe/MemoForge/actions/workflows/deploy.yml) -![Version](https://img.shields.io/badge/version-1.3.1-46E08A) +![Version](https://img.shields.io/badge/version-1.4.0-46E08A) ![Couverture moteur](https://img.shields.io/badge/couverture_moteur-100%25-46E08A) ![Dépendances runtime](https://img.shields.io/badge/d%C3%A9pendances_runtime-0-46E08A) @@ -106,9 +106,10 @@ Chaque PR passe quatre barrières en CI : | Barrière | Contenu | |---|---| -| **Tests** | 621 tests `node:test` — moteur, niveaux (chaque appât vérifié comme *enseignant*), monde, médailles, pièges, a11y · **couverture moteur ≥ 90 % exigée (100 % effective)** | +| **Tests** | 655 tests `node:test` — moteur, niveaux (chaque appât vérifié comme *enseignant*), monde, médailles, pièges, a11y, garde i18n · **couverture moteur ≥ 90 % exigée (100 % effective)** | | **Non-régression** | balayage data-driven : chaque niveau doit rester résoluble par son chemin canonique | -| **Écrans clés** | harnais Puppeteer : 8 écrans capturés (dont mobile et EN), invariants structurels + comparaison pixel ([`docs/TESTING.md`](docs/TESTING.md)) | +| **Écrans clés** | harnais Puppeteer : 9 écrans capturés (dont mobile, EN, carte EN), invariants structurels + comparaison pixel ([`docs/TESTING.md`](docs/TESTING.md)) | +| **A11y & sécurité** | axe-core (WCAG 2.x AA, 0 violation) + garde CSP stricte, vérifiés en CI ([`docs/A11Y.md`](docs/A11Y.md), [`docs/SECURITY.md`](docs/SECURITY.md)) | | **Budgets perf** | poids ≤ 280 KB, rendu ≤ 16 ms — mesurés et appliqués ([`docs/PERF.md`](docs/PERF.md)) | L'artefact de prod (`npm run build` → `dist/`) est revérifié par le même harnais avant diff --git a/package.json b/package.json index e09ce5c..d28b260 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "memoforge", - "version": "1.3.1", + "version": "1.4.0", "private": true, "type": "module", "description": "Jeu de puzzle pour comprendre les pointeurs et la mémoire C",