Architecture de l'administration web¶
L'administration web reste une application statique sans framework ni bundler. nginx assemble le
document HTML avec SSI, sert les modules ES natifs et relaie les appels relatifs /api/... vers
FastAPI. Le navigateur ne contient ni clé interne ni autorité d'autorisation : les permissions
client pilotent la visibilité, tandis que l'API revalide chaque action.
Organisation¶
public/index.htmlcontient uniquement le head, la connexion et le shell applicatif.public/partials/shell/contient topbar, navigation et modale partagée.public/partials/{community,world-edit,administration}/contient un fragment par panneau.public/js/core/possède session, client HTTP/CSRF, modale, navigation, registre de features et registre d'actions transverses.public/js/features/contient une factory par ensemble fonctionnel etfeatures/index.jscompose explicitement l'application.public/app.jsne fait que composer les services, établir la session, monter les features, configurer la navigation, précharger les panneaux autorisés et gérer la déconnexion.
Chaque factory reçoit un contexte partagé immuable et retourne le contrat suivant :
{ id: 'identifiant-unique', panels: ['example-panel'], mount() {}, load(panelId) {}, shouldPreload() {} }
L'état mutable appartient à la closure de la feature. Une feature n'importe jamais une autre
feature. Un parcours transverse s'enregistre dans core/actions.js, par exemple l'ouverture de
l'inventaire depuis la fiche Personnage.
Ajouter une page¶
- Ajouter un partial sans
<script>,<style>ni élément racine global, puis l'inclure dansindex.html. - Ajouter le bouton
tab-buttonet sondata-panel, avec sa permission. - Créer la factory, garder ses caches/timers privés et l'enregistrer dans
features/index.js. - Réutiliser le core et
openAdminModal; ne jamais utiliseralert,confirmouprompt. - Mettre à jour la recette et exécuter les contrôles structurels.
Contrat des champs de modale¶
openAdminModal choisit le contrôle avant d'appliquer ses attributs : un champ avec options
produit un <select>, multiline produit un <textarea>, et les autres champs produisent un
<input> dont le type vaut text par défaut. La propriété type ne doit jamais être affectée à
un select ou à un textarea. Les contraintes communes (required, min, max, minlength,
maxlength, pattern) restent portées par la description du champ. Le premier input, textarea ou
select reçoit le focus à l'ouverture.
Le test admin/tests/modal-contracts.mjs protège ce choix sans navigateur. Le contrat HTML vérifie
également que le fragment SSI contient une paire <dialog>...</dialog> équilibrée.
Assemblage et contrôles¶
SSI est activé uniquement pour /index.html. /partials/ est internal; le navigateur reçoit un
DOM complet sans flash de template incomplet. Les imports ES restent same-origin et compatibles
avec la CSP existante.
node admin/tests/module-graph.mjs
node admin/tests/html-contracts.mjs
node admin/tests/modal-contracts.mjs
Le premier valide imports, cycles, factories, IDs et ownership des panneaux. Le second résout les includes SSI, contrôle l'unicité des IDs, les cibles de navigation, la fermeture du dialog et le markup interdit. Le troisième protège la sélection du bon élément pour chaque description de champ de modale.