Deux bugs UX rapportés sur v0.26.0 admin/versions.php :
1. Cliquer 'Aller' avec un nom contenant majuscules / espaces / accents
ne faisait RIEN. Cause : pattern HTML5 strict (`[a-z0-9_-]{1,64}`) qui
bloque la submission du form GET sans message visible. Selon le browser
le tooltip de validation est barely visible, donc le user a l'impression
que le bouton est cassé.
Fix : retire le pattern strict, normalise côté serveur :
« ASTERION VR » → « asterion-vr », « éàç!? » → « » (et on dit pourquoi).
Flash success qui annonce la normalisation, ou flash error si le nom
est inexploitable après nettoyage.
2. Après création d'un channel, le dropdown affichait encore '(default)'
parce que listExistingChannels() filtre sur les versions-*.json
existants et l'admin n'a pas encore ajouté de version donc le fichier
n'existe pas. Du coup l'admin pensait que la création n'avait pas
marché alors que la session était bien sur le nouveau channel.
Fix : injection forcée du channel actif dans le tableau des options du
dropdown avec label « X (vide — pas encore de versions) ».
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.