== Exe par-version, configurable via le backoffice == Pour éviter de devoir bumper le launcher à chaque changement d'Unreal Engine (PROSERVE_UE_5_5.exe → PROSERVE_UE_5_7.exe), l'exe à lancer est maintenant déclaré par version dans le manifest serveur, configurable depuis le form admin. - server/admin/versions.php : nouveau champ "Nom de l'exécutable" dans le form d'ajout de version (regex strict anti-path-traversal). Par défaut PROSERVE_UE_5_7.exe. - InstallationRegistry : nouveau .proserve-meta.json écrit dans chaque dossier d'install fraîchement extrait (contient l'exe declaré par le manifest). Scan() lit cette meta pour résoudre l'exe sans avoir besoin du manifest en mémoire (offline / pré-check). - Fallback glob PROSERVE_UE_*.exe pour les vieux installs sans metadata — garantit la backward compat de l'UE 5.5 actuel sans intervention. == Auto-install des redists Unreal depuis _redist/ == Quand une version change d'Unreal (typique : UE 5.5 → 5.7), les redists Microsoft VC + UEPrereqSetup doivent être installés sur le PC. Au lieu de demander à l'opérateur de les installer à la main, le launcher détecte maintenant un dossier _redist/ dans la racine du ZIP de release et lance automatiquement tous les .exe dedans. - MainViewModel.InstallRedistsAsync : après le ZipInstaller, scan _redist/ pour .exe, lance chacun avec /install /quiet /norestart + Verb=runas (UAC popup par installer, inévitable car les redists écrivent dans Program Files). Tri alphabétique (préfixe 01_, 02_, … pour forcer un ordre si besoin). - InstallationRegistry.MarkRedistInstalledAsync : trace redistInstalledAt dans .proserve-meta.json après succès. Reinstall de la même version : skip silencieux, pas de UAC popup chain. - Best-effort sur les exit codes : les "already installed" retournent souvent un code non-zero, on log mais on continue (l'install PROSERVE ne doit pas être bloquée par un redist mineur). Côté ZIP de release : crée _redist/ à la racine avec les .exe à installer (typiquement VC_redist.x64.exe + UEPrereqSetup_x64.exe). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PS_Launcher — Côté serveur
Contenu de ce dossier à uploader sous www/PS_Launcher/ sur le mutualisé OVH.
Arborescence finale après upload
www/
└── PS_Launcher/
├── .htaccess
├── api/ ← API consommée par le launcher
│ ├── config.php ← À CRÉER (copie de config.example.php)
│ ├── index.php
│ ├── lib/{Response,Db,Crypto}.php
│ └── routes/{Manifest,Releasenotes,ValidateLicense}.php
├── admin/ ← Backoffice web (auth par mot de passe)
│ ├── .htaccess
│ ├── index.php (dashboard)
│ ├── login.php / logout.php
│ ├── licenses.php / versions.php / audit.php
│ ├── lib/{Auth,Layout}.php
│ └── assets/style.css
├── manifest/versions.json
├── releasenotes/1.4.X.md
├── builds/ ← ZIPs uploadés en SFTP
├── migrations/001_init.sql ← Schéma MySQL initial
└── tools/
├── generate-keypair.php
├── issue-license.php
└── sign-manifest.php
Setup initial (à faire une fois)
1. Crée la base MySQL
Manager OVH → Hébergements → Bases de données → Créer. Note le DSN, user, password.
2. Joue le schéma
PhpMyAdmin (manager OVH) ou en SSH :
mysql -h <host> -u <user> -p <db> < www/PS_Launcher/migrations/001_init.sql
3. Configure le serveur
- Copie
api/config.example.php→api/config.php - Remplis la section
db,base_url - Génère les clés Ed25519 :
Recopie
cd ~/www/PS_Launcher php tools/generate-keypair.phpprivate_key_hexetpublic_key_hexdansapi/config.phpsectioned25519. Recopie aussipublic_key_hexdanssrc/PSLauncher.Core/Resources/server-pubkey.txtcôté projet C# et recompile le launcher.
4. Configure le mot de passe admin
php -r "echo password_hash('TonMotDePasseFort', PASSWORD_DEFAULT);"
Recopie le hash dans api/config.php → admin_password_hash.
5. Test la chaîne
https://tondomaine.com/PS_Launcher/api/health → JSON status: ok
https://tondomaine.com/PS_Launcher/admin/login.php → page de connexion admin
Workflow de release (via le backoffice)
- Connecte-toi sur
https://tondomaine.com/PS_Launcher/admin/. - Onglet Versions → formulaire « Ajouter une version » : numéro, date min de license, release notes Markdown.
- Upload le ZIP correspondant via SFTP dans
www/PS_Launcher/builds/proserve-{version}.zip. - Bouton 🔁 Sync (sign-manifest) : calcule SHA-256, met à jour
latest, signe le manifest avec Ed25519. - Au prochain « Vérifier les MAJ » côté launcher, la nouvelle version apparaît.
Workflow de release (alternative manuelle SSH)
# 1. Édite manifest/versions.json (ou utilise le backoffice)
# 2. Upload le ZIP en SFTP dans builds/
# 3. Resigne :
cd ~/www/PS_Launcher
php tools/sign-manifest.php
Émettre une license
Via le backoffice (recommandé) : onglet Licenses → formulaire « Émettre ». La clé apparaît une seule fois — copie-la pour le client.
Via SSH :
php tools/issue-license.php "ACME Corp" 2027-12-31 1
Convention du contenu du ZIP
Le client extrait le ZIP dans installRoot/Proserve v{version}/. Le ZIP peut soit contenir
un dossier racine Proserve v{version}/, soit le contenu directement — le launcher détecte
automatiquement le préfixe commun et le strippe.
Test API depuis ton poste
curl.exe https://tondomaine.com/PS_Launcher/api/health
curl.exe https://tondomaine.com/PS_Launcher/api/manifest
curl.exe https://tondomaine.com/PS_Launcher/api/releasenotes/1.4.6
Sécurité
api/config.phpest gitignored. Ne jamais le commit.- Toutes les URLs
/api/*forcent HTTPS via.htaccess. - Les routes /api/* renvoient toujours du JSON (pas de page Apache 500 HTML).
- L'admin est protégé par session + CSRF + mot de passe bcrypt.
- Les licenses sont stockées via UNIQUE en clair (pour la lookup constant-time côté serveur), mais ne sont jamais loguées en clair côté audit.
- Côté client : la clé license est chiffrée DPAPI scope CurrentUser dans
%LocalAppData%. - Les réponses serveur (manifest, validation license) sont signées Ed25519 — le launcher embarque la clé publique et refuse toute réponse mal signée.