4 Comparatif Back
Corentin JOGUET edited this page 2026-09-30 15:09:07 +02:00

Comparatif attendu / reel — Back (serveur, donnees, securite applicative)

Constat date. Ce volet decrit la version 11271f7 du 27/09. Depuis, la production sert aab4e96 (29/09) : plusieurs ecarts releves ici sont corriges, et les valeurs « justes » proposees pour le dossier ont bouge. Pour le dossier, reprendre les valeurs a jour (voir Home et la Synthese) : 2610 tests PHP (8924 assertions) et 492 tests JavaScript (recomptage du 30/09, en production depuis la release du 30/09, f841027), 158 routes (57 sous /admin/api), 24 tables, 20 fiches de decision, 18 entrees de journal, 141 fichiers PHP sous src/app dont 33 controleurs (23 au premier niveau, 10 sous Admin/Api, plus 1 trait), 934 mesures d'accessibilite sur 19 ecrans (mesure du 29/09, non rejouee depuis).

Comparaison menee sur le code deploye en production, copie de travail en lecture seule une copie de travail au commit 11271f7 (confirme identique a la production : GET /api/health sur https://corentin-wakdo-admin.stark.a3n.fr repond {"status":"ok","app_env":"production", "version":"11271f7", ...} le 2026-09-27). Comparee au sujet d'examen (docs/_ref/), au referentiel RNCP 37805, a la documentation du projet (docs/), aux pages de wiki deja redigees (versions de travail du 27/09) et au dossier de soutenance (brouillons dossier-soutenance/*.md (brouillons du dossier, hors depot) + export du Google Doc, qui declare decrire le commit 567bb0a du 24/09/2026). Perimetre : serveur PHP, modele de donnees, API, securite applicative — pas le front borne ni l'accessibilite (Bloc 1), hors mandat.

Methode de mesure : lecture directe du code et des migrations, requetes SHOW/SELECT en lecture seule sur la base de production (conteneur wakdo-db), appels HTTP en lecture seule sur la production, et execution de la suite PHPUnit + PHPStan sur une copie jetable de une copie de travail (une copie, supprimee a la fin) via un script local (hors depot) qui joue PHPStan et PHPUnit sur une base MariaDB jetable avec une base MariaDB ephemere, plus node --test tests/js/ execute directement sur une copie de travail (lecture seule confirmee : git status inchange apres coup). Aucune ecriture en production, aucune modification de une copie de travail ni du depot.

Constat d'ensemble, a lire avant le tableau : la documentation Merise du modele de donnees (docs/merise/dictionary.md, docs/merise/mlt.md) est exacte et a jour au 2026-09-27 — verifiee terme a terme contre le schema reel de production. En revanche, tous les documents de preparation a la soutenance (dossier, docs/soutenance/oral-blanc-plan-40min.md, pages de wiki deja redigees) portent des chiffres geles a une date anterieure et n'ont pas suivi les ~26 demandes de fusion livrees entre le 24 et le 27 septembre (dont l'API JSON d'administration PUT/DELETE, la refonte du back-office, le classement des ingredients par famille, la page Sante de l'API et l'annulation de commande par le responsable). Le dossier se decrit lui-meme au commit 567bb0a (24/09) ; docs/soutenance/oral-blanc-plan-40min.md se date lui-meme au commit 1dd2620 (26/09, ligne 9) ; les pages de wiki n'affichent aucune date de reference verifiable. Le tableau ci-dessous classe chaque ecart individuellement, avec la precision « faux des 567bb0a » quand la preuve git le montre, sinon « depasse depuis » sans presumer de l'etat exact a 567bb0a.

Tableau des ecarts

# Sujet Attendu (source) Reel (preuve) Cas Action proposee Gravite
1 Contrat PUT/DELETE de l'API d'administration Dossier : « reste au stade prevu » ; « les methodes PUT/DELETE de l'API d'administration ne sont pas marquees livre » (partie-3-c4bcd.md:86, meme texte dans dossier-court.html:174 et le Google Doc) Livre : 9 routes PUT + 5 DELETE sous /admin/api/* dans src/app/Core/routes.php (recompte exact), documentees comme « livre » des le titre de la section citee elle-meme : docs/api/conventions.md:139 « API d'administration JSON (livre, session + permission + PIN) ». Ajoute par la demande de fusion #151 (dca02b4, 26/09), posterieure a 567bb0a (24/09, verifie par git merge-base --is-ancestor) (a) — doc fausse, code juste Corriger les trois occurrences du dossier ; le document source qu'il cite (conventions.md) est deja exact Haute — c'est le point que le dossier presente lui-meme comme central pour ce critere, et il contredit son propre document source
2 Nombre de tests PHP/JS (dossier) « 755 tests PHP (1962 assertions) et 233 tests JavaScript » — mesure datee du 22/09/2026 (partie-3-c4bcd.md:60, partie-3-c4bcd.md:251, partie-4-devops.md:266, partie-5-methode.md:152, tracabilite.md:94) Mesure reelle sur 11271f7 (execution complete, ce jour) : 2352 tests PHP, 7791 assertions, 0 echec ; 399 tests JavaScript (node --test tests/js/), 0 echec. PHPStan niveau 6, 0 erreur (a) — doc fausse (perimee), code juste et verifie vert Regenerer ce chiffre a partir d'une execution datee, dans le dossier et dans docs/soutenance/oral-blanc-plan-40min.md Haute — sous-estime la base de tests d'un facteur ~3, critere Cr 4.g.2 explicitement note « Couvert » sur ce chiffre perime
3 Nombre de fiches de decision d'architecture (ADR) Dossier : « seize » / « 16 fiches », a quatre endroits (partie-3-c4efg.md:205, partie-3-conception.md:19 : « docs/adr/0001 a 0016 », partie-5-methode.md:23,162, tracabilite.md:71,89) ; docs/soutenance/oral-blanc-plan-40min.md dit 17 (lignes 74, 809, 1352) 20 fiches (0001 a 0020), toutes au statut Accepte, recense a l'identique par le registre du depot lui-meme : docs/adr/README.md. Les ADR 0017-0020 sont posterieurs a 567bb0a (verifie par date de premier commit : 26 et 27/09) (a) pour le dossier (16 etait exact a 567bb0a, verifie par git) ; (a) egalement pour oral-blanc-plan-40min.md (17 est perime depuis le 26/09, commit 1dd2620) Recompter docs/adr/*.md avant publication ; le registre docs/adr/README.md est deja la source fiable a recopier Moyenne — sans consequence fonctionnelle, mais visible et facile a verifier par le jury en un ls
4 Fichiers PHP et repartition des classes Dossier : « 103 fichiers PHP sous src/app » ; « 65 fichiers portent une declaration de classe ou d'interface : 3 abstraites, 34 final, 24 concretes non final, 4 interfaces » (partie-3-c4bcd.md:60, partie-3-c4bcd.md:198) Recompte sur 11271f7 : 133 fichiers PHP sous src/app ; 90 portent une declaration de classe/interface : 3 abstraites (inchange), 46 final, 36 concretes non final, 5 interfaces (a) — doc fausse (perimee), code juste Regenerer le comptage avant l'oral (c'est une question rehearsee, section 7.1 Q1.3 de oral-blanc-plan-40min.md, qui porte elle aussi des chiffres perimes, voir #7) Haute — question de code anticipee et repetee (« Ou est l'heritage dans votre code ? ») avec une reponse chiffree fausse
5 Nombre d'entrees du journal de bord Dossier : « 12 entrees de session versionnees » (partie-3-c4efg.md:205) 14 fichiers sous docs/journal/ (hors README.md), dont deux ajoutes le 27/09 (2026-09-27--familles-ingredients-filtre-recette.md, 2026-09-27--page-sante-api.md) (a) Mettre a jour le chiffre Basse
6 Nombre de commits oral-blanc-plan-40min.md : « 210 commits » (ligne 767) git rev-list --count HEAD sur 11271f7 = 226 (a) — perime depuis le commit 1dd2620 (26/09) cite en tete du document Recompter avant l'oral (git rev-list --count HEAD) Basse
7 Nombre de routes declarees oral-blanc-plan-40min.md : « 155 routes » (Q1.1, ligne 856 ; table de correspondance ligne 763 ; table 6.2 ligne 808bis) grep -c "$router->add(" src/app/Core/routes.php sur 11271f7 = 157 (76 GET, 67 POST, 9 PUT, 5 DELETE). Les 2 routes en plus (GET /admin/health, GET /admin/api/health) viennent de la demande de fusion #175 (26/09), posterieure au commit 1dd2620 cite par ce document (a) — 155 etait exact a 1dd2620, perime depuis Recompter avant l'oral ; App\Health\RouteSecurity::ENTRIES (157 entrees) est deja synchronise et peut servir de source Haute — c'est la toute premiere reponse rehearsee (Q1.1)
8 Repartition des controleurs (heritage) oral-blanc-plan-40min.md, Q1.3 : « 22 fichiers du premier niveau : 2 abstraits, 13 AdminController, 6 Controller, 1 AuthenticatedController » ; correspondance table : « Hierarchie des controleurs a 4 niveaux » sans chiffre propre Recompte sur 11271f7 : 23 fichiers de premier niveau (src/app/Controllers/*.php), 2 abstraits, 14 etendent AdminController (le nouveau est HealthPageController, ajoute par #175 le 27/09, lui-meme non final et heritant d'AdminController), 6 Controller, 1 AuthenticatedController (a) Recompter ; HealthPageController est le seul fichier manquant Haute — meme question rehearsee (Q1.3) que #4, chiffres coherents entre eux mais tous perimes du meme montant (+1 controleur)
9 Migrations et jeux de donnees de reference oral-blanc-plan-40min.md, table 6.2 : « 15 fichiers, 0001 a 0015 » / « 9 jeux de donnees » (deja une correction du dossier, qui disait « dix fichiers, 0001 a 0011 ») Recompte sur 11271f7 : 17 migrations (0001 a 0018, le saut sur 0004 est volontaire et trace dans dictionary.md), 10 jeux de donnees (0001 a 0010). Les fichiers 0015 a 0018 (migrations) et 0009-0010 (seeds) sont tous posterieurs au 26/09 (a) — la correction du 6.2 elle-meme est deja perimee de 2 migrations et 1 seed Recompter db/migrations/*.sql et db/seeds/*.sql avant publication Moyenne — sujet directement lie a Cr 3.b, mais sans risque fonctionnel
10 Nombre d'entites du modele de donnees oral-blanc-plan-40min.md, table 6.2 : « 22 » (deja une correction de « 21 » du dossier, avec la note « pin_throttle n'est classee nulle part ») ; correspondance table : « Dictionnaire, 22 entites » docs/merise/dictionary.md liste 23 entites (3.1 a 3.23, la derniere category_ingredient_family, ajoutee par la migration 0017 le 27/09) — verifie 1:1 par SHOW TABLES en production (23 tables de domaine hors les 3 tables techniques schema_migrations/seed_history/seeds_applied) (a) — la correction « 22 » de oral-blanc-plan-40min.md est elle-meme deja perimee (elle manque l'entite ajoutee juste avant l'ecriture de cette meme ligne) Recompter docs/merise/dictionary.md (deja a jour, 23) et aligner les autres documents dessus Moyenne
11 Nombre de classes *Repository oral-blanc-plan-40min.md, Q1.2 : « 10 classes Repository » Recompte : 11 fichiers *Repository.php sous src/app/ (le nouveau est CategoryIngredientFamilyRepository, ajoute le 27/09 avec la migration 0017) (a) Recompter Basse
12 Nombre de vues (gabarits) oral-blanc-plan-40min.md, Q1.2 : « 38 gabarits » ; wiki Architecture.md : « 38 vues du back-office » Recompte : 41 fichiers sous src/app/Views/ (a) Recompter Moyenne
13 Contraste des mesures d'accessibilite (chiffre back-office cite dans le meme tableau que les autres chiffres back) oral-blanc-plan-40min.md, table 6.2 : « 407 » (deja une correction) rapports/resume.json du 26/09 en donne 415 (source deja citee par le document lui-meme, docs/soutenance/preuves/06-audit-accessibilite-mesure.md) — hors mandat back strict, signale par coherence avec le reste du tableau 6.2 (a) Recompter (hors mandat, a confirmer par l'auditeur Bloc 1) Basse
14 Couverture de la matrice de classification des donnees (RGPD/securite) docs/PROJECT_CONTEXT.md section 19.4 : « Les 21 entites du modele (dictionary.md 3.1-3.21)... Couverture : 21/21 entites classifiees » (ligne 806, ligne 817). Document date « version 1.3 — 2026-06-15 » en pied de page Le modele reel compte 23 entites (voir #10) : pin_throttle (migration 0002, 16/06, donc posterieure a la version 1.3 du 15/06) et category_ingredient_family (migration 0017, 27/09) n'apparaissent dans AUCUN des quatre niveaux de la matrice (a) — doc perimee de longue date (plus de 3 mois), aucune consequence de securite reelle car les deux entites manquantes ne portent pas de donnee personnelle (compteurs de throttle, slug de famille) Ajouter ces deux entites au niveau INTERNAL (coherent avec login_throttle, deja classe INTERNAL) et mettre a jour la conclusion « 23/23 » Moyenne — document cite au titre du critere Cr 3.d (donnees sensibles), l'ecart n'est pas dangereux mais la couverture annoncee (100%) est fausse
15 Conclusion de couverture du MCT docs/merise/mct.md, derniere ligne : « 22/22 entites couvertes... Coherence MCT <-> MCD validee » — document date « v0.3 (2026-09-24) » en tete 23 entites existent desormais (voir #10) ; category_ingredient_family n'a pas d'operation MCT dediee ni de mention dans les notes de bas de tableau (contrairement a allergen/permission, explicitement notees "lecture seule au niveau MCT") (d) — probablement un choix voulu (filtre de categorie, pas une operation metier autonome, gerable via MANAGE_INGREDIENT/MANAGE_CATEGORY) mais non trace comme tel Ajouter une note explicite (comme pour allergen) plutot que de laisser la conclusion numerique fausse Basse
16 Wiki Modele-de-donnees.md : entites, migrations, jeux de donnees « 22 entites... quatre sous-domaines » (ligne 3) ; « 15 migrations » (ligne 18) ; « 9 jeux de donnees » (ligne 22) Recompte identique a #9/#10 : 23 entites, 17 migrations, 10 jeux de donnees (a) Corriger avant publication au wiki Forgejo Haute — cette page sera publiee telle quelle
17 Wiki Architecture.md : controleurs, vues, routes « 32 controleurs » (ligne 31) ; « 38 vues » (ligne 33) ; « 155 routes declarees a la suite » (ligne 35) Recompte : 31 controleurs concrets (21 de premier niveau + 10 sous Admin/Api, hors 2 classes abstraites et 1 trait JsonApiTrait) ; 41 vues (#12) ; 157 routes (#7) (a) Corriger avant publication Haute — meme raison que #16
18 Wiki Decisions.md : liste des fiches ADR « Dix-sept fiches » listant 0001 a 0017 (lignes 3, 11-27) 20 fiches existent (docs/adr/README.md, deja a jour) : manquent 0018 (familles d'ingredients), 0019 (page Sante de l'API), 0020 (le responsable peut annuler une commande) (a) Ajouter les trois lignes manquantes, en recopiant docs/adr/README.md qui est deja exact Haute — la fiche manquante 0020 documente justement une fonctionnalite tres recente et visible (annulation par le responsable), dont l'absence saute aux yeux d'un lecteur qui la connait

Conforme

Ce qui a ete verifie directement (code, base de production en lecture seule, ou execution de test) et qui tient :

  • Version deployee : GET /api/health en production renvoie version: "11271f7", app_env: "production", status: "ok" — identique a la copie de travail auditee. Preuve : appel curl du 2026-09-27.
  • Carte des routes vs garde de securite : App\Health\RouteSecurity::ENTRIES (157 entrees) correspond exactement, une a une, aux 157 routes de src/app/Core/routes.php (meme nombre recompte independamment des deux cotes). C'est precisement ce que revendique l'ADR-0019 (« une carte des routes qui ne peut pas diverger du code »).
  • Matrice RBAC (docs/demo/matrice-rbac.md) : les totaux par role annonces (admin 23, manager 15, kitchen 5, counter 8, drive 8) et le detail case par case correspondent exactement aux INSERT INTO role_permission de db/seeds/0001_rbac_and_reference.sql, y compris la ligne order.cancel du role manager, ajoutee par l'ADR-0020 et le seed en meme temps.
  • Comptes de demonstration (docs/demo/comptes-demo.md) : les 6 comptes decrits (admin, manager, cuisine, comptoir, comptoir2, drive) correspondent exactement aux INSERT INTO user de db/seeds/0009_demo_accounts.sql.
  • Dictionnaire de donnees vs schema reel : les 23 entites de docs/merise/dictionary.md (3.1 a 3.23) correspondent nom pour nom, sans manque ni surplus, aux 23 tables de domaine trouvees par SHOW TABLES sur la base de production (hors les 3 tables techniques schema_migrations/seed_history/seeds_applied, qui ne sont pas des entites metier). Verifie egalement en detail sur l'entite la plus recente : category_ingredient_family (cle primaire composite, contrainte ON DELETE CASCADE) correspond exactement au SHOW CREATE TABLE reel.
  • Regles transverses de securite : docs/merise/mlt.md liste RG-T01 a RG-T22, soit 22 regles — a jour, coherent avec le code (pin_throttle = RG-T22).
  • Analyse statique : phpstan.phar analyse (niveau 6, phpstan.neon ligne 5) sur 11271f7 : 0 erreur.
  • Suite de tests : PHPUnit sur base MariaDB ephemere : 2352 tests, 7791 assertions, 0 echec ; suite JS (node --test tests/js/) : 399 tests, 0 echec.
  • Hachage des mots de passe et des PIN : PASSWORD_ARGON2ID partout (src/app/Auth/PasswordHasher.php, PinVerifier), aucune occurrence de bcrypt ou de PASSWORD_DEFAULT dans le code.
  • Anonymisation RGPD : UserRepository::anonymise() vide la PII (email, nom, hachages) en conservant la ligne (integrite des FK entrantes stock_movement/customer_order/ audit_log), idempotent (anonymized_at IS NULL) — conforme a l'ADR-0007.
  • Limitation des tentatives : deux mecanismes bien separes verifies dans le code — login_throttle (par IP) et user.failed_login_attempts/lockout_until (par compte), plus pin_throttle (par utilisateur agissant, db/migrations/0002_pin_throttle.sql), conforme a l'ADR-0005. Contre-audit du 30/09 (revue adversariale) : la re-verification du mot de passe sur /admin/profile/pin compte desormais sur le MEME budget que le compte (elle comptait auparavant, a tort, sur pin_throttle, contournable par une action PIN reussie d'un tiers) ; une connexion reussie ne remet plus a zero le compteur IP.
  • En-tetes de securite en production (mesure curl en lecture seule) : HSTS (max-age=31536000; includeSubDomains; preload), X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, cookie de session Secure; HttpOnly; SameSite=Strict. La politique CSP du back-office autorise style-src 'unsafe-inline' alors que celle de la borne l'interdit et ajoute base-uri/form-action/frame-ancestors/object-src — exactement la limite que le dossier annonce lui-meme (« CSP du back-office moins stricte que celle de la borne, a cause du rendu serveur des vues »).
  • Enveloppe d'erreur JSON en production : GET /admin/api/route-inexistante renvoie {"data":null,"error":{"code":"NOT_FOUND","message":"Resource not found"}} ; une route protegee sans session renvoie {"data":null,"error":{"code":"AUTH_REQUIRED",...}} en 401 — conforme a l'enveloppe decrite par docs/api/conventions.md section 7, aucune fuite de trace PHP observee (contrairement a l'ancienne inquietude notee dans le dossier, deja corrigee par la demande de fusion #168 avant 567bb0a).
  • Registre des ADR du depot (docs/adr/README.md) : 20 fiches, toutes « Accepte », a jour — c'est la seule liste d'ADR qui est exacte parmi tous les documents audites.
  • Contrat PUT/DELETE documente : docs/api/conventions.md section 5.3 decrit le contrat complet (permission, PIN, CSRF par en-tete, codes d'erreur) et il correspond exactement au code (RouteSecurity, routes.php), y compris le detail fin comme le DELETE sur /admin/api/categories/{id} qui bascule is_active=0 au lieu d'une suppression dure (FK RESTRICT).

A verifier

Hypotheses non prouvees, ou preuve introuvable d'un cote — a ne pas traiter comme des faits :

  • « bcrypt ou argon2 » dans le dossier, sections 7/16/18 : cette affirmation figure dans la table 6.2 de oral-blanc-plan-40min.md (ligne 818) comme un ecart a corriger, mais une recherche du mot « bcrypt » dans tous les fichiers dossier-soutenance/*.md et dans le texte exporte du Google Doc ne renvoie aucune occurrence : le dossier dit deja « argon2id » partout ou le sujet est aborde (ex. partie-1.md:218). Soit la table 6.2 decrit une version du dossier deja corrigee depuis, soit elle vise un fichier hors de mon perimetre de lecture. Non confirme, a ne pas reprendre tel quel.
  • « 158 demandes de fusion » (oral-blanc-plan-40min.md, ligne 767) : je n'ai pas d'acces a l'API du forge pour recompter les pull requests fusionnees ; seul le nombre de commits a ete recompte (226, contre 210 annonces — voir #6), ce qui suggere que ce chiffre est probablement lui aussi perime, sans le confirmer precisement.
  • Etat exact du code a 567bb0a pour les sujets #4, #7 (repartition fine), #10, #11, #12 : je n'ai verifie l'anteriorite/posteriorite par rapport a 567bb0a que pour les items ou une preuve git directe etait rapide a obtenir (#1, #3, #7, #9). Pour les autres, le rapport compare seulement au commit deploye 11271f7 ; dire si le chiffre du dossier etait deja faux ou seulement depasse a 567bb0a demanderait de checkouter ce commit specifiquement (non fait, en dehors du temps imparti).
  • Nombre exact d'ecrans couverts par l'audit d'accessibilite back-office et validite du chiffre de 415 mesures de contraste (item #13) : ressort du Bloc 1 / front, hors mon mandat ; signale seulement par coherence avec le reste du tableau 6.2, non audite en detail cote preuves d'accessibilite.
  • Docker/CI (« 4 travaux », « deploiement en deux etapes », « 5 services ») : non recompte en detail (hors coeur du mandat serveur/donnees/securite), a verifier separement si un volet DevOps est mene.

Pour le dossier

Passages a corriger dans les brouillons (dossier-soutenance/*.md) et le Google Doc, avec le texte actuel, le texte juste, et le statut precis vis-a-vis de 567bb0a :

  1. partie-3-c4bcd.md:86 (et dossier-court.html:174, meme phrase dans le Google Doc) : actuel — « Une partie du contrat d'API decrit dans docs/api/conventions.md (section 5.3) reste au stade prevu : les methodes PUT/DELETE de l'API d'administration ne sont pas marquees livre. » juste — « Le contrat PUT/DELETE de l'API d'administration est livre depuis la demande de fusion #151 : 9 routes PUT, 5 routes DELETE sous /admin/api/*, documentees et testees. » Depasse depuis 567bb0a (la fonctionnalite a ete ajoutee par la demande de fusion #151, posterieure de deux jours).

  2. partie-3-c4bcd.md:60 et :198 : actuel — « 103 fichiers PHP sous src/app/... 65 fichiers portent une declaration de classe... 3 abstraites, 34 final, 24 concretes non final, 4 interfaces. » juste — « 133 fichiers PHP sous src/app/... 90 fichiers portent une declaration de classe... 3 abstraites, 46 final, 36 concretes non final, 5 interfaces. » Depasse depuis 567bb0a (statut exact a 567bb0a non verifie, voir section « A verifier »).

  3. partie-3-c4bcd.md:251, partie-4-devops.md:266, partie-5-methode.md:152, tracabilite.md:94 : actuel — « 755 tests PHP (1962 assertions) et 233 tests JavaScript. » juste — « 2352 tests PHP (7791 assertions) et 399 tests JavaScript, mesures le [date de re-execution]. » Depasse depuis 567bb0a (statut exact a 567bb0a non verifie).

  4. partie-3-c4efg.md:205, partie-3-conception.md:19, partie-5-methode.md:23,162, tracabilite.md:71,89 : actuel — « seize fiches » / « docs/adr/0001 a 0016. » juste — « vingt fiches, docs/adr/0001 a 0020. » Faux pour 567bb0a : non, exact a 567bb0a (les ADR 0001-0016 existaient bien a cette date, verifie par date de premier commit) ; depasse depuis par les ADR 0017 a 0020 (26 et 27/09).

  5. partie-3-c4efg.md:205 : actuel — « Le dossier docs/journal/ rassemble 12 entrees. » juste — « 14 entrees. » Depasse depuis 567bb0a.

  6. Coherence interne du dossier avec docs/soutenance/oral-blanc-plan-40min.md : ce dernier document donne deja un chiffre different pour les ADR (17, lignes 74/809/1352) — ce chiffre est lui-meme perime (voir tableau, item 3). Les deux documents doivent etre corriges vers le meme chiffre exact (20), pas l'un vers l'autre.

Precision demandee par la methode sur le point deja connu (contrat PUT/DELETE) : la version 567bb0a du 24/09, que le dossier declare decrire, ne portait effectivement pas encore l'API JSON d'administration en ecriture — a cette date le passage etait donc exact. Le code deploye et juge par le jury (11271f7, via la production) l'a depuis largement depassee. Le dossier doit etre reecrit pour decrire l'etat livre, pas seulement note comme « en retard ».