# Build Windows One-Click

Le packaging Windows standard du projet repose sur :

- `build_windows_oneclick.bat`
- `build_windows_gui_v6_oneclick.bat`
- `build_windows_installer_oneclick.bat`
- `scripts/build_windows_oneclick.ps1`
- `anonymisation_onefile.spec`
- `anonymisation_gui_v6_onefile.spec`
- `installer/Anonymisation.iss`

## Usage

Sur la machine Windows de build :

1. ouvrir le dossier du projet
2. double-cliquer sur `build_windows_oneclick.bat`

Le script :

- crée un venv de build local `.venv_build_win`
- installe les dépendances nécessaires au packaging
- génère `build_info.py`
- lance `PyInstaller` avec `anonymisation_onefile.spec`
- vérifie la présence de l'exécutable final
- prépare un dossier de livraison et une archive ZIP
- crée `release\Anonymisation-Setup.exe` si Inno Setup 6 est installé

## Sorties attendues

- exécutable : `dist\Anonymisation.exe`
- dossier de livraison : `release\Anonymisation-Windows\`
- archive : `release\Anonymisation-Windows.zip`
- installateur : `release\Anonymisation-Setup.exe`
- hash : `release\Anonymisation.exe.sha256.txt`

## Installateur Windows

L'installateur est généré avec Inno Setup 6. Il fournit :

- choix du dossier d'installation
- installation utilisateur par défaut sans droits administrateur
- raccourci menu Démarrer
- option d'icône sur le bureau
- désinstallation Windows standard

Si Inno Setup n'est pas présent sur la machine de build, le script conserve le
build EXE/ZIP et affiche un avertissement. Installer Inno Setup 6 depuis le site
officiel puis relancer le build.

Installation automatisée de la dépendance de build Inno Setup :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\install_inno_setup_build_dep.ps1
```

Recompiler uniquement l'installateur à partir de `release\Anonymisation-Windows\Anonymisation.exe` :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_installer_only.ps1
```

Pour ne générer que l'exécutable et le ZIP :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_oneclick.ps1 -SkipInstaller
```

## GUI V6

La GUI V6 utilise le même pipeline PyInstaller + Inno Setup, mais avec l'entrée
`Pseudonymisation_Gui_V6.py` et la spec dédiée `anonymisation_gui_v6_onefile.spec`.
Le comportement historique reste le défaut du script one-click.

Sur la machine Windows de build :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_oneclick.ps1 -GuiV6
```

ou double-cliquer sur :

```text
build_windows_gui_v6_oneclick.bat
```

Sorties attendues identiques :

- `dist\Anonymisation.exe` : exécutable GUI V6 ;
- `release\Anonymisation-Windows\Anonymisation.exe` : paquet local ;
- `release\Anonymisation-Windows.zip` : archive locale ;
- `release\Anonymisation-Setup.exe` : installateur destiné au portail après GO
  diffusion ;
- `release\Anonymisation.exe.sha256.txt` : hash de l'exécutable.

## Important

- les utilisateurs finaux n'ont pas besoin d'installer Python
- le build doit être lancé depuis Windows
- le modèle ONNX embarqué requis doit exister localement dans :
  `models\camembert-bio-deid\onnx\model.onnx`
- limitation MVP frozen : voir `docs/limitations-frozen-mvp.md` pour les moteurs
  effectivement embarqués, notamment l'absence d'EDS-Pseudo dans le paquet MVP.

## CLI Windows (sans GUI) — fichier unique

En plus de la GUI, un exécutable **CLI de production** permet d'anonymiser un
fichier (ou un dossier) en ligne de commande, sans interface graphique.

- entrypoint : `scripts/anonymize_cli.py`
- spec PyInstaller : `anonymisation_cli_onefile.spec`
- exécutable produit : `dist\Anonymisation-CLI.exe` (ne remplace pas
  `Anonymisation.exe`)

### Build CLI

Sur la machine Windows de build, dans le venv de build :

```powershell
pyinstaller --noconfirm --clean anonymisation_cli_onefile.spec
```

Le `.spec` embarque les mêmes ressources que la GUI : `config\`, `data\`,
`models\camembert-bio-deid\onnx\`, `detectors\`, `assets\`, plus les
hiddenimports NER / docTR / ONNX. Le modèle ONNX obligatoire
`models\camembert-bio-deid\onnx\model.onnx` doit exister localement avant le
build (sinon il ne sera pas embarqué et le CLI échouera au lancement).

### Utilisation

```powershell
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 ;
- options : `--no-ner` (regex seul), `--gliner` (vote croisé optionnel),
  `--limit N`, `--config <dictionnaires.yml>`.

Sorties produites dans le dossier demandé (identiques à la GUI v5, burn raster) :
`<doc>.redacted_raster.pdf`, `<doc>.pseudonymise.txt`, `<doc>.audit.jsonl`.
Un log lisible est écrit à côté de l'EXE : `anonymisation_cli.log`.

### Codes retour

| Code | Signification |
|------|---------------|
| `0`  | anonymisation terminée, sortie produite |
| `1`  | erreur de traitement (exception) |
| `2`  | entrée manquante (fichier/dossier introuvable, aucun document) |
| `3`  | modèle OBLIGATOIRE absent / illisible (fail-closed, pas de mode dégradé) |
| `4`  | sortie non produite (quarantaine résiduelle ou PDF absent) |

### Modèles (dernière version du moteur)

- **OBLIGATOIRE** : CamemBERT-bio ONNX (`models\camembert-bio-deid\onnx\model.onnx`).
  Embarqué dans le build. S'il est absent/illisible et que le NER est demandé,
  le CLI **échoue clairement (code 3)** — il n'affiche jamais « OK » en mode
  dégradé silencieux.
- **OPTIONNELS** : EDS-Pseudo, GLiNER. Chargés best effort et **tracés dans le
  log** ; leur absence est signalée explicitement, jamais masquée. ⚠️ EDS-Pseudo
  peut ne pas être embarqué dans le paquet MVP frozen — voir
  `docs/limitations-frozen-mvp.md`. Dans ce cas le log indique
  « EDS-Pseudo (optionnel) INDISPONIBLE » et le traitement se poursuit avec
  CamemBERT-bio ONNX (impact qualité faible, validé en bêta interne).
- `--no-ner` : mode regex seul **assumé** par l'opérateur (aucun modèle
  obligatoire), à n'utiliser qu'en connaissance de cause.

### Limitations CLI frozen

- pas d'EDS-Pseudo garanti dans le MVP frozen (cf. ci-dessus) ;
- pas de dépendance internet : tous les modèles déclarés obligatoires sont
  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 = <dossier d'installation>
    ExePath     = <dossier>\Anonymisation-CLI.exe
    Version     = <version>

HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\Anonymisation-CLI.exe
    (Default) = <dossier>\Anonymisation-CLI.exe
    Path      = <dossier>
```

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.

Pour une diffusion à des utilisateurs novices, la voie recommandée est :

- signer `Anonymisation.exe` avec un certificat Authenticode
- horodater la signature
- diffuser par partage réseau interne, Intune, GPO ou portail établissement
- conserver le hash `release\Anonymisation.exe.sha256.txt`
- éviter de demander aux utilisateurs de cliquer sur `Exécuter quand même`

Le script prend en charge la signature si un certificat est disponible.

### Signature automatique avec configuration locale

Sur la machine Windows de build :

1. copier `build_signing.example.ps1` en `build_signing.local.ps1`
2. renseigner l'empreinte du certificat ou le chemin du PFX
3. double-cliquer comme d'habitude sur `build_windows_oneclick.bat`

`build_signing.local.ps1` est ignoré par Git pour éviter de versionner des secrets.

### Signature manuelle via PowerShell

Avec un certificat installé dans le magasin Windows :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_oneclick.ps1 -Sign -CertThumbprint "EMPREINTE_CERTIFICAT"
```

Avec un fichier PFX :

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_windows_oneclick.ps1 -Sign -PfxPath "C:\chemin\certificat.pfx" -PfxPassword "mot-de-passe"
```

Si aucun certificat n'est disponible, le build reste possible, mais Windows peut afficher un avertissement de réputation au premier lancement.

Références Microsoft :

- SmartScreen reputation : https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/smartscreen-reputation
- SignTool : https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool
- Authenticode timestamping : https://learn.microsoft.com/en-us/windows/win32/seccrypto/time-stamping-authenticode-signatures
