d52e29151e0dd27f5e3333b0fd85fb2d5f697507
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 73d084a703 |
v1.0.0 đ â Production release. i18n Espagnol + Allemand (launcher + emails).
PremiĂšre release MAJEURE aprĂšs ~30 itĂ©rations 0.x. Le systĂšme est complet et stable pour la production : distribution PROSERVE multi-channels, install launcher cross-fleet, monitoring santĂ© VR, sĂ©curitĂ© (signatures Ed25519, HMAC URLs prĂ©signĂ©es, settings lock per-license, RFC1918 filter cache LAN). i18n nouvelles langues (Espagnol + Allemand) : - Strings.cs : signature T() Ă©tendue avec 2 params optionnels (es?/de?) en plus des 5 obligatoires. Fallback automatique sur l'anglais quand non traduit â infrastructure prĂȘte immĂ©diatement, traduction progressive sur les ~317 strings du launcher selon les besoins terrain. - ~30 strings critiques traduites maintenant (top bar, body, status badges, actions principales Launch/Install/Cancel/Yes/No, MessageBox titles). - Available[] inclut es/Español + de/Deutsch ; auto-dĂ©tection Windows pour es-* / de-* funcionne au premier launch. - Init() whitelist mise Ă jour. Emails release announce localisĂ©s par license : - Migration 005 : ajout `language VARCHAR(8) NULL` sur licenses (whitelist fr/en/es/de/zh/th/ar, NULL = fallback English). - getEmailStrings() PHP Ă©tendu : dictionnaire 7 langues Ă 14 strings. Traduction complĂšte es + de (gĂ©rable : 28 nouvelles strings, vs 634 pour traduire le launcher en intĂ©gralitĂ©). - notify_release boucle par license : rĂ©cupĂšre language + locale fallback 'en' + render avec la bonne locale â chaque destinataire reçoit son email dans la langue de SA license, indĂ©pendamment des autres clients. - Subject localisĂ© aussi (« PROSERVE v1.5.4 ya estĂĄ disponible » / « PROSERVE v1.5.4 ist jetzt verfĂŒgbar »). - Release notes body reste TOUJOURS en anglais (Ă©vite d'avoir Ă maintenir N traductions du Markdown des notes). - Direction RTL prĂ©servĂ©e pour l'arabe (dir="rtl" sur <html> + <table>). Admin UI : dropdown langue dans la modal Contacts d'une license + whitelist backend (set_contact_emails accepte fr/en/es/de/zh/th/ar). Bumps : 0.29.10 â 1.0.0 â milestone V1, premier release majeur en prod. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 500f7d12e6 |
v0.29.10 â Admin UI refonte (modals + onglets), emails de release, 4-digit versions
Admin backoffice â UI redesign : - Pages versions.php + licenses.php : remplace les <details> inline qui dĂ©bordaient horizontalement par UN bouton « â Modifier » par row qui ouvre une modal <dialog> avec onglets. 5 tabs versions (MĂ©ta, Notes, BĂTA, Channels, AvancĂ©) + 6 tabs licenses (Prolonger, Slots, Channel, BĂTA, Lock, Contacts, Machines). DĂ©lĂ©gation JS unique pour les onglets. - Bouton đ Copier la clĂ© license dans chaque row (Clipboard API + feedback visuel â vert 1.5s). Ăvite le dĂ©tour par phpMyAdmin pour transmettre la clĂ© aux clients. - Overlay « hashing en cours » plein Ă©cran sur tous les boutons de hash (3-5 min sur OVH pour 13 Go ZIP). Spinner CSS + message contextualisĂ© par scope (bulk vs single). - Date de release passĂ©e de datetime-local Ă date (l'heure n'a pas de sens UX), avec dĂ©faut = aujourd'hui pour release_at et aujourd'hui-1an pour min_license_date (= license standard couvre les releases sur 1 an). Emails de notification release : - Migration 004 : colonne contact_emails TEXT NULL sur licenses (CSV) - Onglet « Contacts » sur la modal licenses pour saisir les emails par license (parsing tolĂ©rant : CSV, ligne par ligne, point-virgule) - Bouton « â Notifier » par version : POST notify_release filtre les licenses Ă©ligibles (channel match + min_license_date + can_see_betas pour BĂTA) et envoie un email HTML Ă chaque contact (dĂ©dup global) - Template email table-based + bgcolor (compat Outlook/Word engine), navy foncĂ© #0F172A, logo Asterion en CID embed (= affichage direct sans demande de permission Outlook), bouton download installer centrĂ© (align="center" + margin auto), release notes en <pre> - Mailer.php helper : parse emails, multipart/related avec attachments inline, fallback execCommand pour clipboard 4-digit version support (X.Y.Z.B) : - SemVer Parse/CompareTo/ToString gĂšrent 3 ou 4 digits ; Build absent = 0 implicite (1.5.4 == 1.5.4.0 < 1.5.4.13). HasExplicitBuild prĂ©serve le format d'origine au round-trip. - Regex InstallationRegistry Ă©tendue avec (?:\.\d+)? â reconnaĂźt « PROSERVE v1.5.4.13 » cĂŽte-Ă -cĂŽte avec « PROSERVE v1.5.4 » sur disque - Server-side : versions.php, launcher.php, DownloadUrl.php, api/index.php, Releasenotes.php â toutes les regex de validation acceptent le 4á” digit - Use case : dev/test iterations cohabitant avec leur release stable Bugs fixes : - migrate.php : strip ligne par ligne les commentaires SQL avant le check is-empty. Sans ça, le PREMIER chunk d'un fichier migration (= header + premier ALTER) commençait par `--` et Ă©tait silencieusement skip â ALTER jamais appliquĂ©. Affectait migrations 003, 004. - SignManifest::getOrComputeSha256 ignorait son cache interne quand force demandĂ© par le caller, retournant l'ancien hash en 0 ms mĂȘme aprĂšs re-upload SFTP (avec mtime prĂ©servĂ©). Propage maintenant le flag $force. Bouton « đ Hash » per-row force maintenant un re-calcul systĂ©matique. - DownloadManager : 416 (Range Not Satisfiable) ajoutĂ© aux URL-refresh triggers, avec HEAD probe pour comparer taille serveur vs manifest â message d'erreur explicite si ZIP tronquĂ©. Bps display lissĂ© sur une fenĂȘtre glissante de 12 samples (3 s) â plus de clignotement quand un segment finit / Polly retry. SHA mismatch popup enrichi avec les deux SHAs (attendu vs calculĂ©) extraits via regex de l'exception. - DownloadUrl.php : signature de l'URL utilisait un template hardcodĂ© /builds/proserve-{version}.zip, ignorant tout rename serveur. Lit maintenant download.url du manifest et signe le filename rĂ©el. Strings i18n (5 langues) : - ~15 nouveaux : SHA mismatch enrichi avec sources, 416 size mismatch, stale manifest, manifest refreshed auto-retry, force fresh menu Bumps : 0.29.7 â 0.29.10 (4-digit support + accumulated UI fixes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| efb53f079e |
v0.28.10 â Mode auto + settings lock par license + fix post-install state
Mode auto (auto-launch d'une version dĂ©signĂ©e au dĂ©marrage et aprĂšs exit) : - Master toggle + version dĂ©signĂ©e via bouton AUTO (orange) sur chaque row - Countdown 5 s configurable avec popup d'annulation (StartAutoLaunchCountdown) - Args CLI passĂ©s Ă PROSERVE : opĂ©rateur tape juste le nom (autoconnect, login), le launcher ajoute -/=/quotes. Format produit identique Ă un .bat. Fix : passage de ArgumentList Ă Arguments string pour Ă©viter le quotage auto .NET sur les args contenant '=' (cassait FParse::Value). - Garde-fou anti double-lancement : refuse de lancer si _runningProserve vivant OU IProcessLauncher.IsRunning() dĂ©tecte une instance externe. Silent pour les triggers auto, popup pour les clics manuels. - Option « Attendre santĂ© systĂšme » : countdown diffĂ©rĂ© tant que les health checks ne sont pas tous OK (phase 1 du dialog avec liste des pending). Settings lock par license (remplace l'ancien lock global manifest) : - Colonne settings_lock_password_hash sur table licenses (migration 003) - Backoffice : bouton đ par license pour set/clear hash SHA-256 - Payload /license/validate inclut settingsLockPasswordHash (v3 canonique) - 3-tier fallback signature : v3 â v2 â legacy pour compat cache offline - SettingsLockService : in-memory unlock state, gate l'expander AvancĂ©s - SettingsLockDialog : prompt mdp, persiste dĂ©verrouillĂ© jusqu'au restart Fix post-install : la row restait en visuel « Installing » jusqu'au prochain Check Updates. Reset explicite row.State=InstalledIdle + _activeRow=null AVANT le RebuildList post-install pour purger l'instance orpheline. Migrations : - 002_channel_betas.sql réécrit en ALTER simples (DELIMITER cassait migrate.php qui split sur ';\n') - migrate.php tolĂšre « Duplicate column/key name » comme idempotent Strings (5 langues, ~25 nouvelles) : - Renomme « Relance automatique » â « Lancement automatique » (dialog utilisĂ© pour les 3 entry points : clic, startup, post-exit) - Tooltips auto-mode, settings lock prompts, health wait phase, etc. Bumps : 0.27.4 â 0.28.10 (csproj + .iss). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| aab2e41152 |
Admin licenses : bouton BĂTA visible directement, plus dans un menu repliĂ©
Avant : pour basculer l'accĂšs BĂTA d'un client, il fallait deviner qu'il fallait cliquer sur le code <channel> dans la cellule pour ouvrir un <details> cachĂ© â pas de chevron, pas de label « modifier ». L'admin trouvait pas l'option et pensait qu'elle n'existait pas. AprĂšs : sur la page Licenses, chaque ligne affiche directement deux boutons cliquables : - « Activer BĂTA » / « â BĂTA actif » (bouton secondary / warning selon l'Ă©tat) â toggle en un clic sans menu - « â Channel » qui dĂ©plie le dropdown pour changer le channel L'Ă©tat actuel reste visible au-dessus (code du channel + badge ÎČ BĂTA si actif). Beaucoup plus discoverable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 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>
|
|||
| c371a79f93 |
v0.26.0 â Channels per-license + tag BĂTA sur versions
DEUX features liées :
1. CHANNELS : chaque license peut ĂȘtre attribuĂ©e Ă un manifest distinct
(« channel »). Permet de servir des versions différentes selon le
client. Le serveur lit ?channel=X et sert manifest/versions-{X}.json
avec fallback transparent sur versions.json. NULL = default.
2. BĂTA : nouveau flag isBeta + betaNotes par version dans le manifest.
Visible uniquement par les licenses avec can_see_betas=1. Affichage
d'une pill orange « BĂTA » sur la row + tooltip avec les notes pour
les testeurs. Les installations locales déjà présentes restent
visibles mĂȘme si l'accĂšs BĂTA est retirĂ© ensuite (on n'efface pas
le disque du client).
DB :
002_channel_betas.sql ajoute channel + can_see_betas sur licenses.
Idempotent (ALTER TABLE IF NOT EXISTS), zero data migration.
Serveur PHP :
- ValidateLicense.php signe channel + canSeeBetas dans la réponse
(ordre des clés CRITIQUE pour matcher le canonical client).
- Manifest.php : whitelist regex anti-traversal sur ?channel=, fallback
silencieux sur versions.json si channel inconnu (évite leak de la
liste de channels par probing).
- SignManifest.php prend un channel optionnel â l'admin peut signer
chaque manifest indépendamment.
- admin/licenses.php : dropdown channel + checkbox bĂȘta sur create,
bouton détails repliable par-row pour edit.
- admin/versions.php : channel switcher en tĂȘte, badge BĂTA sur chaque
row, dialog repliable « BĂȘta » avec checkbox + notes des testeurs.
Client C# :
- License.Channel + License.CanSeeBetas (dans le canonical signé).
- VersionManifest.IsBeta + BetaNotes.
- ManifestService prend un channelProvider via DI, lu depuis license
cachée à chaque fetch (lazy, pas de circular dep).
- MainViewModel.RebuildList filtre les versions IsBeta si !CanSeeBetas
(mais conserve les installĂ©es locales â on ne retire pas l'accĂšs
rétroactivement à ce qui est déjà sur disque).
- VersionRowViewModel : props IsBeta / BetaNotes / BetaTooltip.
- MainWindow.xaml : pill orange à cÎté du n° version pour le featured
et les rows compactes, tooltip dynamique avec les notes testeurs.
Backward compat signature :
Anciennes licenses cachées (signées sans channel/canSeeBetas) sont
toujours validées via un fallback canonical legacy dans VerifySignature.
Sans ce fallback, le passage Ă v0.26 invaliderait toutes les caches
hors-ligne et bloquerait les users en mobilité.
Migration cÎté admin : jouer 002_channel_betas.sql sur la base, déployer
les fichiers PHP, créer manifest/versions-{channel}.json pour les
nouveaux channels (l'admin versions.php propose un input « Créer/utiliser
un nouveau channel »). Les licenses existantes restent en channel=NULL
= default = comportement actuel.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 9de8e95910 |
v0.24.5 â Install Program Files, multi-PC DL reliability, polish UI
Installeur : - Bascule en Program Files (autopf) avec PrivilegesRequired=admin. L'auto-update reste fonctionnel : LauncherSelfUpdater dĂ©tecte le dossier protĂ©gĂ© et lance PS_Launcher.Updater.exe via Verb=runas (UAC Ă chaque MAJ). - build-installer.ps1 : dĂ©tection ISCC.exe robuste (Program Files + LocalAppData pour install winget user-mode + PATH), messages d'erreur explicites avec URL et commande winget, suppression accents (compat PS 5.1 sans BOM). TĂ©lĂ©chargements multi-PC : - DownloadManager : dĂ©tection des connexions fermĂ©es prĂ©maturĂ©ment (PHP-FPM request_terminate_timeout). Sans ça, segment marquĂ© Completed=false sans exception â fichier sparse final avec trous â SHA-256 KO. Lance maintenant HttpResumableException(transient) pour que Polly retry au bon offset. - ParallelDownloadSegments : 16 â 6 par dĂ©faut pour permettre plusieurs PCs simultanĂ©s sans saturer le pool PHP-FPM OVH (~30 workers). UI : - FenĂȘtre maximisĂ©e par dĂ©faut au dĂ©marrage (WindowState=Maximized). - Fix maximize qui cachait le footer / barre de DL (WM_GETMINMAXINFO clamp sur work area, remplace le margin hack 7px imprĂ©cis). - Sidebar : bloc info en bas avec PS_Launcher vX.Y.Z + IPv4 locale alignĂ©s. - Copyright remontĂ© plus prĂšs du footer (margin 28 â 8). - Settings â Health checks : boutons âČ/⌠pour rĂ©ordonner, CanExecute auto. - HealthCheck refresh dĂ©faut : 5000 â 2000 ms. Bug fix UI : - MainViewModel.RebuildList preserve l'Ă©tat du row actif pendant un DL. Sinon ouvrir Settings/License pendant un DL recrĂ©ait les rows from scratch â UI affichait "Reprendre" + "Annuler" alors que le DL tournait. Les progress callbacks pointent maintenant sur _activeRow (rĂ©solution dynamique) au lieu de capturer le row local. Defaults config : - ServerBaseUrl : example.com â asterionvr.com (out-of-the-box). - Vive Business Streaming check : HtcConnectionUtility â rrserver. Backoffice (server/admin/licenses.php) : - Action set_max_machines : bouton "Slots" pour ajuster max_machines Ă chaud sur une licence existante. Refus de descendre sous le nombre de machines dĂ©jĂ actives. Build : - AllowUnsafeBlocks=true sur PSLauncher.App.csproj (compat WinRT generator rĂ©cent qui Ă©met du code unsafe dans WinRTGenericInstantiation.g.cs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 48d601176d |
admin/licenses : per-machine view with individual remove
- New action `remove_machine` releasing a single (license_id, machine_id) slot. - Pre-fetches all machines in one query and groups by license_id (no N+1). - Machines column "X / Y" is now clickable: opens an inline expandable row showing each machine on that license â truncated SHA-256 ID with full hash in tooltip, machine_label, first_seen, last_seen with a "stale" warning badge for slots not seen in >30 days, plus a per-row "LibĂ©rer" button. - Existing "LibĂ©rer machines" button kept but renamed "LibĂ©rer toutes" with a beefier confirmation that hints at the per-row alternative. Replaces the all-or-nothing reset workflow with surgical control: when one user changed PCs you can free their old slot without touching their colleagues'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 92f4fd16e8 |
Backoffice: PHP admin web UI for licenses, versions, audit
Self-contained admin under /PS_Launcher/admin/ on the same OVH host. No
JS framework, no Composer deps â just PHP 8.3 + sessions + a small CSS.
Auth & infrastructure
---------------------
- admin/lib/Auth.php: session + CSRF helper. Login via password_hash /
password_verify. session_regenerate_id on successful login.
config.example.php gains admin_password_hash, generated by:
php -r "echo password_hash('PWD', PASSWORD_DEFAULT);"
- admin/lib/Layout.php: shared header/footer/nav, formatBytes,
csrfField helpers.
- admin/.htaccess: noindex / X-Frame-Options DENY / X-Content-Type
nosniff / blocks lib/*.php from web access.
- admin/assets/style.css: matches launcher's dark theme â same
Brush.* palette mapped to CSS vars, vivid green/blue/amber status
pills consistent with the WPF UI.
Pages
-----
- index.php (Dashboard): KPIs (active/expired/revoked licenses, machines
seen 30d, validations 24h), manifest signature status, last 10
audit_log entries.
- licenses.php: full CRUD.
* Ămettre: owner, expiration date, max machines, internal notes â
generates a PRSRV-XXXX-XXXX-XXXX-XXXX key, displays it ONCE in a
green callout (DB stores the key; the message stays only on this
request, never shown again).
* Prolonger (per-row, expandable form), Revoke / Unrevoke,
Reset machines (frees all slots for that license).
* Status badge: active / expired / revoked.
- versions.php: edit the manifest from the web.
* Add a version: number + release date + minLicenseDate + release
notes Markdown (creates releasenotes/{version}.md). Sets default
download URL to {base_url}/builds/proserve-{version}.zip.
* Per-row Méta (edit minLicenseDate / releasedAt), Notes (edit md
inline), toggle availableForDownload, Delete entry.
* đ Sync (sign-manifest) button: shells out to
`php tools/sign-manifest.php` and shows its stdout â recomputes
sha256/sizeBytes for every uploaded ZIP, bumps `latest`, signs
Ed25519. Visual indicators on each row: zip presence, hash
computed yes/no, signature status.
* Lists orphan ZIPs in builds/ that no manifest entry references.
- audit.php: paginated audit_log viewer (100/page) with event-type
filter dropdown. JOINs licenses to show owner_name. Color-codes
events (validate_ok green, expired amber, invalid/revoked red).
Server README rewritten to document the full setup flow:
1. Create MySQL DB, run migrations/001_init.sql
2. Copy config.example.php â config.php, fill db credentials
3. php tools/generate-keypair.php â paste into config.php and into the
client's Resources/server-pubkey.txt
4. Set admin_password_hash in config.php
5. Login at /PS_Launcher/admin/
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|