diff --git a/docs/build-windows-oneclick.md b/docs/build-windows-oneclick.md index a1fae02..6d70212 100644 --- a/docs/build-windows-oneclick.md +++ b/docs/build-windows-oneclick.md @@ -147,6 +147,50 @@ Un log lisible est écrit à côté de l'EXE : `anonymisation_cli.log`. locaux/embarqués ; - rastérisation séquentielle en mode frozen (cf. limitations GUI). +### Installateur CLI dédié (Inno Setup, séparé de la GUI) + +Pour les tests internes et l'intégration de la brique CLI dans un autre logiciel, +un installateur Inno Setup **distinct de la GUI** est fourni : + +- script : `installer\Anonymisation-CLI.iss` (AppId propre, ne partage pas la + désinstallation de la GUI ; `installer\Anonymisation.iss` n'est pas modifié) ; +- build : `scripts\build_windows_cli_installer_only.ps1` ; +- sortie : `release\Anonymisation-CLI-Setup.exe` (+ `.sha256.txt`). + +```powershell +# 1. builder l'EXE CLI (cf. section précédente) -> dist\Anonymisation-CLI.exe +# 2. builder l'installateur : +powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_cli_installer_only.ps1 +``` + +Caractéristiques de l'installateur : + +- **sans droits admin** (`PrivilegesRequired=lowest`) ; +- dossier par défaut : `%LOCALAPPDATA%\Programs\Anonymisation-CLI` ; +- **pas** d'ajout au PATH système, **pas** de raccourci bureau (entrée menu + Démarrer vers le README seulement) ; +- désinstalleur Windows standard, qui **supprime les clés de registre créées**. + +#### Clés de registre HKCU (intégration logicielle tierce) + +``` +HKCU\Software\CHUXX\Anonymisation-CLI + InstallPath = + ExePath = \Anonymisation-CLI.exe + Version = + +HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\Anonymisation-CLI.exe + (Default) = \Anonymisation-CLI.exe + Path = +``` + +Un autre logiciel retrouve l'exe ainsi (PowerShell) : + +```powershell +$exe = (Get-ItemProperty 'HKCU:\Software\CHUXX\Anonymisation-CLI').ExePath +& $exe "C:\doc.pdf" "C:\sortie" +``` + ## Blocage Windows / SmartScreen Un exécutable PyInstaller non signé peut déclencher Microsoft Defender SmartScreen, surtout s'il est téléchargé depuis Internet ou envoyé par e-mail. La signature réduit fortement le risque et évite l'éditeur inconnu, mais elle ne garantit pas toujours l'absence totale d'avertissement SmartScreen pour une toute nouvelle version : Windows tient aussi compte de la réputation du fichier et de son hash. diff --git a/installer/Anonymisation-CLI-README.txt b/installer/Anonymisation-CLI-README.txt new file mode 100644 index 0000000..db0f14c --- /dev/null +++ b/installer/Anonymisation-CLI-README.txt @@ -0,0 +1,56 @@ +Anonymisation-CLI +================= + +Outil en ligne de commande (sans interface graphique) pour anonymiser un +document médical unique (ou un dossier). + +UTILISATION +----------- + Anonymisation-CLI.exe "C:\chemin\document.pdf" "C:\chemin\sortie" + Anonymisation-CLI.exe --help + +- argument 1 : fichier unique existant (ou dossier parcouru récursivement) ; +- argument 2 : dossier de sortie (créé si absent) ; --out reste accepté ; +- chemins avec espaces et accents supportés. + +Sorties produites dans le dossier demandé : + .redacted_raster.pdf (PDF anonymisé) + .pseudonymise.txt (texte pseudonymisé) + .audit.jsonl (audit / traçabilité) + +Un log est écrit à côté de l'exécutable : anonymisation_cli.log + +CODES RETOUR +------------ + 0 anonymisation terminée, sortie produite + 1 erreur de traitement + 2 entrée manquante (fichier/dossier introuvable, aucun document) + 3 modèle obligatoire absent (CamemBERT-bio ONNX) — échec fail-closed + 4 sortie non produite (quarantaine résiduelle ou PDF absent) + +INTÉGRATION DANS UN AUTRE LOGICIEL +---------------------------------- +L'installateur écrit des clés de registre HKCU stables : + + HKCU\Software\CHUXX\Anonymisation-CLI + InstallPath = dossier d'installation + ExePath = chemin complet de Anonymisation-CLI.exe + Version = version installée + +App Paths (résolution standard Windows) : + + HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\Anonymisation-CLI.exe + (Default) = chemin complet de l'exe + Path = dossier d'installation + +Exemple PowerShell pour retrouver l'exe : + + $exe = (Get-ItemProperty 'HKCU:\Software\CHUXX\Anonymisation-CLI').ExePath + & $exe "C:\doc.pdf" "C:\sortie" + +MODÈLES +------- +- CamemBERT-bio ONNX : OBLIGATOIRE (embarqué). Absent -> code 3, pas de mode + dégradé silencieux. +- EDS-Pseudo / GLiNER : optionnels. Leur absence est tracée dans le log ; + le traitement se poursuit avec CamemBERT-bio. diff --git a/installer/Anonymisation-CLI.iss b/installer/Anonymisation-CLI.iss new file mode 100644 index 0000000..7b4ad58 --- /dev/null +++ b/installer/Anonymisation-CLI.iss @@ -0,0 +1,52 @@ +; Installateur Inno Setup DÉDIÉ au CLI (distinct de la GUI Anonymisation.iss). +; Cible : tests internes + intégration de la brique CLI dans un autre logiciel. +; - AppId distinct de la GUI (ne partage pas la désinstallation) +; - installation utilisateur sans droits admin (PrivilegesRequired=lowest) +; - clés registre HKCU stables (InstallPath / ExePath / Version) + App Paths HKCU +; pour qu'un autre logiciel retrouve l'exe ; PAS d'ajout au PATH système. +#define MyAppName "Anonymisation-CLI" +#define MyAppPublisher "CHUXX" +#define MyAppExeName "Anonymisation-CLI.exe" +#ifndef AppVersion +#define AppVersion "1.0.0" +#endif + +[Setup] +; AppId PROPRE au CLI (différent du GUID GUI 6D11E4F8-...) — ne pas réutiliser ailleurs. +AppId={{B2F4A7C1-9E3D-4A52-8C77-1D6E0A9B4F30} +AppName={#MyAppName} +AppVersion={#AppVersion} +AppPublisher={#MyAppPublisher} +DefaultDirName={localappdata}\Programs\{#MyAppName} +DisableDirPage=no +DisableProgramGroupPage=yes +PrivilegesRequired=lowest +OutputDir=..\release +OutputBaseFilename=Anonymisation-CLI-Setup +SetupIconFile=..\assets\icons\app.ico +UninstallDisplayIcon={app}\{#MyAppExeName} +Compression=lzma2 +SolidCompression=yes +WizardStyle=modern +ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible + +[Languages] +Name: "french"; MessagesFile: "compiler:Languages\French.isl" + +[Files] +Source: "..\dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "Anonymisation-CLI-README.txt"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignoreversion skipifsourcedoesntexist + +[Registry] +; Clés stables pour intégration logicielle tierce (HKCU, supprimées à la désinstallation). +Root: HKCU; Subkey: "Software\{#MyAppPublisher}\{#MyAppName}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"; Flags: uninsdeletekey +Root: HKCU; Subkey: "Software\{#MyAppPublisher}\{#MyAppName}"; ValueType: string; ValueName: "ExePath"; ValueData: "{app}\{#MyAppExeName}" +Root: HKCU; Subkey: "Software\{#MyAppPublisher}\{#MyAppName}"; ValueType: string; ValueName: "Version"; ValueData: "{#AppVersion}" +; App Paths HKCU : permet à un tiers de résoudre Anonymisation-CLI.exe via la base de registre. +Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\App Paths\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey +Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\App Paths\{#MyAppExeName}"; ValueType: string; ValueName: "Path"; ValueData: "{app}" + +[Icons] +; Pas de raccourci bureau pour un CLI ; entrée menu Démarrer vers le README (aide). +Name: "{autoprograms}\{#MyAppName} (README)"; Filename: "{app}\README.txt" diff --git a/scripts/build_windows_cli_installer_only.ps1 b/scripts/build_windows_cli_installer_only.ps1 new file mode 100644 index 0000000..c469d4f --- /dev/null +++ b/scripts/build_windows_cli_installer_only.ps1 @@ -0,0 +1,67 @@ +# Build de l'installateur Inno Setup DÉDIÉ au CLI (distinct de la GUI). +# Produit release\Anonymisation-CLI-Setup.exe à partir de dist\Anonymisation-CLI.exe. +# Calcule le SHA-256. Ne touche pas au build/installateur GUI. +param( + [string]$AppVersion = (Get-Date -Format "yyyy.MM.dd.HHmm") +) + +$ErrorActionPreference = "Stop" + +function Resolve-InnoCompiler { + $command = Get-Command ISCC.exe -ErrorAction SilentlyContinue + if ($command) { + return $command.Source + } + + $candidates = @() + if (${env:ProgramFiles(x86)}) { + $candidates += (Join-Path ${env:ProgramFiles(x86)} "Inno Setup 6\ISCC.exe") + } + if ($env:ProgramFiles) { + $candidates += (Join-Path $env:ProgramFiles "Inno Setup 6\ISCC.exe") + } + if ($env:LOCALAPPDATA) { + $candidates += (Join-Path $env:LOCALAPPDATA "Programs\Inno Setup 6\ISCC.exe") + $candidates += (Join-Path $env:LOCALAPPDATA "Inno Setup 6\ISCC.exe") + } + + foreach ($candidate in $candidates) { + if ($candidate -and (Test-Path $candidate)) { + return $candidate + } + } + throw "ISCC.exe introuvable. Installer Inno Setup 6 puis relancer." +} + +function Require-Path { + param( + [string]$PathValue, + [string]$Label + ) + if (-not (Test-Path $PathValue)) { + throw "$Label introuvable: $PathValue" + } +} + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = (Resolve-Path (Join-Path $ScriptDir "..")).Path +$InstallerScriptPath = Join-Path $ProjectRoot "installer\Anonymisation-CLI.iss" +$PackageExePath = Join-Path $ProjectRoot "dist\Anonymisation-CLI.exe" +$InstallerPath = Join-Path $ProjectRoot "release\Anonymisation-CLI-Setup.exe" + +Require-Path -PathValue $InstallerScriptPath -Label "Script Inno Setup CLI" +Require-Path -PathValue $PackageExePath -Label "Executable CLI (dist\Anonymisation-CLI.exe)" + +$innoCompiler = Resolve-InnoCompiler +Write-Host "Inno Setup Compiler : $innoCompiler" +& $innoCompiler "/DAppVersion=$AppVersion" $InstallerScriptPath +if ($LASTEXITCODE -ne 0) { + throw "Inno Setup a echoue avec le code $LASTEXITCODE." +} + +Require-Path -PathValue $InstallerPath -Label "Installateur CLI Windows" +$installerSizeMb = [math]::Round((Get-Item $InstallerPath).Length / 1MB, 1) +$sha = (Get-FileHash -Algorithm SHA256 $InstallerPath).Hash +Set-Content -Path "$InstallerPath.sha256.txt" -Value $sha -Encoding ascii +Write-Host "Installateur CLI pret : $InstallerPath ($installerSizeMb MB)" +Write-Host "SHA-256 : $sha"