• v2.4.1 d8219acaab

    nicolas released this 2026-11-07 21:01:25 +01:00 | 93 commits to master since this release

    🔏 Launcher 2.4.1 — Avertissement avant une publication signée

    Petite version du menu d'administration : avant de publier le catalogue ou une version, le launcher vérifie que la clé de votre PC est bien reconnue par les launchers des joueurs. Si ce n'est pas le cas, il vous prévient avant d'envoyer quoi que ce soit.

    Rien ne change dans le fonctionnement : le serveur accepte toujours ces publications, et les launchers des joueurs les traitent exactement comme avant. Il s'agit uniquement d'un avertissement. Pas de serveur à redéployer.

    ✨ En bref

    Changement
    🆕 Nouveau Avertissement « Clé non reconnue par les launchers des joueurs » avant de publier le catalogue (page « Jeux »)
    🆕 Nouveau Même avertissement avant de publier une version et avant « Signer la version en ligne » (page « Publier une version »)
    💡 Amélioré Le message explique la conséquence pour les joueurs et la marche à suivre (page « Signature »)
    🖧 Serveur Aucun changement, rien à redéployer
    🧪 Qualité 5 nouveaux tests automatisés (281 au total)

    🤔 Pourquoi cet avertissement ?

    Le serveur vérifie qu'un contenu est signé par la clé de la session (signature valide, date correcte). Il ne vérifie pas que cette clé figure dans le trousseau publié (keyring.json), celui que téléchargent les launchers des joueurs.

    Exemple : un administrateur vient d'enregistrer un nouveau PC, que le propriétaire n'a pas encore ajouté au trousseau. Il modifie le catalogue et clique sur « Publier » :

    • le serveur accepte et publie le catalogue ;
    • la page « Jeux » affiche bien la nouvelle valeur ;
    • mais les launchers des joueurs (vérification des signatures obligatoire) ignorent ce catalogue et gardent l'ancien.

    Jusqu'ici, rien ne le signalait. Désormais, le launcher prévient avant la publication.


    🔔 Quand l'avertissement s'affiche

    Juste avant la signature, le launcher télécharge le trousseau publié et le vérifie comme le font les launchers des joueurs. L'avertissement apparaît si :

    Situation Exemple de message
    La clé du PC est absente du trousseau « La clé de ce PC (…) n'est pas dans le trousseau publié (n° 4). »
    La clé est présente, mais sans l'autorisation voulue « … est dans le trousseau publié, mais sans l'autorisation « versions du jeu ». »
    Le trousseau est refusé (autre clé racine, trop ancien, illisible) « Le trousseau publié (…) est refusé par ce launcher : … »
    Le trousseau est injoignable « Le trousseau publié (…) est injoignable : impossible de vérifier que la clé de ce PC y figure. »
    Aucun trousseau n'est configuré (keyringUrl) « Aucun trousseau n'est configuré dans ce launcher… »

    Le message indique ensuite ce qui se passera chez les joueurs, selon le réglage contentSigning du launcher :

    contentSigning Catalogue Version d'un jeu
    require Ignoré : les joueurs gardent le catalogue précédent (celui intégré au launcher pour une installation neuve) Refusée : ni installation ni mise à jour (le jeu déjà installé reste jouable)
    warn Accepté, avec une alerte de signature dans le journal Acceptée, avec une alerte de signature dans le journal
    off Aucun contrôle, aucun avertissement Aucun contrôle, aucun avertissement

    Deux choix : « Annuler » (rien n'est signé ni envoyé) ou « Publier quand même » (« Signer quand même » pour une version déjà en ligne). La publication se déroule alors exactement comme avant.

    💡 Pour régler le problème : un propriétaire ajoute la clé du PC au trousseau (page « Signature »), le fait signer avec la clé racine puis le publie. Les launchers des joueurs acceptent alors le contenu sans nouvelle publication.


    🛡️ Sécurité

    • Aucun changement côté serveur ni côté joueur : l'avertissement est un contrôle du menu d'administration, rien de plus.
    • Le trousseau est vérifié comme chez les joueurs : structure, clé racine intégrée à l'exe, numéro minimal (keyringMinSequence).
    • L'adresse du trousseau et le mode de vérification viennent du launcher.json intégré à l'exe (en Release), comme pour les joueurs.
    • L'identifiant de la clé est calculé sur le PC, à partir de la clé qui signe réellement.
    • Téléchargement en https, sans cache (une clé ajoutée par un propriétaire est vue tout de suite), taille limitée, 15 secondes au plus.
    • Une erreur imprévue du contrôle ne bloque pas la publication ; chaque avertissement est inscrit dans le journal du launcher.

    🧪 Tests

    Fichier Tests
    Admin/PlayerSigningCheckTests.cs (nouveau) 5 : clé présente, absente ou sans autorisation ; trousseau relu à chaque contrôle ; trousseau refusé, trop ancien, illisible ou injoignable ; modes warn et off ; pages « Jeux » et « Publier une version » (annulation, « Publier quand même », publication acceptée par le serveur)

    281 tests au vert.

    📂 Fichiers modifiés

    Menu d'administration

    • src/GameLauncher.Modules/Admin/PlayerSigningCheck.cs (nouveau)
    • src/GameLauncher.Modules/Admin/AdminPanelViewModel.cs
    • src/GameLauncher.Modules/Admin/IAdminContext.cs
    • src/GameLauncher.Modules.Admin/ViewModels/AdminEnvironment.cs
    • src/GameLauncher.Modules.Admin/ViewModels/AdminWorkspaceViewModel.cs
    • src/GameLauncher.Modules.Admin/Catalog/GamesPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Publishing/PublishPanelViewModel.cs

    Launcher (WPF)

    • src/GameLauncher/App.xaml.cs
    • src/GameLauncher/Services/AdminWindowService.cs
    • src/GameLauncher/GameLauncher.csproj (version 2.4.1)

    Tests

    • tests/GameLauncher.Tests/Admin/PlayerSigningCheckTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/AdminTestKit.cs

    Documentation et notes

    • docs/ADMIN-ARCHITECTURE.md
    • tools/notes-launcher.txt

    ⬆️ Mise à niveau

    • Joueurs : mise à jour automatique depuis la 2.4.0, aucune action requise.
    • Serveur (Launcher API) : aucun changement, rien à redéployer.
    • Administrateurs : rien à faire. Si l'avertissement s'affiche, demandez à un propriétaire d'ajouter la clé de votre PC au trousseau (page « Signature »).

    🔏 La sécurité des mises à jour du launcher ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    Contributors

    Full Changelog: v2.4.0...v2.4.1

    Downloads
  • v2.4.0 c281ca1781

    nicolas released this 2026-11-07 19:20:01 +01:00 | 100 commits to master since this release

    🚀 Launcher 2.4.0 — Groupes, permissions et images des jeux

    Version consacrée au menu d'administration : les rôles fixes deviennent des groupes modifiables avec leurs permissions, l'icône et l'image de fond d'un jeu s'envoient directement depuis le launcher (plus besoin de client FTP), et les pages en deux colonnes défilent séparément.

    Côté joueurs, rien ne change visiblement : le jeu, les mises à jour et le launcher fonctionnent comme avant. Les images du catalogue envoyées depuis le menu sont désormais vérifiées au téléchargement.

    ✨ En bref

    Changement
    🆕 Nouveau Page « Groupes et permissions » : créer, modifier et supprimer des groupes d'administrateurs, choisir leurs permissions
    🆕 Nouveau Permissions personnalisées (module.action), en prévision de modules futurs
    🆕 Nouveau Page « Jeux » : bouton « Parcourir… » pour l'icône et l'image de fond, avec aperçu, sans client FTP
    🛡️ Sécurité Images envoyées depuis le menu : nommées par leur empreinte SHA-256 et vérifiées par les launchers des joueurs
    💡 Amélioré « Jeux », « Notes de version », « Groupes et permissions » : la liste et la fiche défilent séparément
    🐛 Corrigé « Fichiers du serveur » : l'ascenseur ne remonte plus à chaque changement de dossier
    🔄 Modifié « Administrateurs » : « rôle » devient « groupe » ; seuls les groupes attribuables sont proposés
    🖧 Serveur Module Groups, route d'envoi d'images, admins.json au format 2 : à redéployer (voir Mise à niveau)
    🧪 Qualité 21 nouveaux tests automatisés (276 au total)

    👥 Groupes et permissions

    Les rôles Propriétaire, Administrateur et Éditeur deviennent des groupes. Au premier démarrage, le serveur les crée avec les mêmes droits qu'avant : rien ne change pour les comptes existants.

    La nouvelle page « Groupes et permissions » (permission admins.manage) se présente en deux colonnes : la liste des groupes à gauche, la fiche du groupe choisi et la liste des permissions à droite.

    Action Détail
    Créer un groupe Nom, description, permissions à cocher ; identifiant tiré du nom (Modérateurs forum → moderateurs-forum)
    Modifier un groupe Nom, description, permissions ; point orange tant que ce n'est pas enregistré
    Supprimer un groupe Seulement s'il n'a ni membre ni invitation en cours
    Créer une permission Personnalisée, format module.action (ex. news.edit), libellé et description
    Supprimer une permission Personnalisée uniquement ; elle est retirée de tous les groupes

    Les changements s'appliquent immédiatement, y compris aux sessions déjà ouvertes : les droits sont relus par le serveur à chaque requête.

    🛡️ Garde-fous (appliqués par le serveur)

    • Le groupe Propriétaire a toujours toutes les permissions, y compris celles créées plus tard : il ne peut être ni modifié ni supprimé. Il reste donc toujours quelqu'un capable de tout réparer.
    • Pas d'élévation de droits : on n'accorde à un groupe que des permissions que l'on a soi-même, et on ne place un administrateur que dans un groupe dont on a toutes les permissions.
    • On ne modifie pas les permissions de son propre groupe (comme on ne change pas son propre groupe).
    • Seul un propriétaire donne ou retire le groupe Propriétaire, ou gère un autre propriétaire (groupe, révocation, appareils).
    • Les permissions intégrées (vérifiées par le launcher et le serveur) ne peuvent pas être supprimées.
    • Deux administrateurs modifient le même groupe en même temps : la seconde modification est refusée (409 revision_conflict), rien n'est écrasé.
    • Chaque action est une requête signée et est inscrite au journal d'audit : admins.group_create, admins.group_update, admins.group_delete, admins.permission_create, admins.permission_delete.

    ⚠️ Donner admins.manage à un autre groupe que Propriétaire équivaut presque aux droits d'un propriétaire (dans la limite de ses propres permissions) : la page demande une confirmation renforcée.

    Autres pages concernées

    Page Changement
    Administrateurs Le groupe remplace le rôle ; seuls les groupes attribuables sont proposés ; description du groupe affichée à l'invitation
    Signature Les autorisations releases / catalog proposées pour le trousseau suivent les permissions du groupe de chaque administrateur
    Journal d'audit Libellés des nouvelles actions
    Barre latérale, tableau de bord, Mes appareils Nom du groupe affiché

    🖼️ Icône et image de fond sans client FTP

    Page « Jeux » › un jeu › « Parcourir… » à côté du champ « Icône » ou « Image de fond » :

    1. choix de l'image dans l'explorateur Windows ;
    2. contrôle sur le PC, avec les mêmes règles que le serveur ;
    3. envoi au serveur (requête signée), qui la range dans catalog/images/<empreinte SHA-256>.png|.jpg ;
    4. adresse renseignée automatiquement dans le champ, avec un aperçu de l'image ;
    5. « Publier » : l'image est appliquée aux joueurs au prochain démarrage de leur launcher.
    Règle Valeur
    Formats PNG ou JPEG, reconnus à leur contenu (pas à l'extension)
    Taille 4 Mo au plus
    Icône De 32 × 32 à 2048 × 2048 px
    Image de fond De 640 × 360 à 7680 × 4320 px
    Fichier Complet, sans données étrangères ajoutées après l'image
    Dossier du serveur 300 images et 300 Mo au plus ; les images inutilisées se suppriment dans « Fichiers du serveur »

    🛡️ Une image envoyée depuis le menu porte son empreinte SHA-256 dans son nom, et le launcher des joueurs la vérifie au téléchargement. Son adresse figurant dans le catalogue signé, l'image est couverte par la signature du catalogue. Les images déposées à la main en SFTP restent acceptées, mais sans cette vérification.

    💡 L'icône d'un jeu s'affiche sur sa tuile, dans la liste des jeux à gauche de la fenêtre, visible seulement avec plusieurs jeux. Avec un seul jeu, le logo en haut à gauche vient du thème. L'aide sous le champ le précise désormais.


    🧭 Navigation dans le menu d'administration

    • Deux colonnes, deux ascenseurs : pages Jeux, Notes de version et Groupes et permissions. La liste de gauche reste visible quand on descend dans la fiche de droite ; la fiche remonte en haut quand on choisit un autre élément.
    • Les bandeaux (erreur, résultat, conflit) et le choix du jeu restent en haut de la page, hors des zones qui défilent.
    • Fichiers du serveur : se déplacer dans les dossiers (fil d'Ariane, double-clic, « Dossier parent ») ne fait plus remonter l'ascenseur. Seules une erreur ou une suppression ramènent en haut, pour afficher leur bandeau.

    🖧 Serveur (Launcher API)

    Route Signée Permission Rôle
    GET v1/groups admins.manage Groupes, membres, permissions connues
    POST v1/groups ✔ admins.manage Créer un groupe
    PUT v1/groups/{id} ✔ admins.manage Modifier un groupe (révision attendue)
    DELETE v1/groups/{id} ✔ admins.manage Supprimer un groupe vide
    POST v1/permissions ✔ admins.manage Créer une permission personnalisée
    DELETE v1/permissions/{nom} ✔ admins.manage Supprimer une permission personnalisée
    PUT v1/catalog/images/{icon|background} ✔ games.edit Envoyer une image du catalogue (4 Mo au plus)
    • admins.json passe au format 2 (groupes, permissions personnalisées). Un fichier au format 1 est converti à la lecture et réécrit au format 2 à la modification suivante.
    • Le nom du groupe (RoleName) est transmis avec le profil, la liste des administrateurs et les invitations ; la liste des administrateurs inclut leurs permissions effectives.
    • Commande list du VPS : affiche aussi les groupes et leurs permissions.

    🧪 Tests

    Fichier Tests
    Server/GroupsModuleTests.cs (nouveau) 7 : groupes par défaut, groupe personnalisé et effet immédiat, conflit de révision, protections (groupe système, groupe utilisé), pas d'élévation de droits, permissions personnalisées, signature exigée, migration du format 1
    Server/CatalogImageTests.cs (nouveau) 11 : stockage sous l'empreinte, refus (texte, image tronquée, données ajoutées, dimensions), droits, dossier absent, taille, contrôle des formats, règles des groupes, vérification côté joueur
    Admin/GroupsPanelTests.cs (nouveau) 3 : page Groupes (modifier, créer, supprimer, permissions), gestionnaire limité à ses droits, « Parcourir… » de la page Jeux
    Admin/ChangelogPanelTests.cs, Admin/FilesPanelTests.cs Deux colonnes uniquement quand il y a des versions ; ascenseur inchangé en naviguant dans les dossiers

    276 tests au vert.

    📂 Fichiers modifiés

    Contrats

    • src/GameLauncher.Contracts/Security/AdminGroups.cs (nouveau)
    • src/GameLauncher.Contracts/Dtos/GroupDtos.cs (nouveau)
    • src/GameLauncher.Contracts/Catalog/CatalogImages.cs (nouveau)
    • src/GameLauncher.Contracts/Security/AdminPermissions.cs
    • src/GameLauncher.Contracts/Security/AdminRoles.cs
    • src/GameLauncher.Contracts/Dtos/AdminDtos.cs
    • src/GameLauncher.Contracts/Dtos/AuthDtos.cs
    • src/GameLauncher.Contracts/ApiRoutes.cs

    Serveur

    • server/GameLauncher.Server/Modules/Admins/AdminRules.cs (nouveau)
    • server/GameLauncher.Server/Modules/Admins/GroupsModule.cs (nouveau)
    • server/GameLauncher.Server/Storage/CatalogImageStore.cs (nouveau)
    • server/GameLauncher.Server/Modules/Admins/AdminsModule.cs
    • server/GameLauncher.Server/Modules/Auth/AuthModule.cs
    • server/GameLauncher.Server/Modules/Catalog/CatalogModule.cs
    • server/GameLauncher.Server/Security/AdminAuthentication.cs
    • server/GameLauncher.Server/Storage/AdminRecords.cs
    • server/GameLauncher.Server/Storage/AdminStore.cs
    • server/GameLauncher.Server/Storage/PublicFileWriter.cs
    • server/GameLauncher.Server/Hosting/IApiModule.cs
    • server/GameLauncher.Server/Cli/AdminCli.cs

    Launcher (joueur) et client API

    • src/GameLauncher.Core/Catalog/CatalogService.cs
    • src/GameLauncher.ApiClient/AdminSession.cs

    Menu d'administration

    • src/GameLauncher.Modules/Admin/AdminPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Accounts/GroupsPanelViewModel.cs (nouveau)
    • src/GameLauncher.Modules.Admin/Accounts/AccountsAdminModule.cs
    • src/GameLauncher.Modules.Admin/Accounts/AdminsPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Accounts/AccountItems.cs
    • src/GameLauncher.Modules.Admin/Accounts/MyDevicesPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Catalog/CatalogEditors.cs
    • src/GameLauncher.Modules.Admin/Catalog/GamesPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Changelog/ChangelogPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Files/FilesPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Signing/SigningPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Audit/AuditPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Services/AdminTexts.cs
    • src/GameLauncher.Modules.Admin/ViewModels/AdminWorkspaceViewModel.cs
    • src/GameLauncher.Modules.Admin/ViewModels/DashboardPanelViewModel.cs

    Interface WPF

    • src/GameLauncher/Themes/Admin.xaml
    • src/GameLauncher/Views/Admin/AdminWindow.xaml
    • src/GameLauncher/Converters/Converters.cs
    • src/GameLauncher/GameLauncher.csproj (version 2.4.0)

    Tests

    • tests/GameLauncher.Tests/Infrastructure/TestImages.cs (nouveau)
    • tests/GameLauncher.Tests/Server/GroupsModuleTests.cs (nouveau)
    • tests/GameLauncher.Tests/Server/CatalogImageTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/GroupsPanelTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/ChangelogPanelTests.cs
    • tests/GameLauncher.Tests/Admin/FilesPanelTests.cs

    Outils, déploiement, documentation et notes

    • tools/AdminKeyTool/Program.cs
    • tools/UiSnapshot/Fakes/FakeApi.cs
    • tools/UiSnapshot/Capture.cs
    • tools/notes-launcher.txt
    • server/deploy/nginx-api.conf
    • server/deploy/LISEZMOI.md
    • README.md
    • docs/ADMIN-ARCHITECTURE.md

    ⬆️ Mise à niveau

    • Joueurs : mise à jour automatique depuis la 2.3.0, aucune action requise.
    • Serveur (Launcher API) : à redéployer (server/deploy/LISEZMOI.md, étape 3 septies) :
      1. avant la mise à jour, garder une copie de la liste des administrateurs (elle passe au format 2, qu'une ancienne version du serveur refuse) :
        sudo -u deploy cp /var/lib/launcher-api/admins.json /var/lib/launcher-api/admins.format1.json
        
      2. mettre le serveur à jour (étape 8), puis vérifier avec sudo -u deploy /opt/launcher-api/GameLauncher.Server list ;
      3. nginx : ajouter le bloc location ^~ /api/v1/catalog/images/ { … } de server/deploy/nginx-api.conf, puis sudo nginx -t && sudo systemctl reload nginx (sans lui, les images de plus de 64 Ko sont refusées) ;
      4. vérifier que le dossier /srv/exovival/www/catalog/images existe (étape 3 bis).
    • Administrateurs : rien à faire ; les comptes gardent leurs droits. Après un changement des permissions d'un groupe qui touche releases.publish ou games.edit, la page Signature indique s'il faut refaire le trousseau.

    🔏 La sécurité des mises à jour du launcher ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    Contributors

    Full Changelog: v2.3.0...v2.4.0

    Downloads
  • v2.3.0 94cf7147e3

    nicolas released this 2026-11-07 11:55:55 +01:00 | 119 commits to master since this release

    🚀 Launcher 2.3.0 — Menu d'administration multi-jeu

    Version consacrée à la gestion de plusieurs jeux : les pages « Notes de version » et « Publier une version » demandent désormais de choisir le jeu avant d'afficher quoi que ce soit, pour ne jamais modifier ou publier le mauvais jeu par erreur.

    Côté joueurs, rien ne change : le jeu, les mises à jour et le launcher fonctionnent comme avant.

    ✨ En bref

    Changement
    🔄 Modifié « Notes de version » et « Publier une version » : choix du jeu obligatoire quand plusieurs jeux sont déclarés (plus de jeu par défaut)
    🆕 Nouveau Carte « Choisir le jeu » (une tuile par jeu), puis liste « Jeu » pour en changer
    🐛 Corrigé « Publier une version » : changer de jeu efface tout ce qui concernait le jeu précédent
    🐛 Corrigé Un envoi interrompu reste attaché à son jeu
    💡 Amélioré Confirmations et résultats de publication : le jeu est nommé
    🔄 Modifié « Fichiers du serveur » : plus de jeu choisi par défaut pour le nettoyage du dossier objects
    💡 Amélioré Listes déroulantes : texte indicatif quand rien n'est choisi
    🧪 Qualité 2 nouveaux tests automatisés (255 au total)

    🎮 Choix du jeu

    Jusqu'ici, ces deux pages s'ouvraient directement sur le jeu par défaut de launcher.json. Avec plusieurs jeux, il était facile de corriger les notes ou de publier une version du mauvais jeu sans s'en rendre compte.

    Situation Comportement
    Plusieurs jeux déclarés La page s'ouvre sur la carte « Choisir le jeu » : une tuile par jeu (nom, identifiant, serveur). Rien n'est chargé ni affiché avant le choix
    Jeu choisi Contenu de la page pour ce jeu ; liste « Jeu » en haut pour en changer
    Changement de jeu Désactivé pendant un chargement ou un envoi ; confirmation si des notes ne sont pas enregistrées
    Un seul jeu déclaré Choisi automatiquement : aucun changement par rapport à la 2.2.0

    Le choix du jeu repose sur un composant commun (GameTile et les modèles AdminGamePickerTemplate / AdminGameSwitcherTemplate de Themes/Admin.xaml), réutilisable par les futures pages propres à un jeu.


    📦 Publier une version : rien d'un jeu ne reste pour un autre

    Avant : au changement de jeu, le chemin du dossier de publication restait affiché et le bouton « Contrôler de nouveau » restait actif. Le bandeau d'un envoi interrompu s'affichait aussi pour les autres jeux.

    Maintenant :

    • au changement de jeu, sont effacés : le dossier choisi, la version prête, la version en ligne, sa signature et l'avancement de l'envoi ;
    • une réponse du serveur qui arrive après un changement de jeu est ignorée (pas de version en ligne d'un jeu affichée pour un autre) ;
    • un envoi interrompu est mémorisé par jeu : le bandeau « Reprendre / Abandonner » réapparaît quand on revient à ce jeu ;
    • les confirmations (« Publier la version… », « Signer la version en ligne… ») et le message de résultat nomment le jeu : Version 1.2 de Exovival Zombie Reborn (EZR) publiée.

    🛡️ Un dossier de publication produit pour un autre jeu reste refusé : l'identifiant du jeu du manifest est contrôlé avant tout envoi, et de nouveau par le serveur.


    🗂️ Fichiers du serveur

    • Nettoyage du dossier objects : avec plusieurs jeux, aucun jeu n'est choisi par défaut ; la liste affiche « Choisir le jeu à nettoyer… ». Avec un seul jeu, il reste choisi automatiquement.
    • Les listes déroulantes du thème (ModernComboBoxStyle) acceptent maintenant un texte indicatif (ui:TextAssist.Placeholder) affiché quand rien n'est choisi.

    🔍 Autres pages vérifiées

    Page Multi-jeu
    Tableau de bord ✅ Liste tous les jeux déclarés
    Jeux ✅ Launcher et tous les jeux du catalogue
    Signature ✅ Version en ligne de chaque jeu
    Fichiers du serveur ✅ Site entier ; nettoyage par jeu choisi explicitement
    Journal d'audit Non concerné (recherche possible par identifiant de jeu)
    Mes appareils, Administrateurs Non concernés

    🧪 Tests

    Fichier Tests
    Admin/MultiGamePanelTests.cs (nouveau) 2 : notes de version (aucun chargement avant le choix, tuiles, changement refusé avec des notes non enregistrées, enregistrement limité au manifest du jeu choisi) ; publication (rien avant le choix, effacement au changement de jeu, dossier d'un autre jeu refusé, jeu nommé dans la confirmation et le résultat)
    Admin/PublishPanelTests.cs Cas à un seul jeu : choisi d'office, sans carte de choix
    Admin/ChangelogPanelTests.cs Cas à un seul jeu : choisi d'office

    255 tests au vert.

    📂 Fichiers modifiés

    Menu d'administration (modèles de vue)

    • src/GameLauncher.Modules.Admin/ViewModels/GameTile.cs (nouveau)
    • src/GameLauncher.Modules.Admin/Changelog/ChangelogPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Publishing/PublishPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Files/FilesPanelViewModel.cs

    Interface WPF

    • src/GameLauncher/Themes/Admin.xaml
    • src/GameLauncher/Themes/Controls.xaml
    • src/GameLauncher/GameLauncher.csproj (version 2.3.0)

    Tests

    • tests/GameLauncher.Tests/Admin/MultiGamePanelTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/PublishPanelTests.cs
    • tests/GameLauncher.Tests/Admin/ChangelogPanelTests.cs

    Outils, documentation et notes

    • tools/UiSnapshot/Scenes/AdminScenes.cs
    • tools/notes-launcher.txt
    • README.md
    • docs/ADMIN-ARCHITECTURE.md

    ⬆️ Mise à niveau

    • Joueurs : mise à jour automatique depuis la 2.2.0, aucune action requise.
    • Serveur (Launcher API) : inchangé, rien à redéployer (si la 2.2.0 a bien été déployée).
    • Administrateurs : rien à faire ; avec un seul jeu déclaré, les pages se comportent comme avant.

    🔏 La sécurité des mises à jour du launcher ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    Contributors

    Full Changelog: v2.2.0...v2.3.0

    Downloads
  • v2.2.0 8e69ec108e

    nicolas released this 2026-11-07 11:06:51 +01:00 | 126 commits to master since this release

    🚀 Launcher 2.2.0 — Fichiers du serveur et journal d'audit

    Version consacrée au menu d'administration : une nouvelle page « Fichiers du serveur » pour libérer de la place sans risque, un journal d'audit filtrable par date qui trace ses propres consultations et exports, et une navigation plus confortable dans toutes les pages.

    Côté joueurs, rien ne change : le jeu, les mises à jour et le launcher fonctionnent comme avant.

    ✨ En bref

    Changement
    🆕 Nouveau Page « Fichiers du serveur » : parcours du site, suppression des fichiers inutilisés, nettoyage du dossier objects d'un jeu
    🆕 Nouveau Journal d'audit : filtre par période, aussi appliqué à l'export CSV
    🆕 Nouveau Chaque consultation et chaque export du journal d'audit sont inscrits au journal
    💡 Amélioré Boutons d'action toujours visibles en bas de chaque page du menu d'administration
    💡 Amélioré Retour automatique en haut de la page après « Recharger », « Publier »… pour voir le bandeau de résultat
    🐛 Corrigé La molette ne change plus une liste déroulante par erreur pendant le défilement de la page
    💡 Amélioré Liens d'un jeu : en-têtes de colonnes, textes indicatifs et info-bulles
    🖧 Serveur Nouvelles routes v1/files, v1/games/{id}/objects/prune, v1/audit/export et paramètre before : à redéployer
    🧪 Qualité 18 nouveaux tests automatisés (253 au total)

    🗂️ Nouvelle page « Fichiers du serveur »

    Accessible aux propriétaires et administrateurs (nouvelle permission files.manage), elle permet de libérer de la place sur le serveur graphiquement, par exemple en supprimant les anciennes archives .zip.

    Ce qu'elle affiche :

    • les dossiers du site public, avec un fil d'Ariane (www › exovivalzombie › objects) ;
    • pour chaque élément : taille, nombre de fichiers (dossiers), date et état ;
    • l'espace disque libre et utilisé du serveur ;
    • un filtre « Fichiers inutilisés seulement ».
    État Signification Supprimable
    ✅ Utilisé Référencé par un manifest (archive, fichier de la version en ligne) ou par le catalogue (image) Non
    🗑️ Inutilisé Référencé par aucun fichier de description Oui, après confirmation
    🔒 Protégé Fichier de description .json (manifest, catalogue, trousseau, mise à jour du launcher) Jamais
    ❔ Inconnu Un fichier de description est illisible : vérification impossible Jamais
    🔗 Lien Lien symbolique : ni suivi, ni supprimé Jamais

    Nettoyage du dossier objects d'un jeu :

    1. « Analyser » : nombre de fichiers que la version en ligne n'utilise plus, place récupérable, quelques exemples et fichiers manquants éventuels ;
    2. « Nettoyer » : suppression après confirmation, uniquement des fichiers objects/xx/<sha256>.bin que plus aucun manifest n'utilise.

    🛡️ Règles de sécurité (appliquées par le serveur)

    Le launcher ne fait qu'afficher : le serveur décide seul de ce qui peut être supprimé et revérifie tout au moment de supprimer.

    • Tous les manifests et le catalogue sont relus juste avant chaque suppression : un fichier encore référencé n'est jamais supprimé.
    • Les manifests ne peuvent jamais être supprimés, ni aucun fichier .json.
    • Fonctionnement fermé par défaut : un manifest illisible bloque son dossier, une adresse qui ne peut pas être vérifiée bloque tout le site.
    • Refus si une publication du jeu est en cours, si le fichier a changé depuis l'affichage (taille), ou si le manifest a changé depuis l'analyse (empreinte SHA-256).
    • Suppression et nettoyage sérialisés avec la publication (verrou du jeu).
    • Chemins strictement contrôlés : pas de .., pas de fichiers cachés, pas de liens symboliques.
    • Requêtes signées par la clé de l'administrateur et inscrites au journal d'audit (files.delete, files.prune).
    • Aucun chemin du serveur dans les messages d'erreur (le détail va dans journalctl).

    📜 Journal d'audit

    Filtre par période

    Choix Période
    Aujourd'hui Le jour même
    7 / 30 derniers jours Glissant jusqu'à aujourd'hui
    Ce mois-ci / Mois précédent Mois calendaire
    Dates choisies « Du » / « Au » au format jj/mm/aaaa (contrôle de saisie)
    • La fin de la période est demandée au serveur (GET v1/audit?before=, ISO 8601 ; les mois postérieurs ne sont pas lus), puis les pages sont chargées jusqu'à son début (5 000 entrées au plus).
    • L'export CSV suit la période, et le nom du fichier l'indique (journal-audit-2026-11-01-au-2026-11-07-….csv).

    Le journal se surveille lui-même

    Action Inscrite par Contenu
    audit.view « Journal d'audit consulté » Le serveur, à chaque lecture de la première page (ouverture, « Actualiser », période changée) Auteur, appareil, IP, nombre d'entrées lues, borne de date
    audit.export « Journal d'audit exporté (CSV) » Le serveur, sur annonce signée du launcher, avant l'écriture du fichier Auteur, appareil, IP, nombre d'entrées, période, filtres
    • « Charger plus » ne crée pas une ligne par page : une nouvelle ligne n'est écrite que si la dernière consultation inscrite du même appareil date de plus de 10 minutes. Un curseur forgé ne permet donc pas de lire sans trace.
    • Si le serveur ne peut pas inscrire l'export (serveur injoignable, session expirée, signature refusée), le fichier n'est pas écrit.
    • L'outil AdminKeyTool est tracé de la même façon.
    • Nouvelles catégories de filtre : « Fichiers du serveur » et « Consultations et exports du journal ».

    🧭 Menu d'administration : confort

    Problème Correction
    Les boutons « Recharger » / « Publier » étaient en bas de page : il fallait tout faire défiler Barre d'actions fixe en bas de la fenêtre, sur toutes les pages (Tableau de bord, Jeux, Notes de version, Publication, Mes appareils, Administrateurs, Journal d'audit, Signature, Fichiers)
    Le résultat d'une action s'affichait en haut, hors de vue Retour en haut après Recharger, Publier, Enregistrer, Actualiser, une signature ou une erreur, et à chaque changement de page
    La molette continuait de contrôler une liste après l'avoir quittée : paramètre modifié par erreur La molette fait défiler ce qui est sous la souris ; une liste déroulante fermée ne réagit plus, une liste ouverte défile normalement
    Liens d'un jeu : rien n'indiquait le rôle des deux champs En-têtes « Type (icône) / Texte du bouton / Adresse du lien (https://…) », textes indicatifs dans les champs vides, info-bulles et ligne d'aide

    Les champs texte du thème savent maintenant afficher un texte indicatif quand ils sont vides (ui:TextAssist.Placeholder).


    🖧 Serveur (Launcher API)

    ⚠️ À redéployer avec publish-server.bat. Sans le nouveau serveur, la page « Fichiers du serveur » et le filtre par date ne fonctionnent pas, les consultations ne sont pas tracées et l'export CSV est refusé.

    Route Méthode Permission Signée
    v1/files?path= GET files.manage
    v1/files/delete POST files.manage ✔
    v1/games/{gameId}/objects/prune GET (analyse) files.manage
    v1/games/{gameId}/objects/prune POST (nettoyage) files.manage ✔
    v1/audit?before= GET audit.read
    v1/audit/export POST audit.read ✔

    Configuration (appsettings.json) :

    • LauncherApi:Files:Root (facultatif) : racine du site. Par défaut, dossier commun aux manifests des jeux et au catalogue. Une racine explicite doit être absolue, exister, ne pas être la racine du disque et rester séparée du dossier de données. Si le dossier par défaut ne convient pas, la page est simplement désactivée (le serveur démarre quand même).
    • Droits d'écriture : les suppressions demandent que le service puisse écrire dans les dossiers concernés (ReadWritePaths du service systemd, par exemple /srv/exovival/www) ; voir server/deploy/LISEZMOI.md, section 3 sexies.

    Rôles : le rôle Admin reçoit files.manage ; Owner l'a automatiquement ; Editor n'y a pas accès.


    🧪 Tests

    Fichier Tests
    Server/FilesModuleTests.cs (nouveau) 9 : liste, règles de suppression, manifest illisible et publication en cours, nettoyage, références croisées entre manifests, liens symboliques, permissions, page non configurée, lecture du journal jusqu'à une date
    Admin/FilesPanelTests.cs (nouveau) 6 : parcours, suppression, nettoyage depuis la page ; affichage des tailles
    Server/AuditModuleTests.cs (nouveau) 2 : consultations inscrites sans une ligne par page ; exports inscrits et contrôlés
    Admin/AuditPanelTests.cs 1 nouveau : période et export ; contrôle des inscriptions audit.view / audit.export

    253 tests au vert.

    📂 Fichiers modifiés

    Contrats et client API

    • src/GameLauncher.Contracts/Files/ServerFilesDtos.cs (nouveau)
    • src/GameLauncher.Contracts/Dtos/AuditDtos.cs
    • src/GameLauncher.Contracts/ApiRoutes.cs
    • src/GameLauncher.Contracts/Security/AdminPermissions.cs
    • src/GameLauncher.Contracts/Security/AdminRoles.cs
    • src/GameLauncher.ApiClient/AdminSession.cs

    Serveur

    • server/GameLauncher.Server/Storage/ServerFilesStore.cs (nouveau)
    • server/GameLauncher.Server/Modules/Files/FilesModule.cs (nouveau)
    • server/GameLauncher.Server/Modules/Audit/AuditModule.cs
    • server/GameLauncher.Server/Storage/AuditLog.cs
    • server/GameLauncher.Server/Hosting/IApiModule.cs
    • server/GameLauncher.Server/Hosting/LauncherApiOptions.cs
    • server/GameLauncher.Server/appsettings.json

    Menu d'administration (modèles de vue)

    • src/GameLauncher.Modules/Admin/AdminPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Files/FilesAdminModule.cs (nouveau)
    • src/GameLauncher.Modules.Admin/Files/FilesPanelViewModel.cs (nouveau)
    • src/GameLauncher.Modules.Admin/Audit/AuditPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Catalog/CatalogEditors.cs
    • src/GameLauncher.Modules.Admin/Catalog/GamesPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Changelog/ChangelogPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Publishing/PublishPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Signing/SigningPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/ViewModels/DashboardPanelViewModel.cs
    • src/GameLauncher.Modules.Admin/Accounts/AccountItems.cs
    • src/GameLauncher.Modules.Admin/Services/AdminTexts.cs

    Interface WPF

    • src/GameLauncher/Controls/AdminAssist.cs (nouveau)
    • src/GameLauncher/Views/Admin/AdminWindow.xaml
    • src/GameLauncher/Themes/Admin.xaml
    • src/GameLauncher/Themes/Controls.xaml
    • src/GameLauncher/Themes/Icons.xaml
    • src/GameLauncher/App.xaml.cs
    • src/GameLauncher/GameLauncher.csproj (version 2.2.0)

    Tests

    • tests/GameLauncher.Tests/Server/FilesModuleTests.cs (nouveau)
    • tests/GameLauncher.Tests/Server/AuditModuleTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/FilesPanelTests.cs (nouveau)
    • tests/GameLauncher.Tests/Admin/AuditPanelTests.cs

    Outils, documentation et notes

    • tools/UiSnapshot/Fakes/FakeApi.cs
    • tools/notes-launcher.txt
    • README.md
    • docs/ADMIN-ARCHITECTURE.md
    • server/deploy/LISEZMOI.md

    ⬆️ Mise à niveau

    • Joueurs : mise à jour automatique depuis la 2.1.0, aucune action requise.
    • Serveur (Launcher API) : à redéployer (publish-server.bat) ; vérifier ReadWritePaths si le site n'est pas déjà accessible en écriture au service.
    • Administrateurs : les comptes « Admin » obtiennent automatiquement l'accès à la page « Fichiers du serveur ». Les clés existantes fonctionnent telles quelles.

    🔏 La sécurité des mises à jour du launcher ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    Contributors

    Full Changelog: v2.1.0...v2.2.0

    Downloads
  • v2.1.0 0f8f64f00f

    nicolas released this 2026-11-07 08:58:01 +01:00 | 140 commits to master since this release

    🚀 Launcher 2.1.0 — Corrections du menu d'administration et raccourci du Bureau

    Version de corrections après la 2.0.0 : la connexion par clé TPM fonctionne de nouveau, les listes du menu d'administration redeviennent lisibles, et le raccourci du Bureau suit désormais le nom affiché du jeu.

    Côté joueurs, une seule nouveauté visible : le raccourci du Bureau porte le nom du jeu tel qu'il est affiché dans le launcher.

    ✨ En bref

    Changement
    🐛 Corrigé Clé TPM : la puce n'est plus vue comme « bloquée » en permanence, la connexion par code PIN refonctionne
    🐛 Corrigé Menu d'administration : noms des listes lisibles (plus de noir sur noir)
    🐛 Corrigé Menu d'administration : plus de panneau blanc derrière les listes pendant « Recharger »
    🔄 Modifié Le raccourci du Bureau prend le nom affiché du jeu (catalogue)
    💡 Amélioré Page « Jeux » : explications sur le nom du launcher et le nom affiché
    🧪 Qualité 3 nouveaux tests sur la lecture de l'état de la puce TPM
    🛠️ Outils Nouvel outil de captures d'écran tools/ui-snapshot.bat (développement uniquement)

    🔐 Clé TPM : connexion de nouveau possible

    Symptôme : après la création d'une clé dans la puce (« J'ai une invitation »), l'écran de connexion affichait immédiatement « puce verrouillée ». Le message revenait même une semaine plus tard, au premier lancement.

    Cause : pour savoir si la puce est bloquée par sa protection anti-essais, le launcher lisait le bit 2 de TPMA_PERMANENT (lockoutAuthSet). Ce bit indique seulement qu'une autorisation « lockout » existe, ce qui est toujours vrai sur un PC dont Windows gère la puce. Le décompte (souvent 2 h) recommençait ensuite en boucle et bloquait la saisie du code PIN.

    Correction :

    • le blocage est lu dans le bit 9 (inLockout) et dans le compteur TPM_PT_LOCKOUT_COUNTER comparé à TPM_PT_MAX_AUTH_FAIL ;
    • la lecture de la réponse TPM2_GetCapability est déplacée dans TpmLockoutInfo.FromCapabilityResponse (projet GameLauncher.Modules.Admin), avec contrôle de la balise, du code retour, du type de capacité et de la longueur ;
    • 3 tests ajoutés : PC ordinaire non bloqué, blocage détecté par l'indicateur ou par le compteur, réponses en erreur, incomplètes ou tronquées.

    Rien à refaire : les clés TPM déjà créées fonctionnent telles quelles.

    🛡️ La protection anti-essais reste assurée par la puce elle-même : un code PIN faux compte toujours, et une puce réellement bloquée refuse tout code.


    🎨 Menu d'administration : listes lisibles

    Les listes du menu gardaient le modèle Windows par défaut, qui :

    • imposait un texte noir aux éléments (noms « Launcher », « Exovival Zombie Reborn » illisibles sur fond sombre) ;
    • peignait un fond blanc quand la liste était désactivée, c'est-à-dire pendant un rechargement ou une publication.

    Correction : nouveau style AdminListBoxStyle (fond transparent, texte du thème, liste simplement atténuée lorsqu'elle est désactivée), appliqué aux 4 listes :

    Liste Écran
    Navigation Fenêtre d'administration
    Launcher et jeux Page « Jeux »
    Versions Page « Notes de version »
    Clés Écran de connexion

    Les titres des éléments ont aussi une couleur explicite (TextPrimaryBrush).


    🖥️ Raccourci du Bureau : il suit le nom affiché du jeu

    Avant, le raccourci gardait toujours le nom de launcher.json, même après un changement du « Nom affiché » dans la page « Jeux ».

    Moment Ce qui se passe
    Démarrage du launcher Les raccourcis nommés par le launcher sont renommés
    Paramètres du jeu › Raccourci › « Mettre à jour » Redirection, icône du jeu et nouveau nom
    « Réparer » Raccourci renommé, signalé dans le bandeau de fin
    Création Nom affiché du jeu, sinon celui de launcher.json
    Désinstallation Retire aussi un raccourci renommé par le launcher

    Règles de sécurité :

    • un raccourci renommé par le joueur garde son nom (reconnu grâce au commentaire du raccourci, qui mémorise le nom posé par le launcher) ;
    • aucun fichier existant du Bureau n'est remplacé par un nom venu du catalogue : en cas de conflit, le nom de launcher.json est conservé ;
    • le nom est nettoyé (caractères interdits remplacés) et limité à 80 caractères par les règles du catalogue.

    « Applications installées » de Windows et les dossiers du jeu gardent le nom de launcher.json.


    🏷️ Page « Jeux » : le nom du launcher

    Le champ « Nom du launcher » fonctionnait, mais son effet était peu visible. La page indique maintenant où il apparaît :

    • paramètres du launcher (roue crantée), sous le titre ;
    • info-bulle de l'icône de la zone de notification ;
    • titre de la fenêtre dans la barre des tâches, quand plusieurs jeux sont proposés.

    Avec un seul jeu, l'en-tête montre le nom du jeu. Le catalogue publié est pris en compte au démarrage suivant du launcher.

    L'aide du champ « Nom affiché » précise désormais que le raccourci du Bureau suit ce nom.


    🛠️ Développement

    • Nouvel outil tools/UiSnapshot (tools/ui-snapshot.bat) : capture les fenêtres du launcher et du menu d'administration dans leurs différents états (~45 écrans) et produit un rapport (artifacts/ui-snapshots/report.md).
      • API d'administration simulée en mémoire, sans réseau ; clés de démonstration temporaires.
      • Rien n'est lu ni écrit dans %AppData%, le registre ou .launcher-keys.
      • Jamais livré aux joueurs.
    • Les icônes de MainWindow.xaml et AdminWindow.xaml utilisent l'adresse pack:// complète (aucun effet visible).
    • README.md mis à jour : raccourcis du Bureau, nom du launcher, lecture du blocage TPM.
    📂 Fichiers modifiés

    Clé TPM

    • src/GameLauncher.Modules.Admin/Services/IAdminTpm.cs
    • src/GameLauncher/Platform/TpmKeyStore.cs
    • tests/GameLauncher.Tests/Admin/AdminTpmTests.cs

    Listes du menu d'administration

    • src/GameLauncher/Themes/Admin.xaml
    • src/GameLauncher/Views/Admin/AdminWindow.xaml
    • src/GameLauncher/Views/Admin/LoginView.xaml

    Raccourci du Bureau

    • src/GameLauncher/Services/ShortcutService.cs
    • src/GameLauncher/Services/Interfaces.cs
    • src/GameLauncher/ViewModels/GameViewModel.cs
    • src/GameLauncher.Modules.Admin/Catalog/CatalogEditors.cs
    • src/GameLauncher.Core/Models/LauncherConfig.cs
    • src/GameLauncher.Core/Catalog/CatalogMerger.cs
    • src/GameLauncher.Contracts/Catalog/CatalogDocument.cs
    • tools/UiSnapshot/Fakes/FakeServices.cs

    Outil de captures

    • tools/UiSnapshot/ (nouveau projet), tools/ui-snapshot.bat, GameLauncher.sln

    Documentation et notes

    • README.md
    • tools/notes-launcher.txt

    ⬆️ Mise à niveau

    • Joueurs : mise à jour automatique depuis la 2.0.0, aucune action requise.
    • Serveur (Launcher API) : inchangé, rien à redéployer.
    • Administrateurs avec une clé TPM : rien à refaire, la clé existante fonctionne.

    🔏 La sécurité des mises à jour du launcher ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    Contributors

    Full Changelog: v2.0.0...v2.1.0

    Downloads
  • v2.0.0 fbfb456b5d

    nicolas released this 2026-11-07 08:07:34 +01:00 | 148 commits to master since this release

    🚀 GameLauncher 2.0.0 — Le menu d'administration

    Version majeure. Le launcher s'administre désormais depuis le launcher lui-même : informations des jeux, notes de version, publication d'une nouvelle version, gestion des administrateurs, journal d'audit et signature de tout ce que reçoivent les joueurs.
    Le tout repose sur un nouveau serveur, le Launcher API, et sur une authentification par clé publique / clé privée : aucun mot de passe, aucun secret dans l'exécutable, aucun secret sur le serveur.

    Pour les joueurs, rien ne change : le menu d'administration est invisible, ne contacte le serveur qu'une fois ouvert, et toutes les nouveautés côté joueur (catalogue, signature) sont rétrocompatibles et désactivables.


    ✨ En bref

    Nouveauté Pour qui
    🔐 Menu d'administration intégré : accès discret, connexion par clé, verrouillage automatique Administrateurs
    🗝️ Clé d'administrateur en fichier chiffré ou dans la puce TPM 2.0 du PC (non exportable) Administrateurs
    🏠 Tableau de bord : compte, droits, session, serveur, jeux, approbations en attente Tous les administrateurs
    🎮 Page « Jeux » : nom affiché, accroche, description, liens, thème, icône, fond, ordre… sans republier le launcher Éditeurs et +
    📝 Page « Notes de version » : éditeur graphique avec aperçu identique au launcher Éditeurs et +
    📦 Page « Publier une version » : envoi du jeu depuis le launcher, avec reprise et vérification Administrateurs et +
    💻 Page « Mes appareils » : ses PC, ajout d'un nouveau PC par invitation Tous les administrateurs
    👥 Page « Administrateurs » : inviter, approuver par empreinte, changer un rôle, révoquer Propriétaires
    📜 Page « Journal d'audit » : toutes les actions, filtres, export CSV Administrateurs et +
    ✍️ Page « Signature » + signature de bout en bout : versions et catalogue signés, vérifiés par les launchers Propriétaires / joueurs
    🖥️ Launcher API : serveur ASP.NET Core durci (systemd, nginx), modules, audit, outil en ligne de commande VPS
    🧪 232 tests automatisés (unitaires et de bout en bout, serveur démarré en mémoire) Qualité

    📑 Sommaire

    1. Ouvrir le menu d'administration
    2. Clés d'administrateur et connexion
    3. Tableau de bord
    4. Page « Jeux » — le catalogue des jeux
    5. Page « Notes de version »
    6. Page « Publier une version »
    7. Pages « Mes appareils », « Administrateurs » et « Journal d'audit »
    8. Page « Signature » et signature de bout en bout
    9. Nouveautés pour les joueurs
    10. Launcher API (serveur)
    11. Sécurité
    12. Déploiement sur le VPS
    13. Outils
    14. Configuration : nouvelles clés de launcher.json
    15. Corrections et stabilisation
    16. Architecture technique
    17. Mise à niveau depuis 1.x
    18. Limites connues

    1. Ouvrir le menu d'administration

    • ⌨️ Ctrl + Maj + Alt + A dans la fenêtre du launcher, ou 5 clics rapides (en moins de 3 s) sur le logo en haut à gauche.
    • L'accès est discret mais pas secret : seule la connexion par clé, vérifiée par le serveur, protège l'administration. Masquer le bouton n'est qu'un confort.
    • Fenêtre dédiée au design moderne (coins arrondis, icônes, thème sombre) :
      • à gauche : l'administrateur connecté, les pages auxquelles il a droit, le temps restant avant verrouillage et le bouton « Verrouiller » ;
      • à droite : la page choisie.
    • Seules les pages autorisées par les droits renvoyés par le serveur sont affichées (le serveur reste seul juge).
    • Sans apiUrl dans launcher.json, le menu indique clairement qu'il n'est relié à aucun serveur.

    🔒 Verrouillage automatique

    La clé déchiffrée n'existe en mémoire que pendant la session. Le menu se verrouille (session fermée, clé effacée, retour à l'écran de connexion) :

    Déclencheur Détail
    ⏱️ Inactivité 10 minutes sans activité dans la fenêtre
    ⌛ Durée maximale 8 heures de session
    🪟 Windows Session Windows verrouillée (Win + L, mise en veille)
    ⌨️ Manuel Ctrl + L ou bouton « Verrouiller »
    🚫 Serveur Session refusée par le serveur (révocation, redémarrage)
    • Tant que l'administrateur est actif, la session est prolongée automatiquement sur le serveur toutes les 4 minutes.
    • Fermer la fenêtre ou le launcher efface la clé, puis ferme la session sur le serveur.
    • La phrase de passe n'est jamais conservée (champ vidé dès la tentative de connexion).
    • Pendant l'envoi d'une version, le verrouillage pour inactivité est suspendu (le verrouillage manuel, celui de Windows et la durée maximale restent appliqués).

    2. Clés d'administrateur et connexion

    🗝️ Deux façons de ranger sa clé

    📄 Fichier chiffré 🛡️ Puce de sécurité TPM 2.0
    Algorithme ECDSA P-256 / SHA-256 ECDSA P-256 / SHA-256, générée dans la puce
    Protection Phrase de passe (12 caractères min.), AES-256, PBKDF2-SHA256 600 000 itérations Code PIN (6 caractères min.) vérifié par la puce, blocage anti-essais
    Copie / sauvegarde ✅ Possible ❌ Impossible (non exportable)
    Fichiers sur le disque *.key (chiffré) + *.pub *.tpmkey (référence, sans secret) + *.pub
    Disparaît avec La perte du fichier La carte mère, une réinitialisation du TPM, une réinstallation de Windows
    • Dossier proposé : %USERPROFILE%\.launcher-keys.
    • Une clé n'écrase jamais un fichier existant.
    • Le choix TPM n'est proposé qu'après une vérification réelle de la puce (création, signature et suppression d'une clé de test).
    • À la connexion TPM, la clé publique de la puce est comparée à celle du fichier de référence avant tout essai du code PIN. Le fichier .tpmkey ne peut désigner que des clés GameLauncher.Admin.*.
    • Après un code PIN faux : nombre d'essais restants affiché ; si la puce est bloquée, un décompte indique quand elle acceptera de nouveau un code (état lu dans la puce via TPM2_GetCapability).
    • Bouton « Supprimer cette clé de la puce » sur l'écran de connexion (clé TPM uniquement, après confirmation).
    • 💡 Conseil : avec une clé TPM, garder aussi une clé fichier de secours.

    🚫 Clés refusées

    • La clé de signature du launcher (launcher-signing*.key, copies comprises) n'est jamais proposée ni acceptée.
    • Nouveau : toute clé dont l'identifiant ou la clé publique est celle de la clé racine intégrée au launcher est refusée, quel que soit le nom du fichier.

    🔑 Connexion par défi signé

    1. Le launcher demande un défi au serveur (sans état : valable 60 s, nonce de 256 bits, scellé par HMAC — réponse identique pour une clé connue ou inconnue).
    2. Il signe un message de connexion contenant l'origine, l'identifiant du serveur, le défi, le nonce et la clé.
    3. Le serveur vérifie le sceau, l'échéance, la signature, que la clé et le compte sont actifs, et que le défi n'a jamais été utilisé.
    4. Il renvoie un jeton de session (256 bits, seule son empreinte est conservée) et les droits.

    ✍️ Requêtes signées

    Toute requête qui modifie quelque chose porte, en plus du jeton, une signature de la clé de l'administrateur (méthode, chemin, SHA-256 du corps, horodatage, nonce).
    ➡️ Un jeton volé ne permet aucune modification, et le journal d'audit sait quelle clé a signé chaque action.

    📨 « J'ai une invitation »

    • Crée la clé sur ce PC (fichier ou TPM), l'enregistre auprès du serveur avec le code d'invitation et une preuve de possession, puis affiche l'empreinte à communiquer à la personne qui approuve.
    • Empreinte lisible : 5 groupes de 4 caractères (AB12 CD34 EF56 7890 1A2B, 80 bits).
    • Sans code : création d'une clé seule (premier propriétaire, à déclarer sur le VPS).

    3. Tableau de bord

    Page d'accueil du menu :

    • 👤 Compte connecté : nom, initiales, rôle, liste des droits.
    • 🔑 Clé utilisée (nom de l'appareil, identifiant).
    • ⏳ Session : heure de fin au plus tard.
    • 🖥️ Serveur : adresse, version, identifiant.
    • 🎮 Jeux déclarés dans launcher.json (nom, identifiant, hôte du manifest).
    • 🔔 Pour les propriétaires : appareils en attente d'approbation et invitations actives.
    • 🔗 Raccourcis vers les pages « Administrateurs » et « Mes appareils ».
    • 🔄 Bouton « Actualiser ».

    4. Page « Jeux » — le catalogue des jeux

    Permission games.edit — propriétaires, administrateurs et éditeurs.

    Les informations d'affichage des jeux se modifient désormais sans recompiler ni republier le launcher. Les jeux restent déclarés dans launcher.json : le serveur ne peut ni ajouter ni retirer un jeu.

    Ce qui est modifiable

    Launcher Par jeu
    Nom du launcher Nom affiché
    Jeu affiché au premier lancement Accroche
    Ordre des jeux (↑ ↓) Description (texte long : 2000 caractères / 40 lignes)
    Liens (Discord, YouTube, forum… jusqu'à 8, https)
    Site web
    Thème (thèmes intégrés uniquement)
    Icône et fond (PNG/JPEG du serveur du catalogue)
    Fréquence des recherches de mise à jour (0 ou 5 à 1440 min)
    Jeu masqué

    Ce qui reste dans l'exécutable (jamais modifiable à distance)

    launcherId, dataFolder, publisher, gameId, manifestUrl, launcherUpdateUrl, apiUrl, catalogUrl, gameDataFolder (dossiers supprimés à la désinstallation), dossier d'installation par défaut, exécutable et arguments du jeu.

    Ergonomie

    • Champ vide = valeur de launcher.json (rappelée sous le champ), pastille « modifié ».
    • Contrôle complet avant l'envoi, avec les mêmes règles que le serveur.
    • Si quelqu'un a publié entre-temps : rien n'est écrasé, la page propose de recharger (révisions).
    • Bandeau explicatif si la publication n'est pas configurée sur le serveur.
    • Nouveau (signature) : le catalogue est signé automatiquement à chaque publication.

    Règles appliquées

    48 Ko au plus · 50 jeux · noms 80 caractères · accroche 200 · adresses https uniquement (500 caractères, sans identifiants) · images .png/.jpg du même serveur que le catalogue · thème = identifiant ([a-z0-9-], jamais un chemin ni du XAML distant).


    5. Page « Notes de version »

    Permission changelog.edit — propriétaires, administrateurs et éditeurs.

    Corrige les notes des versions déjà publiées, directement dans le manifest.json du serveur.

    • 📋 Liste des versions publiées.
    • 🏷️ En-tête : titre, sous-titre, introduction.
    • 📂 Sections › éléments : modification ou commentaire, étiquette, sous-points, note.
    • ↕️ Boutons ↑ ↓ pour réordonner sections et éléments.
    • 👁️ Aperçu en direct avec exactement la présentation du launcher (mêmes modèles, mêmes limites).
    • Une ancienne version au format « liste à plat » est présentée en sections et enregistrée au format enrichi (la liste à plat est régénérée pour les anciens launchers).
    • « Enregistrer » ne change que les notes : fichiers, archive, version et exécutable restent identiques.
    • Si le manifest a changé entre-temps (nouvelle version publiée, autre administrateur) : rien n'est écrasé, rechargement proposé.
    • Limites vérifiées avant l'envoi, sans rien tronquer en silence.

    ManifestBuilder : --remote-manifest

    • Nouvelle option --remote-manifest <url> (ajoutée à tools\publish-example.bat) : l'historique des notes est repris du manifest en ligne, seule la nouvelle version vient de notes.txt.
      ➡️ Les corrections faites depuis le menu d'administration ne sont plus perdues à la publication suivante.
    • 404 = première publication (historique local) ; toute autre erreur arrête la publication.
    • Republier une version sans --notes conserve ses notes existantes.

    6. Page « Publier une version »

    Permission releases.publish — propriétaires et administrateurs.

    Publie une nouvelle version du jeu depuis le launcher, à partir du dossier produit par le .bat (ManifestBuilder, qui reste l'outil de génération).

    Déroulement

    1. Choix du manifest.json produit par le .bat.
    2. Contrôle local du dossier : manifest valide, archive et objets présents avec la bonne taille, chemins sûrs (mêmes règles que le serveur).
    3. Version en ligne rappelée, avec avertissement si le numéro est identique ou inférieur.
    4. Envoi intelligent :
      • le manifest, contrôlé par le serveur, qui répond avec la liste des fichiers absents de son dossier objects/ ;
      • uniquement ces fichiers : petits fichiers par lots (des centaines par requête), gros fichiers par morceaux ;
      • l'archive ZIP par morceaux de 4 Mo.
    5. Mise en ligne : manifest.json en dernier, remplacé atomiquement. L'historique des notes du serveur est conservé.

    Fiabilité

    • 🔁 Reprise : « Interrompre » garde ce qui a été reçu, « Publier » reprend à la position exacte.
    • 📶 Coupures réseau, délais, serveur occupé : l'état est relu sur le serveur et l'envoi continue automatiquement après une courte pause affichée sur la page.
    • 🔐 Chaque fichier est vérifié par SHA-256 des deux côtés ; un fichier modifié depuis le .bat est refusé.
    • 💾 Espace disque vérifié par le serveur avant d'accepter les fichiers.
    • ↩️ Si l'écriture du manifest échoue, l'ancienne archive est remise en place.
    • 🛑 Si les fichiers en ligne ont changé pendant l'envoi (autre publication, WinSCP), la mise en ligne est refusée (une simple correction des notes reste permise).
    • 📬 Réponse perdue : le serveur garde le résultat 24 h, un nouvel essai le retrouve.
    • 👥 Une publication à la fois par jeu ; celle d'un autre administrateur n'est remplaçable qu'après 30 min sans envoi ; abandon automatique après 48 h.
    • ✍️ Nouveau (signature) : la version est signée juste avant la mise en ligne (la reprise n'est pas affectée ; signature refaite si la mise en ligne est retentée plus de 5 minutes après).
    • ✍️ « Signer la version en ligne » : pour une version déjà en ligne (envoyée avec WinSCP ou avant la 2.0.0), depuis son dossier ; accepté uniquement si les fichiers en ligne sont identiques à ceux du dossier.

    7. Pages « Mes appareils », « Administrateurs » et « Journal d'audit »

    💻 Mes appareils — tout administrateur

    • Liste de vos PC (clés) avec leur empreinte, leur date d'ajout et leur dernière connexion.
    • Nouveau : l'empreinte de l'appareil en cours est calculée sur votre PC (pas annoncée par le serveur) ; une différence avec celle du serveur est signalée.
    • « Ajouter un appareil » : crée une invitation « nouvel appareil » (code affiché une seule fois). Sur le nouveau PC : « J'ai une invitation ». De retour ici : l'appareil en attente s'approuve en saisissant l'empreinte affichée sur le nouveau PC.
    • Personne d'autre, pas même un propriétaire, ne peut ajouter un appareil à votre compte.
    • Suppression de vos propres invitations « nouvel appareil ».
    • Révocation d'un appareil perdu : propriétaires.

    👥 Administrateurs — propriétaires (admins.manage)

    • Comptes en attente d'abord, puis actifs (vous en premier), les révoqués sur demande.
    • Inviter : nom + rôle → code d'invitation à usage unique (160 bits, valable 24 h), affiché une seule fois, copiable ; « J'ai transmis le code » l'efface de l'écran. Le code n'est jamais enregistré par le launcher.
    • Approuver un premier appareil en saisissant l'empreinte dictée par la personne (format contrôlé localement, comparaison en temps constant par le serveur ; l'empreinte d'une clé en attente n'est jamais affichée : l'approbation prouve la vérification).
    • Changer un rôle (confirmation renforcée pour « Propriétaire »).
    • Révoquer un appareil ou un compte (effet immédiat).
    • Supprimer une invitation.
    • Garde-fous : impossible de changer son propre rôle, de se révoquer, de révoquer la clé de la session en cours, ou de retirer le dernier propriétaire actif.

    🎭 Rôles

    Permission 👑 Propriétaire 🛠️ Administrateur ✏️ Éditeur
    Gérer les administrateurs et la signature (admins.manage) ✅
    Lire le journal d'audit (audit.read) ✅ ✅
    Modifier les jeux (games.edit) ✅ ✅ ✅
    Modifier les notes de version (changelog.edit) ✅ ✅ ✅
    Publier une version (releases.publish) ✅ ✅

    📜 Journal d'audit — propriétaires et administrateurs (audit.read)

    • Connexions, invitations, approbations, publications, modifications et refus, les plus récents d'abord.
    • Chargement par pages de 200 entrées (5 000 au plus en mémoire).
    • Filtres : catégorie, résultat, texte libre (nom, IP, clé…).
    • Export CSV des entrées filtrées, protégé contre l'injection de formules dans les tableurs.
    📋 Actions inscrites au journal
    Catégorie Actions
    Connexion auth.login, auth.logout, request.signature (requête signée refusée)
    Administrateurs admins.invite, admins.invite_deleted, admins.enroll, admins.key_approve, admins.key_revoke, admins.role, admins.revoke
    Ligne de commande (VPS) cli.add_owner, cli.add_key, cli.revoke_key, cli.revoke_admin
    Contenu catalog.publish, changelog.edit
    Publication release.start, release.publish, release.cancel, release.sign
    Signature keyring.publish (clés ajoutées / retirées)

    Les échecs sans signature valide sont détaillés 10 fois par minute au plus, puis résumés (protection contre l'inondation du journal) ; les échecs avec signature valide (clé révoquée, rejeu…) sont toujours détaillés.


    8. Page « Signature » et signature de bout en bout

    🛡️ Pourquoi ? Sans signature, quelqu'un qui prendrait le contrôle du VPS pourrait distribuer un faux jeu. Désormais, chaque version et le catalogue portent la signature de l'administrateur qui les a publiés, et les launchers ne font confiance qu'aux clés d'un trousseau signé hors ligne. Le VPS ne détient aucune clé privée.

    🔗 Chaîne de confiance

    Clé racine (hors ligne, celle des mises à jour du launcher)
       └─ signe ──► Trousseau keyring.json (clés autorisées + autorisations)
                       └─ autorise ──► Clés des administrateurs
                                          └─ signent ──► manifest.json de chaque version + catalog.json
                                                            └─ vérifiés par ──► Launcher des joueurs
    

    ✍️ Page « Signature » — propriétaires

    • Trousseau publié : numéro, date, nombre de clés, signature racine vérifiée par ce launcher, adresse à mettre dans launcher.json.
    • Trousseau proposé : calculé à partir des appareils actifs des comptes autorisés à publier, avec les différences (à ajouter, à retirer, autorisations modifiées).
      • autorisation « versions du jeu » si le rôle peut publier une version ;
      • autorisation « catalogue » s'il peut modifier les jeux.
    • État de chaque contenu en ligne (versions, catalogue) : signé ou non, par qui, valide ou non pour les launchers, et alerte si un contenu deviendrait invalide avec le trousseau proposé (à re-signer d'abord).
    • « Exporter la demande… » → fichier à signer hors ligne (possible aussi quand le trousseau publié est refusé, pour le remplacer).
    • « Publier le trousseau signé… » : signature racine et numéro vérifiés avant l'envoi ; le serveur exige un numéro strictement croissant.
    • Les noms d'appareils sont nettoyés (caractères invisibles, inversion du sens d'écriture) et la page rappelle qu'ils sont publics.

    🧰 tools\sign-keyring.bat — signature hors ligne

    • Glisser la demande sur le .bat : la demande est comparée au trousseau signé précédent (keyring-N.json du même dossier) ; chaque NOUVELLE CLÉ ou autorisation élargie est signalée en couleur.
    • Rappel de vérifier ces empreintes hors du serveur (de vive voix, avec la page « Mes appareils » de chaque personne).
    • Confirmation, phrase de passe de la clé racine, puis écriture de keyring-N.json (à garder : il sert de référence la fois suivante).
    • Refuse une clé racine absente de update-signing.pub.

    🎮 Côté joueur — contentSigning

    Mode Comportement
    off Rien n'est vérifié (comportement 1.x, par défaut sans keyringUrl)
    warn Signatures vérifiées, problèmes inscrits au journal, contenu utilisé (mise en place)
    require Contenu non signé, mal signé ou plus ancien que le dernier vu refusé

    En mode require :

    • 🚫 Manifest refusé → message « Mise à jour bloquée par sécurité » : aucune installation ni mise à jour, le jeu installé reste jouable.
    • 🚫 Catalogue refusé → ignoré, le cache précédent est conservé.
    • ⏪ Anti-retour en arrière : un contenu signé plus tôt que le dernier accepté est refusé (un serveur compromis ne peut pas resservir une ancienne version vulnérable).
    • 🔍 Le catalogue en cache est revérifié à chaque démarrage, hors ligne.
    • 🔤 Un catalogue dont deux jeux ne diffèrent que par la casse est refusé, même signé.

    Trousseau côté joueur :

    • téléchargé au démarrage, vérifié avec la clé racine, mis en cache ;
    • refusé s'il est plus ancien que le dernier vu, différent sous le même numéro, ou plus ancien que keyringMinSequence ;
    • hors ligne ou en cas d'erreur : le dernier trousseau vu est utilisé (aucune erreur ne fait planter le launcher) ;
    • contenu signé par une clé inconnue : nouveau téléchargement du trousseau (au plus une fois toutes les 5 minutes) ;
    • date de signature retenue plafonnée à « maintenant + 1 jour » (une horloge déréglée ne bloque pas les versions suivantes).

    🧾 Ce qui est signé

    Contenu Couvert par la signature Non couvert
    manifest.json Jeu, version, exécutable, arguments, archive (adresse, taille, SHA-256), base des objets, liste des fichiers (chemin, taille, SHA-256) Notes de version et date (corrigeables en ligne, jamais exécutées)
    catalog.json Tout le contenu affiché (textes, liens, thèmes, images référencées, ordre) Révision et date (posées par le serveur) ; le contenu des images

    La signature est intégrée au JSON (propriété signature) : les launchers 1.x l'ignorent et continuent de fonctionner.


    9. Nouveautés pour les joueurs

    • 📖 Fiche du jeu enrichie : description et boutons de liens (site, Discord, vidéo, forum… avec icônes).
    • 🎨 Nom affiché, accroche, thème, icône, fond et ordre des jeux mis à jour depuis le serveur, sans nouvelle version du launcher.
    • ⚡ Démarrage sans attente : le catalogue en cache est appliqué immédiatement ; la version à jour est téléchargée en parallèle et appliquée si elle arrive en 2,5 s (sinon au démarrage suivant).
    • 📴 Hors ligne : dernier catalogue en cache, sinon les valeurs de launcher.json.
    • 🖼️ Images contrôlées (vrai PNG/JPEG, 4 Mo max.), mises en cache, fonds réduits à 3840 px.
    • 🧱 Le nom affiché ne change ni le raccourci, ni le registre, ni les dossiers.
    • 👁️ Un jeu masqué reste affiché s'il est installé ou demandé par un raccourci ; au moins un jeu est toujours affiché.
    • ✍️ Vérification des signatures (voir §8), activable progressivement (warn puis require).

    10. Launcher API (serveur)

    Nouveau serveur ASP.NET Core (.NET 8), publié en Linux x64 autonome, derrière nginx sur le VPS.

    🧩 Modules serveur

    Module Rôle
    System Informations, santé
    Auth Défi, connexion, session, déconnexion, enrôlement
    Admins Administrateurs, clés, invitations, rôles, révocations, « mon compte »
    Audit Journal d'audit
    Catalog Lecture et publication de catalog.json
    Changelog Notes de version dans le manifest publié
    Publishing Envoi par morceaux, reprise, mise en ligne
    Signing Trousseau, état et signature des contenus
    🛣️ Routes de l'API (/api/v1/…)
    Méthode Route Droit
    GET info, health public
    POST auth/challenge, auth/login public (limité)
    POST / GET auth/logout, auth/me connecté
    POST enrollment code d'invitation
    GET admins, admins/invitations admins.manage
    GET admins/me connecté
    POST / DELETE admins/invitations, admins/invitations/{id} connecté ; admins.manage sauf invitation « nouvel appareil » pour soi (droit revérifié)
    POST admins/{id}/keys/{keyId}/approve propriétaire (premier appareil) ou titulaire du compte (nouvel appareil)
    POST admins/{id}/keys/{keyId}/revoke, admins/{id}/role, admins/{id}/revoke admins.manage
    GET audit audit.read
    GET / PUT catalog connecté / games.edit
    GET / PUT games/{gameId}/changelog, …/changelog/{version} connecté / changelog.edit
    POST games/{gameId}/publications releases.publish
    GET / DELETE publications/{id} releases.publish
    PUT publications/{id}/manifest, publications/{id}/archive, publications/{id}/objects/{sha256} (morceaux) releases.publish
    POST publications/{id}/objects (petits fichiers par lots), publications/{id}/commit releases.publish
    GET signing admins.manage
    PUT keyring admins.manage
    GET / POST games/{gameId}/signature releases.publish

    Toutes les routes qui modifient quelque chose exigent une requête signée.

    💾 Stockage

    • Aucune base de données : fichiers JSON écrits atomiquement (fichier temporaire puis renommage), verrou inter-processus, sauvegarde de la version précédente.
    • Données privées dans /var/lib/launcher-api (droits 700), hors du chroot SFTP.
    • Le serveur ne stocke que des clés publiques et des empreintes de codes d'invitation : une fuite complète de ses données ne permet pas de se connecter.
    • Historiques : 20 dernières versions du catalogue, 20 derniers manifests modifiés, historique des trousseaux.
    • Fichiers publics (catalogue, trousseau) écrits en 0644, atomiquement, malgré UMask=0077.

    🚦 Limites

    Limite Valeur
    Requêtes générales 300 / min par IP
    Connexion 20 / min par IP
    Morceaux de publication 1500 / min par IP (limite dédiée)
    Taille des requêtes 64 Ko (8 Mo pour les routes d'envoi)
    Sessions 20 min d'inactivité, 8 h max., 5 par administrateur
    Horloge des requêtes signées ± 2 min
    Date des signatures de contenu ± 10 min de l'heure du serveur

    Chaque refus 429 annonce son délai (Retry-After). Les limites par IP regroupent les adresses IPv6 par /64.

    🧯 Récupération en ligne de commande (sur le VPS)

    sudo -u deploy /opt/launcher-api/GameLauncher.Server add-owner   --name "Nom" --public-key /tmp/owner.pub
    sudo -u deploy /opt/launcher-api/GameLauncher.Server add-key     …   # restaurer l'accès d'un compte sans appareil
    sudo -u deploy /opt/launcher-api/GameLauncher.Server list
    sudo -u deploy /opt/launcher-api/GameLauncher.Server revoke-key  …
    sudo -u deploy /opt/launcher-api/GameLauncher.Server revoke-admin …
    sudo -u deploy /opt/launcher-api/GameLauncher.Server server-id
    

    Une révocation en ligne de commande prend effet immédiatement, y compris sur les sessions ouvertes.


    11. Sécurité

    Principe fondamental : le launcher est distribué à tous les joueurs, tout ce qu'il contient est public. Le serveur est la seule barrière de sécurité, et le serveur lui-même ne peut pas distribuer de contenu sans la signature d'un administrateur.

    Menace Défense
    Vol du mot de passe / hameçonnage Aucun mot de passe : clé privée sur le PC (fichier chiffré ou puce TPM)
    Force brute, saturation Limites par IP (nginx + ASP.NET Core), défis sans état, sessions bornées
    Énumération des clés Défi identique pour une clé connue ou inconnue, erreurs génériques
    Rejeu Défi à usage unique (60 s), nonce + horodatage des requêtes signées
    Vol du jeton de session Inutile pour modifier (requêtes signées), courte durée, lié à la clé
    Fuite des données du serveur Uniquement des clés publiques et des empreintes
    Serveur compromis qui distribue un faux jeu Signature de bout en bout (§8), clé racine hors ligne
    Serveur compromis qui ressert une ancienne version Anti-retour en arrière (date de signature, numéro du trousseau)
    Serveur compromis qui glisse sa clé dans le trousseau Comparaison au trousseau précédent par sign-keyring, empreintes vérifiées hors du serveur
    Clé d'administrateur compromise Révocation, nouveau trousseau, keyringMinSequence
    Usurpation par un autre administrateur Un nouvel appareil n'est approuvé que par le titulaire du compte
    Erreur de manipulation Impossible de se révoquer, de changer son propre rôle, de retirer le dernier propriétaire
    launcher.json modifié à côté de l'exe apiUrl, catalogUrl, keyringUrl, contentSigning, keyringMinSequence lus uniquement dans l'exe (Release)
    Thème ou contenu distant malveillant Thèmes intégrés uniquement, valeurs bornées, images contrôlées, même hôte
    Export CSV piégé Toutes les cellules entre guillemets, formules neutralisées
    En-têtes falsifiés X-Forwarded-* acceptés uniquement depuis 127.0.0.1, HTTPS exigé
    Compromission du compte SFTP Données de l'API hors du chroot SFTP

    12. Déploiement sur le VPS

    Guide complet pas à pas : server/deploy/LISEZMOI.md.

    • 📦 installer-api.sh : installation et mise à jour vérifiées par empreinte SHA-256, binaires appartenant à root (le service ne peut pas les modifier), réglages du VPS conservés, retour automatique à la version précédente si le démarrage échoue.
    • 🛡️ Service systemd durci (launcher-api.service) : compte deploy, UMask=0077, NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, PrivateDevices, RestrictSUIDSGID, RestrictNamespaces, CapabilityBoundingSet= vide, IPAddressAllow=localhost uniquement, MemoryMax=512M…
    • ✍️ Écriture autorisée uniquement dans les dossiers nécessaires, par compléments systemd séparés : launcher-api-catalog.conf (catalogue et trousseau), launcher-api-games.conf (dossier du jeu).
    • 🌐 nginx : nginx-api.conf (API, limites), nginx-catalog.conf (catalog.json et keyring.json sans cache), nginx-publications.conf (routes d'envoi 8 Mo, zone publication_par_ip).
    • 🗂️ Dossier objects/ et ses 256 sous-dossiers créés en 2750 (bit setgid, groupe www-data).

    Étapes du guide : 3 bis (catalogue) · 3 ter (notes de version) · 3 quater (publication) · 3 quinquies (signature) · 4 (clé d'administrateur) · 8 (mise à jour du serveur).


    13. Outils

    Outil Usage
    tools\publish-server.bat Publie le serveur (Linux x64 autonome) + empreinte SHA-256
    tools\admin-key.bat (AdminKeyTool) Ligne de commande : create, fingerprint, login-test, enroll, admins, invite, approve, role, revoke-key, revoke-admin, audit
    tools\sign-keyring.bat (LauncherPublisher sign-keyring) Nouveau : signe le trousseau avec la clé racine, hors ligne
    tools\publish-example.bat (ManifestBuilder) Option --remote-manifest : reprend l'historique des notes en ligne

    14. Configuration : nouvelles clés de launcher.json

    Toutes facultatives. En Release, elles ne sont lues que dans le launcher.json intégré à l'exécutable.

    Clé Exemple Rôle
    apiUrl "https://…/api/" Adresse de la Launcher API (sans elle : pas de menu d'administration)
    catalogUrl "https://…/catalog/catalog.json" Catalogue des jeux
    keyringUrl "https://…/catalog/keyring.json" Trousseau des clés autorisées
    contentSigning "warn" / "require" / "off" Vérification des signatures (défaut : warn si keyringUrl est présent, sinon off)
    keyringMinSequence 1 Numéro minimal du trousseau accepté (à relever après le retrait d'une clé compromise)

    Par jeu, nouvelles valeurs par défaut possibles : description, links, icon, background, hidden.


    15. Corrections et stabilisation

    Corrigé pendant le développement de la 2.0.0, avant sa sortie :

    • 🐛 Publication : erreur « Le thread appelant ne peut pas accéder à cet objet… » au clic sur « Publier » — l'avancement et les boutons sont désormais toujours mis à jour sur le fil de l'interface.
    • 🐛 Publication : le bandeau « L'envoi de la version … a été interrompu » s'affichait pendant un envoi normal — il n'apparaît plus qu'une fois l'envoi réellement arrêté.
    • 🐛 Publication : pauses de plusieurs dizaines de secondes pendant l'envoi — limite de requêtes dédiée aux envois, délai Retry-After respecté, pauses courtes (1 s doublée, 30 s max.), zone nginx dédiée.
    • 🐛 Publication : échec de la mise en ligne (« pas les droits ou plus de place ») sous systemd — les dossiers objects/xx sont créés sans demander le bit setgid (refusé par RestrictSUIDSGID), et le guide les fait créer à l'avance.
    • 🐛 Administration : erreurs du travail en arrière-plan correctement remontées (hors de Task.Run).
    • 🐛 Journal d'audit : le nom et le rôle de l'invitation supprimée sont désormais inscrits.
    • 🔒 Signature (relecture de sécurité) : identifiants du catalogue sans mise en minuscules dans le condensé, membres null sans exception, noms d'appareils trompeurs refusés, téléchargement du trousseau qui ne lève jamais d'exception, keyringMinSequence, revérification du cache, clé racine refusée à la connexion, empreinte locale sur « Mes appareils ».

    16. Architecture technique

    🏗️ Nouveaux projets de la solution
    Projet Cible Rôle
    src/GameLauncher.Contracts net8.0 Protocole partagé launcher ⇄ serveur : routes, DTO, rôles, messages signés, catalogue, notes de version, publication, signature
    src/GameLauncher.ApiClient net8.0 Client HTTP de l'API (défi signé, requêtes signées, fichier de clé chiffré)
    src/GameLauncher.Modules net8.0 Socle des modules, sans WPF : ILauncherModule, registre, pages, boîtes de dialogue, MVVM
    src/GameLauncher.Modules.Admin net8.0 Module « Administration » : services et ViewModels, testés sans interface
    server/GameLauncher.Server net8.0 (ASP.NET Core) Launcher API : modules, authentification, audit, ligne de commande
    tools/AdminKeyTool net8.0 Clé d'administrateur et administration en ligne de commande
    tests/GameLauncher.Tests net8.0 (xUnit) Tests unitaires et de bout en bout
    • Socle modulaire : le menu d'administration est le premier module ; les futures fonctionnalités « à la Steam » (actualités, amis, succès, sauvegardes dans le cloud…) s'y brancheront de la même façon, côté launcher et côté serveur.
    • Ajouter une page : une classe AdminPanelViewModel + son descripteur + son DataTemplate. La fenêtre d'administration ne change pas.
    • Aucun paquet NuGet supplémentaire hors du projet de tests.

    Documentation : docs/ADMIN-ARCHITECTURE.md (architecture, sécurité, décisions), README.md §8, server/deploy/LISEZMOI.md.


    17. Mise à niveau depuis 1.x

    ⚠️ Aucune action n'est requise pour les joueurs. Sans les nouvelles clés dans launcher.json, le launcher 2.0.0 se comporte comme la 1.x.

    Pour activer l'administration :

    • Installer la Launcher API sur le VPS (LISEZMOI.md, étapes 1 à 3) et créer le premier propriétaire (add-owner).
    • Ajouter apiUrl à launcher.json, recompiler et publier le launcher.
    • Activer les pages une à une : catalogue (3 bis), notes de version (3 ter), publication (3 quater).
    • Inviter les autres administrateurs depuis la page « Administrateurs ».

    Pour activer la signature (LISEZMOI.md, étape 3 quinquies) :

    • Mettre à jour le serveur et ajouter le bloc keyring.json à nginx.
    • Page « Signature » › exporter la demande › tools\sign-keyring.bat › publier le trousseau signé.
    • Signer la version en ligne (page « Publier une version ») et republier le catalogue (page « Jeux »).
    • launcher.json : keyringUrl + "contentSigning": "warn" + "keyringMinSequence": 1, publier le launcher, vérifier le journal.
    • Puis "contentSigning": "require" ; en option, LauncherApi:ContentSigning:Require sur le serveur.

    18. Limites connues

    • 🖼️ Le contenu des images du catalogue n'est pas signé (un serveur compromis pourrait les remplacer, pas les textes ni les liens).
    • 🗝️ Un launcher qui n'a encore jamais vu de trousseau accepte tout trousseau signé par la racine dont le numéro atteint keyringMinSequence.
    • ➕ Un appareil ajouté au trousseau pendant qu'un launcher tourne est connu au plus tard 5 minutes après, ou au démarrage suivant.
    • 🧹 Retirer une clé du trousseau invalide le contenu qu'elle a signé (la page « Signature » le signale : re-signer d'abord).
    • 🛡️ Clé TPM : non sauvegardable ; le serveur ne peut pas prouver qu'une clé est dans une puce (protection pour l'administrateur, pas une règle du serveur) ; le blocage anti-essais est commun à toute la puce (il compte aussi les codes PIN Windows Hello).
    • 📝 La création d'une nouvelle version et de ses notes se fait toujours avec le .bat (ManifestBuilder) ; le menu publie et corrige.
    • 🔁 Un redémarrage du service déconnecte tous les administrateurs (sessions en mémoire).

    What's Changed

    • Dev/2.0.0 in #114
    • Admin/phase7 in #113

    Contributors

    Full Changelog: v1.3.0...v2.0.0

    Downloads
  • v1.3.0 e8e08f792e

    nicolas released this 2026-10-25 12:09:43 +01:00 | 238 commits to master since this release

    🚀 Launcher 1.3.0

    Un bouton pour créer le raccourci du jeu avec sa propre icône, des dossiers du launcher et du jeu regroupés sous LanisysGames, et une désinstallation vraiment complète — sans jamais emporter le launcher.


    ✨ Nouveautés

    🖱️ Raccourci du Bureau

    • Nouveau bloc « Raccourci » dans menu « … » › Paramètres du jeu : Créer le raccourci, ou Mettre à jour s'il existe déjà (retrouvé même renommé).
    • Icône du jeu sur le raccourci (lue dans l'exécutable du jeu, emplacement pris dans le registre), au lieu de celle du launcher.
      • les raccourcis existants prennent l'icône du jeu au démarrage du launcher ;
      • l'icône suit le jeu s'il change de dossier (localisation, réparation) ;
      • une icône personnalisée par le joueur est conservée.

    📂 Données du jeu — Paramètres du jeu › Informations

    Bouton Ouvre
    Ouvrir le dossier des journaux %USERPROFILE%\AppData\LocalLow\LanisysGames\Exovival Zombie Reborn (Player.log)
    Ouvrir le dossier des données (nouveau) %APPDATA%\LanisysGames\Exovival Zombie Reborn (sauvegardes, réglages)

    Nouveau réglage facultatif launcher.json → "gameDataFolder" (« Société\Produit » de Unity, par défaut publisher\gameName).


    🗂️ Dossiers et registre du launcher

    Avant (≤ 1.2.1) Maintenant
    Données %APPDATA%\LanisysGames\EZRLauncher %APPDATA%\LanisysGames\GameLauncher
    Paramètres d'un jeu …\EZRLauncher\settings.json …\GameLauncher\Games\EZR\settings.json
    Registre du jeu HKCU\Software\LanisysGames\EZR HKCU\Software\LanisysGames\GameLauncher\Games\EZR
    LauncherPath dans la clé de chaque jeu une seule fois, à la racine …\GameLauncher
    • 🔄 Déplacement automatique au démarrage (renommage du dossier ; copie vérifiée puis suppression de l'ancienne clé).
    • 🛡️ Jamais pendant le redémarrage qui suit une mise à jour du launcher (retour arrière possible), ni si un autre launcher est ouvert : l'ancien emplacement sert pour la session, déplacement au démarrage suivant.
    • Nouveau réglage facultatif launcher.json → "dataFolder" ("GameLauncher" par défaut), indépendant de launcherId (identifiant de produit inchangé).

    🧹 Désinstallation

    • « Supprimer aussi les sauvegardes, les réglages, les journaux et tous les autres fichiers du jeu » supprime désormais aussi :
      Élément Emplacement
      Sauvegardes et réglages %APPDATA%\LanisysGames\Exovival Zombie Reborn
      Journaux de Unity AppData\LocalLow\LanisysGames\Exovival Zombie Reborn
      Réglages d'affichage Unity HKCU\Software\LanisysGames\Exovival Zombie Reborn
    • Option proposée aussi quand les fichiers du jeu ont déjà disparu.
    • 🧷 Le launcher n'est jamais supprimé, même placé dans le dossier du jeu ou dans celui des sauvegardes / journaux : signalé dans la confirmation, épargné (exe, launcher.json, fichiers de mise à jour, DLL en développement), emplacement indiqué à la fin.
    • 🔓 Fichier bloqué (jeu mal fermé, antivirus…) : la désinstallation ne s'interrompt plus ; suppression fichier par fichier, fichiers restants signalés (bandeau + journal), registre / raccourci / données traités ensuite.

    🔒 Sécurité

    • Seul le launcher réellement ouvert écrit dans le registre (LauncherPath, bouton « Désinstaller » de Windows) : un second launcher (« Le launcher est déjà ouvert » ou raccourci transmis) n'écrase rien.
    • Garde-fous de suppression : chemin « Société\Produit » complet uniquement ; jamais le dossier ni la clé GameLauncher, ni le dossier d'installation ; dossier / clé LanisysGames retirés seulement s'ils sont vides.
    • gameDataFolder / dataFolder validés (pas de lecteur, pas de ..).
    • Inchangé : signature ECDSA P-256 de launcher-update.json, vérification SHA-256 de l'exécutable, pas de rétrogradation.

    ⚠️ À savoir

    • 🎮 Les sauvegardes passent dans Roaming côté jeu à partir d'Exovival Zombie Reborn 1.5.1 (déplacement automatique depuis LocalLow au premier lancement). Avec une version antérieure du jeu, « Ouvrir le dossier des données » reste grisé.
    • 🔁 Après la mise à jour automatique depuis la 1.2.1, le déplacement des données du launcher a lieu au démarrage suivant.

    🛠️ Détail des modifications
    Fichier Modification
    GameLauncher.Core/Utils/LauncherSelfFiles.cs Nouveau — fichiers du launcher à conserver, test « dans ce dossier »
    GameLauncher.Core/Utils/FileUtil.cs DeleteDirectoryContents (suppression commune, launcher épargné, fichiers bloqués tolérés), TryRemoveEmptyDirectory, AllFiles
    GameLauncher.Core/Services/GameInstaller.cs Désinstallation fichier par fichier, fichiers du launcher conservés
    GameLauncher.Core/Models/OperationProgress.cs UninstallResult : fichiers bloqués, fichiers du launcher conservés
    GameLauncher.Core/Models/LauncherCatalog.cs dataFolder, dossier GameLauncher, Games\<GameId>, déplacement depuis EZRLauncher
    GameLauncher.Core/Models/LauncherConfig.cs gameDataFolder, dossiers des données (Roaming) et des journaux (LocalLow) du jeu
    GameLauncher.Core/Models/LauncherSettings.cs, LauncherPreferences.cs, SelfUpdate/SelfUpdateSettings.cs Nouveaux emplacements
    Services/RegistryService.cs Clé GameLauncher\Games\<GameId>, LauncherPath unique, déplacement de l'ancienne clé, écriture réservée au launcher ouvert, réglages Unity supprimés avec l'option
    Services/ShortcutService.cs Icône du jeu, mise à jour des raccourcis existants, actualisation de l'Explorateur
    Services/Interfaces.cs DesktopShortcut.IconLocation, CreateDesktopShortcut() → bool, DeleteGameUserSettings()
    ViewModels/GameSettingsViewModel.cs, Views/SettingsWindow.xaml Blocs « Raccourci » et boutons journaux / données
    ViewModels/GameViewModel.cs Raccourci, chemins des données, désinstallation (données du jeu, launcher conservé, fichiers bloqués)
    App.xaml.cs Déplacement des données au démarrage, registre réservé au launcher ouvert
    launcher.json, launcher.multi-jeux.example.json gameDataFolder, dataFolder
    README.md, tools/notes-launcher.txt Documentation, notes 1.3.0
    📜 Commits
    • Raccourci du Bureau : bouton dans les paramètres du jeu + icône du jeu
    • Données du jeu : dossiers des journaux (LocalLow) et des données (Roaming)
    • Données du launcher : dossier et registre « GameLauncher »
    • Notes de version du jeu 1.5.1 : sauvegardes et réglages dans Roaming
    • Désinstallation : « Supprimer aussi… » supprime les données du jeu
    • Désinstallation : mêmes sécurités pour les dossiers Roaming et LocalLow
    • Notes de version du launcher 1.3.0

    📦 Installation : les launchers des joueurs se mettent à jour automatiquement au prochain démarrage. Pour une installation manuelle, téléchargez GameLauncher-1.3.0.exe ci-dessous.

    What's Changed

    • Désinstallation : mêmes sécurités pour les dossiers Roaming et LocalLow in #87
    • Dev/1.3.0 in #86

    Contributors

    Full Changelog: v1.2.1...v1.3.0

    Downloads
  • v1.2.1 f4ebb680ef

    nicolas released this 2026-10-25 09:48:54 +01:00 | 247 commits to master since this release

    🚀 Launcher 1.2.1

    Le launcher peut maintenant se ranger discrètement près de l'horloge (zone de notification de Windows), pendant la partie ou à la place de se fermer.


    ✨ Nouveautés

    🔔 Icône dans la zone de notification

    Action Effet
    Clic gauche Le launcher réapparaît
    Clic droit Menu Ouvrir / Quitter, dans le style des menus du launcher (arrondi, icônes, couleurs du thème du jeu)

    L'icône n'apparaît que lorsque le launcher est masqué. Le menu se ferme en cliquant ailleurs, avec Échap ou après un choix, et se pilote au clavier.

    ⚙️ Deux nouvelles options — Paramètres du launcher (roue crantée)

    Option Effet
    Lancement du jeu › Réduire le launcher pendant la partie › Dans la zone de notification Pendant la partie, le launcher quitte la barre des tâches et attend près de l'horloge. Il réapparaît à la fermeture du jeu.
    Fermeture du launcher › La croix réduit le launcher dans la zone de notification La croix ✕ (et Alt+F4) masque le launcher au lieu de le quitter : téléchargements et mises à jour continuent. Pour quitter : clic droit sur l'icône › Quitter.

    ℹ️ Ces deux options sont désactivées par défaut : rien ne change pour les joueurs qui ne les activent pas.


    🛠️ Améliorations

    • 🛑 Quitter pendant un téléchargement : le launcher réapparaît et demande confirmation.
    • 🎮 L'icône du Bureau fonctionne aussi quand le launcher est caché près de l'horloge : il réapparaît et lance le jeu.
    • 💬 Le message « Le launcher est déjà ouvert » indique où le retrouver s'il est caché.
    • 🔌 À l'arrêt de Windows ou à la fermeture de session, le launcher se ferme normalement, sans rien demander.

    🔒 Sécurité

    • Inchangé : signature ECDSA P-256 de launcher-update.json, vérification SHA-256 de l'exécutable, pas de rétrogradation.
    • Icône gérée directement par l'API Windows (Shell_NotifyIcon) : aucune nouvelle dépendance (pas de Windows Forms).

    🧩 Note technique : pourquoi un menu en fenêtre ?

    Quand le launcher est masqué, aucune de ses fenêtres n'a le premier plan : un ContextMenu WPF ne peut alors pas capturer la souris et se referme dès son ouverture. Le menu est donc une petite fenêtre dédiée (Views/TrayMenuWindow) qui prend le premier plan au clic (Windows l'autorise au propriétaire de l'icône) et se ferme dès qu'elle le perd.

    🛠️ Détail des modifications
    Fichier Modification
    Platform/TrayIcon.cs Nouveau — icône de la zone de notification (clics, icône adaptée à la mise à l'échelle, redémarrage de l'Explorateur)
    Views/TrayMenuWindow.xaml(.cs) Nouveau — menu Ouvrir / Quitter
    Platform/WindowService.cs HideToTray() ; Restore() réaffiche une fenêtre masquée
    Services/Interfaces.cs, Services/GameScopedServices.cs HideToTray() dans IWindowService
    Themes/Icons.xaml Icônes WindowRestore et ExitToApp
    GameLauncher.Core/Models/LauncherPreferences.cs Réglages MinimizeToTray et CloseToTray
    ViewModels/LauncherSettingsViewModel.cs, Views/SettingsWindow.xaml Sous-option et bloc « Fermeture du launcher »
    ViewModels/LauncherViewModel.cs Croix : fermer ou masquer ; Quit() avec confirmation ; info-bulle de la croix
    ViewModels/GameViewModel.cs Réduction pendant la partie : barre des tâches ou zone de notification
    Views/MainWindow.xaml(.cs) Info-bulle de la croix ; Alt+F4 suit l'option
    App.xaml.cs Création de l'icône, fermeture à l'arrêt de Windows, raccourci qui réaffiche le launcher, message « déjà ouvert »
    README.md Section « Zone de notification »
    tools/notes-launcher.txt Notes de version 1.2.1
    📜 Commits
    • Zone de notification : icône du launcher et menu Ouvrir / Quitter
    • Zone de notification : options « pendant la partie » et « croix »
    • README : zone de notification
    • Notes de version du launcher 1.2.1
    • Version 1.2.1

    📦 Installation : les launchers des joueurs se mettent à jour automatiquement au prochain démarrage. Pour une installation manuelle, téléchargez GameLauncher-1.2.1.exe ci-dessous.

    What's Changed

    • Note de version 1.2.1 in #85
    • Dev/1.2.1 in #84

    Contributors

    Full Changelog: v1.2.0...v1.2.1

    Downloads
  • v1.2.0 a17f0efcd7

    nicolas released this 2026-10-25 00:27:55 +02:00 | 254 commits to master since this release

    🚀 Launcher 1.2.0

    L'icône du Bureau lance désormais directement le jeu, que le launcher soit fermé ou déjà ouvert, et les raccourcis suivent le launcher quand il est déplacé.


    ✨ Nouveautés

    🎮 Lancement du jeu depuis le Bureau

    Situation Comportement
    Launcher fermé Le launcher s'ouvre sur le jeu, vérifie les mises à jour puis lance le jeu s'il est prêt
    Launcher déjà ouvert Plus de message « déjà ouvert » : le launcher revient au premier plan sur le bon jeu et le lance
    Launcher ouvert sans l'icône du jeu Message « Le launcher est déjà ouvert » (inchangé)
    • ⚙️ Les réglages « Réduire le launcher pendant la partie » et « Fermer le launcher au lancement du jeu » sont respectés.
    • 🔄 Si la mise à jour automatique du jeu est activée, la nouvelle version est installée avant de jouer.
    • 📴 Hors ligne, la version installée est lancée.
    • 💬 Si le jeu ne peut pas être lancé (mise à jour manuelle, réparation, jeu non installé), le bandeau explique pourquoi.
    • 🛑 Le jeu n'est jamais lancé deux fois, même s'il a été démarré sans le launcher.

    🔧 Raccourcis réparés après un déplacement du launcher

    • Les raccourcis du jeu sont reconnus à leur argument --game <GameId>, même renommés.
    • Au démarrage : les raccourcis vers un launcher disparu sont redirigés automatiquement.
    • Bouton « Réparer » : vérifie aussi les raccourcis du Bureau et l'entrée Applications installées de Windows (fonctionne hors ligne).
      • raccourci vers une autre copie du launcher encore présente → confirmation demandée ;
      • icône personnalisée conservée.

    🔒 Sécurité

    • Communication entre instances par canal nommé local :
      • PipeOptions.CurrentUserOnly côté serveur et client ;
      • nom propre à la session Windows et au SID de l'utilisateur ;
      • un seul message, 256 octets max, 2 s max ;
      • seul un identifiant de jeu est transmis, validé puis comparé à launcher.json. Aucun chemin ni argument.
    • Canal fermé avant le redémarrage d'une mise à jour du launcher, puis recréé par la nouvelle version.
    • Inchangé : signature ECDSA P-256 de launcher-update.json, vérification SHA-256 de l'exécutable, pas de rétrogradation.

    ⚠️ À savoir

    • 🧩 Nouvel argument interne --launch (avec --updated) : après une mise à jour du launcher faite au démarrage depuis un raccourci, la nouvelle version lance le jeu. Après une mise à jour demandée depuis les paramètres, le jeu n'est pas lancé.
    • 1️⃣ La mise à jour depuis la 1.1.3 ne lancera pas le jeu après le redémarrage (la 1.1.3 ne connaît pas --launch). Cas unique, les suivantes sont gérées.
    • 📂 Un launcher.json posé à côté de l'exe doit être déplacé avec lui.

    🛠️ Détail technique des modifications
    Fichier Modification
    Services/InstanceChannel.cs Nouveau — canal entre instances (serveur + client, protocole borné)
    Services/ShortcutService.cs Recherche des raccourcis par argument, redirection, icône conservée, correction au démarrage
    Services/Interfaces.cs DesktopShortcut, IShortcutService.FindDesktopShortcuts() / RetargetDesktopShortcut() / LauncherPath, IRegistryService.RefreshLauncherPath()
    ViewModels/GameViewModel.cs Réparer contrôle les raccourcis, LaunchFromShortcut(), anti double lancement
    ViewModels/LauncherViewModel.cs LaunchFromShortcut(gameId), lancement après initialisation
    App.xaml.cs Transmission au launcher ouvert, écoute du canal, argument --launch
    README.md Section « Raccourcis du Bureau et déplacement du launcher », options de ligne de commande
    tools/notes-launcher.txt Notes de version 1.2.0
    📜 Commits
    • Raccourcis du Bureau : recherche par argument --game et redirection
    • Réparer : contrôle des raccourcis + pas de double lancement du jeu
    • Raccourci ouvert avec le launcher déjà ouvert : le jeu est lancé
    • README : raccourcis du Bureau et déplacement du launcher
    • Raccourci du Bureau : lance le jeu même si le launcher était fermé
    • Notes de version du launcher 1.2.0

    📦 Installation : les launchers des joueurs se mettent à jour automatiquement au prochain démarrage. Pour une installation manuelle, téléchargez GameLauncher-1.2.0.exe ci-dessous.

    What's Changed

    • Dev/1.2 in #82

    Contributors

    Full Changelog: v1.1.3...v1.2.0

    Downloads
  • v1.1.3 7e52faf831

    nicolas released this 2026-10-18 13:42:12 +02:00 | 265 commits to master since this release

    Launcher 1.1.3

    LAUNCHER - NOTES DE MISE À JOUR
    Mise à jour du 18 octobre 2026

    Cette version réorganise les paramètres, enrichit les notes de version et corrige le nom du launcher après une mise à jour automatique.


    PARAMÈTRES

    Les paramètres sont maintenant répartis dans deux fenêtres distinctes :

    • NOUVEAU : Paramètres du launcher, depuis la roue crantée en haut à
      droite. Ces réglages sont communs à tous les jeux :
      • mise à jour automatique du launcher et bouton « Vérifier les
        mises à jour » ;
      • réduire ou fermer le launcher pendant la partie ;
      • accès au dossier des journaux.
    • NOUVEAU : Paramètres du jeu, depuis le menu « … ». Ces réglages ne
      concernent que le jeu sélectionné :
      • mises à jour automatiques du jeu ;
      • téléchargements simultanés et vérification des fichiers après
        l'installation ;
      • informations : version installée, dernière version, taille et
        dossier du jeu.
    • Vos réglages « Lancement du jeu » sont repris automatiquement au
      premier démarrage de cette version.

    NOTES DE VERSION

    • NOUVEAU : notes de version plus lisibles, avec titre, sous-titre,
      introduction, sections, commentaires, sous-points et étiquettes.
    • NOUVEAU : bouton « Agrandir » pour lire les notes de version en
      grand.
    • NOUVEAU : les nouveautés du launcher utilisent la même présentation.
      La fenêtre de mise à jour affiche les notes de toutes les versions
      publiées depuis la vôtre.
    • Les notes reçues du serveur sont limitées en taille et nettoyées
      avant d'être affichées.

    MISE À JOUR DU LAUNCHER

    • Après une mise à jour automatique, le launcher s'appelle toujours
      GameLauncher.exe, même si le fichier avait été renommé (par exemple
      GameLauncher-1.1.2.exe, tel que publié sur le serveur).
    • Le raccourci du Bureau est réparé s'il pointait vers un launcher
      renommé ou déplacé.

    La sécurité ne change pas : la signature numérique et l'empreinte SHA-256 de chaque nouvelle version sont vérifiées avant toute installation.

    What's Changed

    • Ajout d'un module de mise à jour automatique in #1

    Contributors

    New Contributors

    Full Changelog: v1.0.0...v1.1.3

    Downloads