Skip to content

Un poste s'installe en une commande - #33

Merged
lostmind84 merged 5 commits into
mainfrom
feat/installation-en-une-commande
Jul 31, 2026
Merged

lostmind84 merged 5 commits into
mainfrom
feat/installation-en-une-commande

Conversation

@lostmind84

@lostmind84 lostmind84 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Ce que ça change

irm https://raw.githubusercontent.com/lostmind84/OpenScale/main/deploy/windows/bootstrap.ps1 | iex
curl -fsSL https://raw.githubusercontent.com/lostmind84/OpenScale/main/deploy/windows/bootstrap.cmd -o %TEMP%\openscale.cmd && %TEMP%\openscale.cmd

Sept gestes disparaissent. Trois d'entre eux échouaient en silence chez un bénévole :

  • la case « Débloquer » oubliée, que la stratégie d'exécution transforme en refus parlant de « fichier téléchargé depuis Internet » et jamais d'OpenScale ;
  • PowerShell ouvert sans élévation, dont le refus n'arrivait qu'après le téléchargement ;
  • le mauvais répertoire, qui faisait accuser l'archive alors que c'est le cd qui a manqué.

Cette branche ne touche ni install.ps1 ni common.ps1 : elle ajoute un script qui les appelle. La voie clé USB reste entière pour un poste sans Internet.

La collision avec main, et comment elle est résolue

main a livré le même jour, pour un autre défaut, install.ps1 -AccountPassword : un mot de passe de compte choisi à l'installation, plancher à quatre caractères dans common.ps1, décision confiée à Resolve-AccountPassword. Cette branche portait un -SessionPassword qui faisait le même travail en moins bon — il ne conservait pas le mot de passe d'un poste réinstallé et ne le vérifiait pas par Test-LocalCredential.

Il a été retiré. Le bootstrap se branche sur -AccountPassword, et install.ps1/common.ps1 reprennent la version de main sans un mot de la mienne. Le plancher de quatre caractères a disparu du bootstrap au passage : il vit dans common.ps1, Resolve-AccountPassword en est l'autorité, et la question le lit. Un bootstrap qui l'aurait redit aurait accepté ce que l'installeur refuse trois pas plus loin, devant un bénévole ayant déjà tout répondu — le test qui gardait la constante garde maintenant son absence.

Cinq points de conception

L'URL pointe main, pas une release. Le fichier ne porte aucun numéro de version — il demande /releases/latest, seul point de l'API qui exclut brouillons et pré-versions par contrat. Un actif de release le figerait sur son tag ; GitHub Pages en ferait une seconde copie à tenir synchrone avec deploy/windows/.

L'empreinte est vérifiée avant l'extraction. Expand-Archive sur une archive non vérifiée écrit sur le disque des fichiers dont la ligne suivante en exécute un en administrateur.

L'élévation et le mode non-interactif ne se combinent pas. Le one-liner se relance seul par Start-Process -Verb RunAs et pose ses questions dans la fenêtre élevée. Avec -AccountPassword, cette relance est refusée : une relance élevée fait passer ses paramètres par une ligne de commande, lisible dans la liste des processus par tout utilisateur de la machine.

Les scripts survivent à l'installation. install.ps1 ne copie aucun script — uninstall.ps1, update.ps1 et harden.ps1 ne survivaient que parce que l'archive restait sur le Bureau. Le dossier extrait est conservé sous C:\ProgramData\OpenScale\installer\<version>\.

-Version ne casse pas après les questions. Ce script vit sur main, les archives sont figées à leur tag : installer une release antérieure aurait fait échouer l'appel sur un paramètre inconnu après le téléchargement, l'extraction et les trois questions. Les paramètres sont confrontés à ce qu'install.ps1 déclare, et ce qui manque est retiré et annoncé.

Le mot de passe du compte à quatre caractères

Ce mot de passe est déjà en clair dans Winlogon\DefaultPassword et sur la fiche d'installation : sa longueur ne protège pas ce poste. Le refus de connexion réseau (SeDenyNetworkLogonRight) a été proposé et écarté — le réseau du magasin est un réseau de confiance. C'est écrit dans le spec pour être rouvrable, pas redécouvert.

La saisie est masquée et confirmée. Ce que le masque achète n'est pas un secret gardé, c'est un mot de passe qui ne s'affiche pas à l'écran d'un poste posé face aux clients.

Vérification

pwsh -File ./make.ps1 test vert après le merge de main — vet, boundary, deps, l'ensemble des paquets, passe -race.

13 tests ajoutés dans deploy/bootstrap_test.go : aucune version figée, l'empreinte comparée avant l'extraction, Unblock-File appelé, tout paramètre passé déclaré par install.ps1, le mot de passe absent de tout Write-Host et de tout journal, le plancher lu et non redit, les deux entrées qui nomment la même URL, le dépôt et l'hôte alignés sur DefaultUpdateRepository et DefaultBaseURL, l'auto-élévation refusée avec un secret, les scripts conservés sur le poste, la compatibilité avec un install.ps1 plus ancien. Le parsing PowerShell réel (pwsh et powershell.exe 5.1) et la marque d'ordre des octets couvrent le nouveau fichier sans une ligne de plus.

Le chemin réseau a été éprouvé contre la vraie release v0.9 : API interrogée, archive de 7,2 Mo téléchargée, empreinte d33c5d72… conforme, extraction vérifiée. Ce qui reste à la recette de §15.2 : l'invite UAC, le service qui démarre, le redémarrage de recette.

Documentation

INSTALLATION.md retombe à 15 minutes comptées (les deux minutes d'écart étaient le téléchargement et la décompression), garde la section de main sur le mot de passe du compte et gagne « Installer un poste sans Internet », les étapes renumérotées de 1 à 6. README.md gagne une section « Installer un poste » ; handbook/getting-started.md renvoie à INSTALLATION.md par URL absolue (ODR-0002).

Spec : docs/superpowers/specs/2026-07-31-installation-en-une-commande-design.md.

… gestes

Installer un poste demandait de trouver l'archive, la copier, cocher
« Débloquer » dans les propriétés du fichier, extraire, ouvrir PowerShell en
administrateur, se placer dans le bon répertoire, puis lancer install.ps1.
Trois de ces gestes échouaient en silence chez un bénévole : la case oubliée,
que la stratégie d'exécution transforme en refus parlant de « fichier
téléchargé depuis Internet » et jamais d'OpenScale ; la console non élevée,
dont le refus n'arrivait qu'après le téléchargement ; et le mauvais répertoire,
qui faisait accuser l'archive.

deploy/windows/bootstrap.ps1 les fait tous. Il vit sur main et ne nomme aucune
version : il demande /releases/latest, seul point de l'API qui exclut brouillons
et pré-versions par contrat. L'empreinte est vérifiée AVANT l'extraction, jamais
après — décompresser une archive non vérifiée écrit sur le disque des fichiers
dont la ligne suivante en exécute un en administrateur.

Trois questions au lieu de zéro paramètre : mot de passe de la session, type
d'installation, ouverture de session automatique. Le mot de passe ne sort pas du
processus — install.ps1 le reçoit en [securestring] — et l'auto-élévation est
refusée quand -SessionPassword est fourni, parce qu'une relance élevée ferait
passer le secret par une ligne de commande, lisible dans la liste des processus.

Deux trous rebouchés en chemin. install.ps1 ne copie aucun script : un poste
installé depuis %TEMP% n'aurait eu ni désinstalleur ni script de mise à jour, le
dossier extrait est donc conservé sous ProgramData\OpenScale\installer\<version>.
Et -Version, qui installe une release antérieure, aurait fait échouer l'appel sur
un paramètre inconnu après les trois questions : les paramètres sont confrontés à
ce qu'install.ps1 déclare.

Le plancher du mot de passe est à quatre caractères. Ce mot de passe est déjà en
clair dans Winlogon\DefaultPassword et sur la fiche d'installation : sa longueur
ne protège pas ce poste. Le refus de connexion réseau (SeDenyNetworkLogonRight) a
été proposé et écarté, le réseau du magasin étant de confiance.

INSTALLATION.md retombe à 15 minutes comptées, et la voie clé USB reste écrite
pour le poste hors ligne. 12 tests de deploy/ ajoutés aux 32 existants.
Les deux branches ont livré le même jour un mot de passe de compte choisi à
l'installation, et main l'a fait mieux. Son -AccountPassword conserve le mot de
passe d'un poste réinstallé — la règle du code de secours, « la fiche déjà rangée
dans le classeur doit rester vraie » —, le vérifie par Test-LocalCredential, et
confie la décision à Resolve-AccountPassword, exerçable en test sans droits
administrateur. Le -SessionPassword de cette branche ne faisait rien de tout ça.

Il est donc retiré, et bootstrap.ps1 se branche sur -AccountPassword. install.ps1
et common.ps1 reprennent la version de main sans un mot de la mienne.

Le plancher de quatre caractères disparaît aussi du bootstrap : il vit dans
common.ps1, Resolve-AccountPassword en est l'autorité, et la question le lit. Un
bootstrap qui l'aurait redit aurait accepté ce que l'installeur refuse trois pas
plus loin, devant un bénévole ayant déjà tout répondu. Le test qui gardait la
constante garde maintenant son absence.

La saisie reste masquée et confirmée. Ce que -AsSecureString achète n'est pas un
secret gardé — ce mot de passe finit dans Winlogon\DefaultPassword et sur la
fiche — mais un mot de passe qui ne s'affiche pas à l'écran d'un poste posé face
aux clients.

INSTALLATION.md garde les deux sections, celle de main sur le mot de passe du
compte et celle de cette branche sur l'installation hors ligne, renumérotées sur
les six étapes et 15 minutes du nouveau parcours.
« Vide = tiré au sort (20 caractères) » puis, deux lignes plus bas, « laisser
vide ne touche pas au mot de passe en place ». Les deux sont vraies, mais pas au
même moment, et l'écran ne disait pas lequel : c'est install.ps1 qui décide,
selon que le poste est neuf ou déjà installé. L'invite le dit maintenant en une
seule phrase, et nomme au passage ce que la saisie masquée achète.
« Installer un poste » venait en septième section, après « Développer » : un
dépôt dont le produit est un poste de pesée le décrivait à qui vient le
compiler, pas à qui vient le poser dans un magasin. La commande unique est
maintenant la première chose sous le titre, et la démonstration sans matériel
la suit.
@lostmind84
lostmind84 merged commit 3b47753 into main Jul 31, 2026
6 checks passed
@lostmind84
lostmind84 deleted the feat/installation-en-une-commande branch July 31, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant