Files
PS_Launcher/server
j.foucher 49a3b855af v0.27.0 — Channels comme TAGS sur versions (refactor du modèle)
Changement majeur du modèle de channels en réponse au feedback :
« c'est trop compliqué. Il faudrait juste pouvoir tout laisser dans
builds, et taguer une version dans un canal ou un autre voir plusieurs
canaux. ». Le précédent design (1 fichier manifest par channel +
sous-dossier builds/{channel}/) imposait une duplication de structure
et empêchait une version d'être visible sur plusieurs channels à la fois.

NOUVEAU MODÈLE :
- 1 seul fichier manifest/versions.json
- 1 seul dossier builds/ flat (les ZIPs ont des noms libres pour éviter
  les collisions homonymes — proserve-1.5.3.zip, proserve-1.5.3-police.zip…)
- Chaque entry de version a un champ `channels: ["default", "police"]`
  qui dit qui peut la voir
- Sémantique additive : un client sur channel "police" voit les versions
  taggées "default" + celles taggées "police". "default" = public.
- Une version peut être taggée sur plusieurs channels en une fois.

NOUVEAU REGISTRE channels.json :
Le registre des channels (avec name + label + description) vit dans
manifest/channels.json. Le channel "default" est implicite et ne peut
pas être supprimé. Nouvelle page admin Channels (CRUD) pour gérer la
liste, avec garde-fou anti-suppression : compte les versions taggées
et les licenses attribuées avant d'autoriser la suppression.

SERVEUR :
- api/routes/Manifest.php : reçoit ?channel=X depuis la license,
  filtre versions où channels[] contient X ou "default", re-signe avec
  la clé privée Ed25519 à la volée. Coût ~1ms par requête.
- admin/versions.php : refactor — plus de session "channel actif", plus
  de switcher en haut, plus de prefix builds/{channel}/. Add form a
  des checkboxes channels[]. Nouveau bouton "Channels" par-row pour
  retager.
- admin/licenses.php : dropdown channel alimenté depuis channels.json
  au lieu de scanner les fichiers manifest.
- tools/SignManifest.php : revert du constructeur channel-aware,
  toujours sur versions.json + builds/ flat.

CLIENT :
- VersionManifest.Channels (List<string>) ajouté pour debug, mais le
  filtrage est server-side donc le client n'a rien à faire de ce champ
  côté UX.
- L'envoi du ?channel=X depuis la license signée fonctionne déjà
  depuis v0.26.0, pas de changement nécessaire.

MIGRATION :
Les fichiers manifest/versions-{X}.json créés en v0.26.0 deviennent
inutiles. Si tu en avais (test "police" par exemple), copie les
versions concernées dans versions.json et tague-les avec les bons
channels via la nouvelle UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 08:51:10 +02:00
..

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.phpapi/config.php
  • Remplis la section db, base_url
  • Génère les clés Ed25519 :
    cd ~/www/PS_Launcher
    php tools/generate-keypair.php
    
    Recopie private_key_hex et public_key_hex dans api/config.php section ed25519. Recopie aussi public_key_hex dans src/PSLauncher.Core/Resources/server-pubkey.txt cô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.phpadmin_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)

  1. Connecte-toi sur https://tondomaine.com/PS_Launcher/admin/.
  2. Onglet Versions → formulaire « Ajouter une version » : numéro, date min de license, release notes Markdown.
  3. Upload le ZIP correspondant via SFTP dans www/PS_Launcher/builds/proserve-{version}.zip.
  4. Bouton 🔁 Sync (sign-manifest) : calcule SHA-256, met à jour latest, signe le manifest avec Ed25519.
  5. 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.php est 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.