diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b9e1ac..4e59012 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,50 @@
# CHANGELOG — Set-OPS
+## 2026-09-08 — La forme des registres cesse d'etre recopiee : elle est derivee
+
+**61 preuves (P01-P61, dont une conditionnelle). `make prouver` : CONFORME, 60 OK, 0 echec,
+1 saute.**
+
+### Le probleme
+
+La forme du plan etait ecrite TROIS FOIS : dans les constantes du moteur (`ETATS_SERVEUR`,
+`PORTEES_BD`, `AUTORITES_DNS`), dans les formulaires du GUI, et dans la documentation. Rien
+ne les tenait ensemble. Ajouter une portee de base de donnees demandait trois gestes, et le
+troisieme s'oubliait sans qu'aucun controle ne s'en apercoive.
+
+### Ce qui change
+
+`scripts/schema_plan.py` (nouveau) derive un JSON Schema des SIX registres du plan
+— `serveurs`, `applications`, `bases_donnees`, `serveurs_bd`, `domaines_publics`,
+`nomenclature` — en IMPORTANT les enumerations du moteur plutot qu'en les recopiant. Le
+resultat est versionne dans `docs/audit/schema-plan.json` : 42 champs, regenerable par
+`make schema`. Il est versionne, et non recalcule a chaud, pour qu'une divergence se voie
+dans un diff.
+
+Le schema porte ce que JSON Schema seul ne dit pas : `x-source-valeurs` (liste fermee
+alimentee a l'execution depuis l'inventaire), `x-source-selon` (liste dependant d'un autre
+champ), `x-clef` (l'attribut qui identifie l'entite), `x-requis`.
+
+**Le formulaire des bases de donnees du GUI n'est plus ecrit a la main.** Il est construit
+au chargement depuis le schema servi par `/api/inventaire`. Le chemin de SAUVEGARDE aussi
+derive du schema : les champs ecrits sont ceux que le schema declare, avec ses valeurs par
+defaut — plus une liste de champs recopiee dans le JS.
+
+`P61` garde l'ensemble : le schema doit couvrir tout ce que les plans REELS contiennent.
+Son controle negatif : retirer un champ du schema le fait echouer.
+
+### La limite, dite franchement
+
+**UN registre sur six est genere.** Les cinq autres formulaires restent ecrits a la main.
+
+Et le trou connu reste ouvert : `couverture_gui.py verifier` echoue toujours sur
+`nomenclature.categorie` et `nomenclature.service` — deux champs presents dans les plans
+reels que le GUI ne sait pas ecrire. Le schema les DECRIT deja ; c'est le passage de la vue
+nomenclature au generateur qui fermera le trou, par construction.
+
+Enfin : le formulaire genere a ete eprouve en rendant son HTML avec la vraie reponse de
+l'API, pas dans un navigateur.
+
## 2026-09-06 — Tournee des 74 documents : ce que le depot disait de lui-meme avait vieilli
**57 preuves (P01-P57, dont une conditionnelle). `make prouver` : CONFORME, 56 OK, 0 echec,
diff --git a/scripts/inventory_gui.py b/scripts/inventory_gui.py
index 795b9bc..1e83946 100644
--- a/scripts/inventory_gui.py
+++ b/scripts/inventory_gui.py
@@ -2037,7 +2037,10 @@ HTML = r"""
function champDepuisSchema(cle, spec, valeur, entite, surChangement) {
const titre = echapper(spec.title || cle);
const aide = spec.description ? ` title="${echapper(spec.description)}"` : '';
- const req = (spec['x-requis'] ? ' requis' : '');
+ // Marqueur discret : le schema SAIT ce qui est requis, le formulaire ecrit a la
+ // main ne le montrait pas. Une asterisque plutot que le mot « requis », qui se
+ // collait au libelle et se lisait « Base requis ».
+ const req = (spec['x-requis'] ? ' *' : '');
const appel = (expr) => `${surChangement}('${cle}', ${expr})`;
// Liste fermee : soit fixe (enum), soit alimentee a l'execution, soit dependante