Files
Omika/docs/MISE_A_JOUR_DIAGNOSTICS_SRV-OMIKA.md
T
2026-10-23 18:46:50 +02:00

597 lines
26 KiB
Markdown

# Mise à jour production — Omika Diagnostics (SRV-OMIKA)
> **Objet** : procédure de mise à jour d'une installation déjà existante
> (première version de `DiagnosticsWorker` + `DiagnosticsWeb` déjà déployée) vers la
> nouvelle version (code + base de données).
>
> **Cible** : Windows Server 2025 `SRV-OMIKA`, PowerShell **administrateur**,
> PostgreSQL 18, runtime .NET 10 (framework-dependent).
>
> **Style** : chaque composant suit le même schéma que la documentation Omika.Api
> existante → **Publier → Backup → Arrêter/Mettre à jour → Redémarrer → Vérifier**.
---
## 0. Vue d'ensemble des composants à mettre à jour
| # | Composant | Projet | Service Windows | Exécutable | Santé |
|---|---|---|---|---|---|
| 1 | API métier/mobile (+ forwarder diagnostics) | `src\Omika.Api` | `OmikaApi` | `Omika.Api.exe` | `GET /health` |
| 2 | Worker de synchronisation métier | `src\Omika.Worker` | `OmikaWorker` | `Omika.Worker.exe` | service `Running` + logs |
| 3 | Import JSONL → PostgreSQL | `src\Omika.Diagnostics.Worker` | `OmikaDiagnosticsWorker` | `Omika.Diagnostics.Worker.exe` | service `Running` + checkpoint |
| 4 | Interface Diagnostic Center | `src\Omika.Diagnostics.Web` | `OmikaDiagnosticsWeb` | `Omika.Diagnostics.Web.exe` | `GET /Login` (200) |
| 5 | API centrale diagnostics *(optionnel, multi-serveur)* | `src\Omika.Diagnostics.Api` | `OmikaDiagnosticsApi` | `Omika.Diagnostics.Api.exe` | `GET /` (200) |
| — | Base PostgreSQL `omika_diagnostics` | `infra\postgresql\*.sql` | — | migrations `001 → 011` | `SELECT count(*)` |
**Ordre global de la mise à jour** (les étapes 4 à 7 sont détaillées plus bas) :
```
1. Publier (poste DEV) §2
2. Transférer + backup §3
3. Arrêter les services §4
4. Migrer la base §5 ← TOUJOURS AVANT les nouveaux binaires
5. Copier les binaires §6
6. Redémarrer §7
7. Vérifier §8
```
---
## 1. Prérequis
### Poste DEV
- SDK .NET 10 (`global.json` épingle `10.0.302`).
- Dépôt à jour (`git pull`), branche qui contient les derniers changements.
### SRV-OMIKA (PowerShell administrateur)
```powershell
net session # doit réussir, sinon STOP (droits)
dotnet --list-runtimes # Microsoft.AspNetCore.App 10.x présent
Get-Service postgresql* # Running
Test-Path 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
Test-Path 'C:\Program Files\PostgreSQL\18\bin\pg_dump.exe'
```
---
## 2. Publier sur le poste DEV
Depuis `D:\Avalonia\Omika`, publier les **4 composants réellement utilisés**
sur SRV-OMIKA. Le composant `Omika.Diagnostics.Api` (§6.5) n'est publié que si le
mode multi-serveur (clients distants) est activé.
> **Script prêt à l'emploi** : `scripts\publish-diagnostics.ps1` effectue
> exactement ceci (publish + vérification des EXE). Lancer depuis la racine :
> `.\scripts\publish-diagnostics.ps1` (ajouter `-IncludeCentralApi` pour l'API
> centrale). Les commandes manuelles équivalentes sont ci-dessous.
```powershell
cd D:\Avalonia\Omika
# 1. Omika.Api
dotnet publish src\Omika.Api\Omika.Api.csproj `
-c Release -r win-x64 --self-contained false `
-o C:\Omika\Deploy\OmikaApi-next
# 2. Omika.Worker
dotnet publish src\Omika.Worker\Omika.Worker.csproj `
-c Release -r win-x64 --self-contained false `
-o C:\Omika\Deploy\OmikaWorker-next
# 3. Omika.Diagnostics.Worker (EnableWindowsService=true est le défaut : ne pas le désactiver)
dotnet publish src\Omika.Diagnostics.Worker\Omika.Diagnostics.Worker.csproj `
-c Release -r win-x64 --self-contained false `
-o C:\Omika\Deploy\DiagnosticsWorker-next
# 4. Omika.Diagnostics.Web
dotnet publish src\Omika.Diagnostics.Web\Omika.Diagnostics.Web.csproj `
-c Release -r win-x64 --self-contained false `
-o C:\Omika\Deploy\DiagnosticsWeb-next
# 5. (optionnel) Omika.Diagnostics.Api
dotnet publish src\Omika.Diagnostics.Api\Omika.Diagnostics.Api.csproj `
-c Release -r win-x64 --self-contained false `
-o C:\Omika\Deploy\DiagnosticsApi-next
```
### Vérification des sorties
```powershell
Get-ChildItem C:\Omika\Deploy\OmikaApi-next # Omika.Api.exe + Omika.Api.dll + Omika.Core.dll + Omika.Data.dll + Omika.Observability.External.dll
Get-ChildItem C:\Omika\Deploy\OmikaWorker-next # Omika.Worker.exe + Omika.Worker.dll + Omika.Core.dll + Omika.Data.dll + Omika.Observability.External.dll
Get-ChildItem C:\Omika\Deploy\DiagnosticsWorker-next # Omika.Diagnostics.Worker.exe + Omika.Diagnostics.Worker.dll + Omika.Diagnostics.Core.dll + Omika.Diagnostics.Data.dll + Npgsql.dll
Get-ChildItem C:\Omika\Deploy\DiagnosticsWeb-next # Omika.Diagnostics.Web.exe + Omika.Diagnostics.Web.dll + wwwroot\ + Omika.Diagnostics.Core.dll + Omika.Diagnostics.Data.dll + Npgsql.dll
```
> ⚠️ Ne jamais livrer de secret Dev en Prod. Vérifier l'absence de valeur de test
> dans les publications, et que le serveur garde **`ASPNETCORE_ENVIRONMENT=Production`**.
> (`appsettings.Development.json`, s'il est présent dans une publication, n'est chargé
> que si l'environnement est `Development` — il ne doit donc jamais l'être sur SRV-OMIKA.)
Transférer ensuite les dossiers `*-next` vers `SRV-OMIKA` dans
`C:\Omika\Deploy\`.
---
## 3. Backup sur le serveur
### 3.1 Base PostgreSQL (AVANT toute migration)
```powershell
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
$stamp = Get-Date -Format 'yyyyMMdd_HHmm'
$out = "C:\Omika\Backups\omika_diagnostics_${stamp}_before_upgrade.backup"
& 'C:\Program Files\PostgreSQL\18\bin\pg_dump.exe' `
-h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -F c -v -f $out
Remove-Item Env:PGPASSWORD
$f = Get-Item $out
$f.Exists -and $f.Length -gt 0 # doit être True, sinon NO-GO
```
### 3.2 Binaires (AVANT remplacement)
```powershell
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$root = 'C:\Omika\Backups'
Copy-Item 'C:\Omika\Apps\OmikaApi' -Destination "$root\OmikaApi_${stamp}" -Recurse -Force
Copy-Item 'C:\Omika\Apps\OmikaWorker' -Destination "$root\OmikaWorker_${stamp}" -Recurse -Force
Copy-Item 'C:\Omika\Apps\DiagnosticsWorker' -Destination "$root\DiagnosticsWorker_${stamp}" -Recurse -Force
Copy-Item 'C:\Omika\Apps\DiagnosticsWeb' -Destination "$root\DiagnosticsWeb_${stamp}" -Recurse -Force
```
> Le script `infra\deploy\Install-OmikaServerFiles.ps1` fait déjà cette sauvegarde
> horodatée + copie + préservation de la config, si vous préférez l'automatiser.
---
## 4. Arrêter les services (ordre)
L'ordre fige d'abord la lecture (Web), puis les écrivains, et draine le Worker en dernier.
```powershell
Stop-Service OmikaDiagnosticsWeb -Force
Stop-Service OmikaApi -Force
Stop-Service OmikaWorker -Force
Stop-Service OmikaDiagnosticsWorker -Force
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
# Attendu : les 4 = Stopped
```
---
## 5. Mettre à jour la base de données (migrations)
### 5.1 Auditer l'état actuel (lecture seule)
```powershell
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
$psql = 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
"SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE 'diagnostics%' ORDER BY 1;"
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
"SELECT column_name FROM information_schema.columns WHERE table_name='diagnostic_event' ORDER BY ordinal_position;"
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
"SELECT rolname FROM pg_roles ORDER BY rolname;"
Remove-Item Env:PGPASSWORD
```
Cela permet de déterminer **quelles migrations sont déjà appliquées** :
| Repère observé | Migration déjà appliquée |
|---|---|
| `diagnostic_event` présent | `001` |
| colonnes `actor_key` / `actor_key_version` | `002` |
| rôles `omika_diagnostics_owner/worker/web` | `003` |
| `SELECT`+`DELETE` worker sur `diagnostic_event` | `004` |
| colonnes `client_code`/`server_instance`/`environment` | `005` |
| colonnes appareil/licence | `006` |
| colonnes `screen_code`/`feature_code` | `007` |
| table `diagnostics_clients` | `008` |
| rôle `omika_diagnostics_api` + grants clients | `009` |
| table `diagnostics_users` | `010` |
| table `diagnostics_reference` | `011` |
### 5.2 Appliquer UNIQUEMENT les migrations manquantes, dans l'ordre
Migrations `001 → 011`, toutes **idempotentes** (`CREATE/ADD IF NOT EXISTS`,
`ON CONFLICT DO NOTHING`, `GRANT`). Les appliquer avec `ON_ERROR_STOP=1`, en
compte **superuser** (`postgres`), car `003/009/010/011` font du `CREATE ROLE` /
`ALTER TABLE OWNER` / `GRANT`.
```powershell
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
$psql = 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
$db = 'C:\Omika\Deploy\DiagnosticsDatabase' # dossier contenant les .sql livrés
$migrations = @(
'001_diagnostics_schema.sql',
'002_actor_key.sql',
'003_diagnostics_roles.sql',
'004_diagnostics_retention.sql',
'005_diagnostics_client_context.sql',
'006_diagnostics_device_license.sql',
'007_diagnostics_usage.sql',
'008_diagnostics_clients.sql',
'009_diagnostics_clients_grants.sql',
'010_diagnostics_web_users.sql',
'011_diagnostics_reference.sql'
)
foreach ($m in $migrations) {
$f = Join-Path $db $m
if (-not (Test-Path $f)) { Write-Host "ABSENT : $m" ; continue }
Write-Host "Application : $m ..."
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -v ON_ERROR_STOP=1 -f $f
if ($LASTEXITCODE -ne 0) { throw "ÉCHEC sur $m (exit $LASTEXITCODE). STOP." }
}
Remove-Item Env:PGPASSWORD
```
> **Règle d'ordre migration ↔ binaires** : les migrations doivent être appliquées
> **AVANT** la copie des nouveaux binaires (§6). Les colonnes/tables ajoutées sont
> additives ; les anciens binaires restent compatibles, mais les nouveaux binaires
> échoueraient sur un schéma trop ancien.
### 5.3 Ce qui est nouveau dans cette mise à jour
- **`011_diagnostics_reference.sql`** (dernière livraison) : table
`diagnostics_reference` (référentiel administrable `ScreenCode`/`FeatureCode`),
ownership `omika_diagnostics_owner`, grants `omika_diagnostics_web`
(`SELECT`/`INSERT`/`UPDATE` colonnes ciblées + `USAGE` séquence), et **seed
idempotent** des 29 `ScreenCode` + 3 `FeatureCode`. Aucun droit accordé aux rôles
`omika_diagnostics_api` / `omika_diagnostics_worker`.
- `003_diagnostics_roles_preprod.sql` ne concerne **que** la préproduction : ne
**jamais** l'appliquer en Production.
### 5.4 Après `003` / `009` (rôles LOGIN) — mots de passe manuels
Les rôles LOGIN créés sans mot de passe doivent être positionnés manuellement,
jamais dans un script/log :
```
\password omika_diagnostics_worker
\password omika_diagnostics_web
\password omika_diagnostics_api # seulement si l'API centrale est activée
```
---
## 6. Mettre à jour chaque composant
Pour chaque composant, la copie **préserve** la configuration serveur existante
(secrets) : on exclut `appsettings.json` et `appsettings.Production.json`.
> ⚠️ Ne **jamais** supprimer :
> - `C:\Omika\Data\Api\Diagnostics\Jsonl\**` (JSONL en attente d'import)
> - `C:\Omika\Data\DiagnosticsWorker\Checkpoint\import-checkpoint.json`
> - `C:\Omika\Config\**`, les certificats TLS, les variables d'environnement MACHINE.
### 6.1 Omika.Api (service `OmikaApi`)
```powershell
# Backup : déjà fait §3.2. Puis copie :
robocopy 'C:\Omika\Deploy\OmikaApi-next' 'C:\Omika\Apps\OmikaApi' `
/E /XF appsettings.json appsettings.Production.json
```
Fichiers attendus après copie : `Omika.Api.exe`, `Omika.Api.dll`, `Omika.Core.dll`,
`Omika.Data.dll`, `Omika.Observability.External.dll`.
Configuration Production à conserver (injectée sur le serveur) :
`MobileAuth__SigningKey` (obligatoire, fail-fast), `DiagnosticsIdentity__HmacKey`,
`ConnectionStrings__*` HFSQL / licence / sync, `Observability__Remote__Directory`
(doit être **identique** au dossier JSONL lu par le Worker), et si le forwarding
central est actif : `DiagnosticsForwarding__Enabled/Endpoint/ApiKey`.
(Voir la table complète §6.6.)
Redémarrage et contrôle (port Kestrel = celui défini dans
`appsettings.Production.json`, ex. `5080`) :
```powershell
Start-Service OmikaApi
Get-Service OmikaApi # Running
Invoke-WebRequest 'http://127.0.0.1:5080/health' -UseBasicParsing
Invoke-WebRequest 'https://omika.applilogik.fr/health' -UseBasicParsing
# Attendu : 200 + "Healthy"
```
### 6.2 Omika.Worker (service `OmikaWorker`)
```powershell
robocopy 'C:\Omika\Deploy\OmikaWorker-next' 'C:\Omika\Apps\OmikaWorker' `
/E /XF appsettings.json appsettings.Production.json
```
Fichiers attendus : `Omika.Worker.exe`, `Omika.Worker.dll`, `Omika.Core.dll`,
`Omika.Data.dll`, `Omika.Observability.External.dll`.
Pas de port HTTP (background service) : contrôle = service `Running` + absence de
boucle d'erreur dans les logs (`C:\Omika\Logs\Worker`).
```powershell
Start-Service OmikaWorker
Get-Service OmikaWorker # Running
Get-EventLog -LogName Application -Newest 50 | Where-Object { $_.Source -match 'Omika' }
```
### 6.3 Omika.Diagnostics.Worker (service `OmikaDiagnosticsWorker`)
```powershell
robocopy 'C:\Omika\Deploy\DiagnosticsWorker-next' 'C:\Omika\Apps\DiagnosticsWorker' `
/E /XF appsettings.json appsettings.Production.json
```
Fichiers attendus : `Omika.Diagnostics.Worker.exe`, `Omika.Diagnostics.Worker.dll`,
`Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`, `Npgsql.dll`.
Configuration Production à conserver :
`ConnectionStrings__DiagnosticsDatabase`
(`Host=127.0.0.1;Port=5432;Database=omika_diagnostics;Username=omika_diagnostics_worker;Password=…`),
`Observability__Remote__Directory` (**identique** au dossier JSONL d'Omika.Api),
`Diagnostics__Import__CheckpointDirectory/CheckpointFileName`, `Diagnostics__RetentionDays`.
(Voir la table complète §6.6.)
```powershell
Start-Service OmikaDiagnosticsWorker
Get-Service OmikaDiagnosticsWorker # Running
Get-Content 'C:\Omika\Data\DiagnosticsWorker\Checkpoint\import-checkpoint.json'
# Attendu : checkpoint stable ou progressant ; aucun JSONL supprimé.
```
### 6.4 Omika.Diagnostics.Web (service `OmikaDiagnosticsWeb`)
```powershell
robocopy 'C:\Omika\Deploy\DiagnosticsWeb-next' 'C:\Omika\Apps\DiagnosticsWeb' `
/E /XF appsettings.json appsettings.Production.json
```
Fichiers attendus : `Omika.Diagnostics.Web.exe`, `Omika.Diagnostics.Web.dll`,
`wwwroot\`, `Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`, `Npgsql.dll`.
Configuration Production à conserver :
`ConnectionStrings__DiagnosticsDatabase`
(`…Username=omika_diagnostics_web;Password=…`), `DiagnosticsAuth__Operators`
(bootstrap temporaire uniquement), `ASPNETCORE_ENVIRONMENT=Production`.
(Voir la table complète §6.6.)
Contrôle (port Kestrel = celui de `appsettings.Production.json`) :
```powershell
Start-Service OmikaDiagnosticsWeb
Get-Service OmikaDiagnosticsWeb # Running
Invoke-WebRequest 'http://127.0.0.1:<PORT_WEB_DIAG>/Login' -UseBasicParsing # 200
```
> Le Web n'expose pas de `/health` : la page `/Login` (200) est le smoke test.
> Le reste est derrière authentification (redirect `/Login`).
### 6.5 Omika.Diagnostics.Api (service `OmikaDiagnosticsApi`) — **optionnel**
À déployer **uniquement** si vous activez la réception de lots provenant de
**serveurs clients distants**. Sur un SRV-OMIKA mono-serveur (Omika.Api écrit le
JSONL localement), ce composant n'est **pas** nécessaire.
```powershell
robocopy 'C:\Omika\Deploy\DiagnosticsApi-next' 'C:\Omika\Apps\DiagnosticsApi' `
/E /XF appsettings.json appsettings.Production.json
```
Fichiers attendus : `Omika.Diagnostics.Api.exe`, `Omika.Diagnostics.Api.dll`,
`Omika.Core.dll`, `Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`.
Configuration Production à conserver :
`ConnectionStrings__DiagnosticsDatabase` (`Username=omika_diagnostics_api`),
`Diagnostics__Central__Directory` (= spool central, ex.
`C:\ProgramData\Omika\Diagnostics\Central`).
```powershell
Start-Service OmikaDiagnosticsApi
Get-Service OmikaDiagnosticsApi # Running
Invoke-WebRequest 'http://127.0.0.1:<PORT_API_DIAG>/' -UseBasicParsing
# Attendu : 200 + JSON { name: "Omika.Diagnostics.Api", status: "ok" }
```
### 6.6 Référence — variables d'environnement / clés de configuration par service
**Règle de nommage** : en variable d'environnement, `:` devient `__`
(`Diagnostics:Import:CheckpointDirectory` ⇔ `Diagnostics__Import__CheckpointDirectory`).
**Précédence** : `ConnectionStrings:DiagnosticsDatabase` (env
`ConnectionStrings__DiagnosticsDatabase`) **prime** sur `Diagnostics:ConnectionString`.
Toute modification de variable d'environnement d'un service Windows nécessite un
**redémarrage du service** pour être prise en compte.
#### Omika.Api (service `OmikaApi`)
| Variable d'environnement | Clé de configuration | Rôle |
|---|---|---|
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire |
| `MobileAuth__SigningKey` | `MobileAuth:SigningKey` | clé de signature tokens mobile (**fail-fast** en Prod) |
| `DiagnosticsIdentity__HmacKey` | `DiagnosticsIdentity:HmacKey` | clé HMAC ActorKey/DeviceKey (≥ 256 bits Base64) |
| `DiagnosticDeployment__ClientCode` | `DiagnosticDeployment:ClientCode` | override CodeClient (sinon fallback HFSQL) |
| `DiagnosticDeployment__ServerInstanceId` | `DiagnosticDeployment:ServerInstanceId` | id d'instance (sinon `MachineName`) |
| `Observability__Remote__Directory` | `Observability:Remote:Directory` | dossier JSONL (**identique** au Worker) |
| `DiagnosticsForwarding__Enabled` | `DiagnosticsForwarding:Enabled` | kill switch du forwarder central (`true`/`false`) |
| `DiagnosticsForwarding__Endpoint` | `DiagnosticsForwarding:Endpoint` | URL centrale **HTTPS** (si forwarding actif) |
| `DiagnosticsForwarding__ApiKey` | `DiagnosticsForwarding:ApiKey` | clé d'accès centrale (**secret**) |
| `LicenseConnection__*` / `SyncConnection__*` / HFSQL | — | secrets HFSQL existants (non touchés) |
#### Omika.Worker (service `OmikaWorker`)
| Variable d'environnement | Clé de configuration | Rôle |
|---|---|---|
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire |
| `DiagnosticDeployment__ClientCode` | `DiagnosticDeployment:ClientCode` | idem Omika.Api |
| `DiagnosticDeployment__ServerInstanceId` | `DiagnosticDeployment:ServerInstanceId` | idem Omika.Api |
| `SyncConnection__*` / HFSQL | — | secrets HFSQL existants (non touchés) |
#### Omika.Diagnostics.Worker (service `OmikaDiagnosticsWorker`)
| Variable d'environnement | Clé de configuration | Défaut | Rôle |
|---|---|---|---|
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | — | Npgsql `Username=omika_diagnostics_worker` (prime sur ci-dessous) |
| `Diagnostics__ConnectionString` | `Diagnostics:ConnectionString` | `""` | fallback si `ConnectionStrings` absent |
| `Observability__Remote__Directory` | `Observability:Remote:Directory` | `""` | dossier JSONL (**identique** à Omika.Api) |
| `Diagnostics__Import__CheckpointDirectory` | `Diagnostics:Import:CheckpointDirectory` | `""` | dossier checkpoint (sinon = dossier source) |
| `Diagnostics__Import__CheckpointFileName` | `Diagnostics:Import:CheckpointFileName` | `import-checkpoint.json` | nom du checkpoint |
| `Diagnostics__Import__BatchSize` | `Diagnostics:Import:BatchSize` | `100` | taille de lot d'insertion (borné 1..200) |
| `Diagnostics__RetentionDays` | `Diagnostics:RetentionDays` | `60` | rétention en jours (`<=0` = purge désactivée) |
| `Diagnostics__RetentionIntervalHours` | `Diagnostics:RetentionIntervalHours` | `24` | fréquence de purge |
| `Diagnostics__RetentionBatchSize` | `Diagnostics:RetentionBatchSize` | `1000` | lot de suppression (borné) |
| `Diagnostics__CommandTimeoutSeconds` | `Diagnostics:CommandTimeoutSeconds` | `10` | timeout court des commandes |
#### Omika.Diagnostics.Web (service `OmikaDiagnosticsWeb`)
| Variable d'environnement | Clé de configuration | Rôle |
|---|---|---|
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire (default-deny) |
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | Npgsql `Username=omika_diagnostics_web` |
| `DiagnosticsAuth__Operators__0__Username` | `DiagnosticsAuth:Operators:0:Username` | opérateur bootstrap (temporaire) |
| `DiagnosticsAuth__Operators__0__PasswordHash` | `DiagnosticsAuth:Operators:0:PasswordHash` | **hash** bootstrap (jamais en clair) |
| `DiagnosticsAuth__Operators__0__Roles__0` | `DiagnosticsAuth:Operators:0:Roles:0` | `Admin` / `Support` |
| `Diagnostics__RetentionDays` | `Diagnostics:RetentionDays` | `60` (affiché dans l'UI) |
#### Omika.Diagnostics.Api (service `OmikaDiagnosticsApi`) — optionnel
| Variable d'environnement | Clé de configuration | Défaut | Rôle |
|---|---|---|---|
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | — | Npgsql `Username=omika_diagnostics_api` |
| `Diagnostics__Central__Directory` | `Diagnostics:Central:Directory` | `logs/diagnostics-central` | **spool central** (chemin explicite en Prod) |
| `Diagnostics__Central__MaxRequestBodyBytes` | `Diagnostics:Central:MaxRequestBodyBytes` | `524288` | corps de requête borné |
| `Diagnostics__Central__MaxEventsPerBatch` | `Diagnostics:Central:MaxEventsPerBatch` | `100` | événements max par lot |
| `Diagnostics__Central__SchemaVersion` | `Diagnostics:Central:SchemaVersion` | `1` | version du schéma de transport |
**Ports Kestrel** : définis par `appsettings.Production.json` de chaque composant
(`Kestrel:Endpoints:Http:Url` ou `ASPNETCORE_URLS`), en HTTP loopback derrière le
reverse proxy Apache (`https://omika.applilogik.fr`). Aucun port n'est codé en dur
dans le binaire.
---
## 7. Redémarrer (ordre)
Démarrer les **consommateurs avant les producteurs** :
```powershell
Start-Service OmikaDiagnosticsWorker # 1. importeur (consommateur JSONL)
Start-Service OmikaDiagnosticsWeb # 2. UI (lecture)
Start-Service OmikaWorker # 3. sync métier (producteur #2)
Start-Service OmikaApi # 4. API (producteur #1, dernier)
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
# Attendu : les 4 = Running
```
> Si un service passe immédiatement en `Stopped`/`Failed`, ne pas démarrer les
> suivants : diagnostiquer puis rollback si non résolu (§9).
---
## 8. Smoke tests (non destructifs)
```powershell
# Services
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
# API métier
Invoke-WebRequest 'http://127.0.0.1:5080/health' -UseBasicParsing # 200 "Healthy"
# Web Diagnostics (Login)
Invoke-WebRequest 'http://127.0.0.1:<PORT_WEB_DIAG>/Login' -UseBasicParsing # 200
```
Contrôles PostgreSQL après redémarrage :
```sql
SELECT count(*) FROM diagnostic_event;
SELECT max(ingested_at_utc) AS dernier_ingere FROM diagnostic_event;
-- Référentiel (011) :
SELECT reference_type, count(*) FROM diagnostics_reference GROUP BY reference_type;
-- Attendu : SCREEN_CODE = 29, FEATURE_CODE = 3
```
Dans **Diagnostics.Web** : vérifier Dashboard, Diagnostics, Erreurs, Traces,
Synchronisation, Telemetry, Versions, et **Référentiel** (nouvelle fonctionnalité
`011`) ainsi que `/Clients` et `/Users` (Admin).
---
## 9. Rollback
### Binaires
```powershell
Stop-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb -Force
$stamp = '<horodatage_du_backup>' # ex. 20261002-160000
Remove-Item 'C:\Omika\Apps\OmikaApi' -Recurse -Force
Copy-Item "C:\Omika\Backups\OmikaApi_${stamp}" 'C:\Omika\Apps\OmikaApi' -Recurse -Force
Copy-Item "C:\Omika\Backups\OmikaWorker_${stamp}" 'C:\Omika\Apps\OmikaWorker' -Recurse -Force
Copy-Item "C:\Omika\Backups\DiagnosticsWorker_${stamp}" 'C:\Omika\Apps\DiagnosticsWorker' -Recurse -Force
Copy-Item "C:\Omika\Backups\DiagnosticsWeb_${stamp}" 'C:\Omika\Apps\DiagnosticsWeb' -Recurse -Force
Start-Service OmikaDiagnosticsWorker
Start-Service OmikaDiagnosticsWeb
Start-Service OmikaWorker
Start-Service OmikaApi
```
### Base de données
**Pas de rollback SQL automatique** : les migrations `001 → 011` sont **additives**
et idempotentes ; les anciens binaires restent compatibles. Ne jamais `DROP` /
`TRUNCATE` / `DELETE`. Restaurer via `pg_restore` (backup §3.1) uniquement sur
décision humaine explicite et en dernier recours :
```powershell
& 'C:\Program Files\PostgreSQL\18\bin\pg_restore.exe' `
-h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
'C:\Omika\Backups\omika_diagnostics_<stamp>_before_upgrade.backup'
```
---
## 10. Checklist finale
```text
[ ] Publications DEV : 4 composants générés, EXE/DLL présents, pas de secret Dev
[ ] Transfert vers SRV-OMIKA C:\Omika\Deploy\*-next
[ ] pg_dump terminé + taille > 0
[ ] Backup binaires (4 dossiers) présent + complet
[ ] Services arrêtés (4 = Stopped)
[ ] Migrations manquantes identifiées puis appliquées dans l'ordre (ON_ERROR_STOP=1)
[ ] 011 (diagnostics_reference) appliquée ; seed 29 + 3 vérifié
[ ] Mots de passe rôles LOGIN posés manuellement (\password)
[ ] appsettings.json / appsettings.Production.json préservés sur les 4 composants
[ ] JSONL + checkpoint intacts (jamais supprimés)
[ ] Redémarrage dans l'ordre (Worker → Web → OmikaWorker → OmikaApi)
[ ] 4 services Running
[ ] /health Omika.Api = 200 "Healthy" ; /Login DiagnosticsWeb = 200
[ ] Dashboard / Référentiel / Clients / Users fonctionnels
[ ] Rollback prêt (backups binaires + décision DB additive)
```
---
## Références internes
- `docs/DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` — architecture, ports, comptes, secrets.
- `docs/T15-RUNBOOK-DEPLOIEMENT-PRODUCTION.md` — runbook complet (phases détaillées).
- `scripts/publish-diagnostics.ps1` — publication automatisée des composants (poste DEV).
- `infra/deploy/Install-OmikaServerFiles.ps1` — copie statique + sauvegarde + SHA256.
- `infra/deploy/Omika.Deploy.Common.psm1` — module commun (comptes, ACL contrôlées, services, ports).
- `infra/deploy/Install-Omika<Service>.ps1` — **un script par déploiement**
(`OmikaApi`, `OmikaWorker`, `OmikaDiagnosticsApi`, `OmikaDiagnosticsWorker`,
`OmikaDiagnosticsWeb`, `OmikaLanguesApi`) : idempotents, `-WhatIf`, `-Desinstaller`.
- `infra/deploy/Install-OmikaServices.ps1` — orchestrateur : enchaîne les scripts ci-dessus dans l'ordre.
- `infra/deploy/Test-PortDisponible.ps1` — disponibilité d'un port loopback avant configuration.
- `infra/deploy/Install-DatabaseSchema.ps1` — applique `001`+`002` (schéma).
- `infra/deploy/Harden-DatabaseRoles.ps1` — applique `003` (rôles).
- `infra/postgresql/001…011_diagnostics_*.sql` — migrations PostgreSQL.