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

582 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Omika
> **Gestion d'interventions terrain** — application .NET 10 / Avalonia, réécriture moderne de
> l'application WinDev historique **Batik**.
Omika couvre le cycle complet d'une intervention technique : agenda et rendez-vous, dossiers,
clients et sites, interventions et suivi des temps, comptes rendus, documents et photos, courriels,
rapports — sur **poste de bureau, Android et iOS**, avec un fonctionnement **hors ligne** complet et
une synchronisation vers le serveur HFSQL existant.
| | |
|---|---|
| **Langage / runtime** | C# · .NET 10 (`net10.0`) |
| **UI** | Avalonia 12.1.1 (thème Fluent, police Inter) — rendu identique desktop et mobile |
| **MVVM** | CommunityToolkit.Mvvm 8.4.2 |
| **Base locale (mobile)** | SQLite (`Microsoft.Data.Sqlite`) — `omika.db` |
| **Base serveur** | HFSQL Client/Server (PC SOFT) via ODBC / OLE DB |
| **Version** | `1.0.0` build `1` — source unique : `Directory.Build.props` |
| **Éditeur** | Applilogik — `com.applilogik.omika.app` |
---
## Sommaire
1. [Ce que fait Omika](#1-ce-que-fait-omika)
2. [Architecture](#2-architecture)
3. [Les projets](#3-les-projets)
4. [Prérequis](#4-prérequis)
5. [Démarrage rapide](#5-démarrage-rapide)
6. [Configuration](#6-configuration)
7. [Tests](#7-tests)
8. [Publier et déployer](#8-publier-et-déployer)
9. [Observabilité](#9-observabilité)
10. [Traduction hors ligne et packs de langues](#10-traduction-hors-ligne-et-packs-de-langues)
11. [Bases de données](#11-bases-de-données)
12. [Arborescence du dépôt](#12-arborescence-du-dépôt)
13. [Règles d'architecture](#13-règles-darchitecture)
14. [Documentation](#14-documentation)
15. [Dépannage](#15-dépannage)
---
## 1. Ce que fait Omika
### 1.1 Fonctionnel
| Domaine | Contenu |
|---|---|
| **Licence / activation** | Inscription au premier démarrage par code ou **scan de QR** (aperçu caméra), états « connexion requise », « licence expirée ou révoquée ». Attribution et révocation de licence mobile depuis la fiche collaborateur. |
| **Agenda** | Agenda personnel **Jour / Semaine / Mois**, agenda d'équipe avec filtres par équipe et collaborateur. Lecture 100 % locale, aucun appel réseau au chargement. |
| **Rendez-vous** | Fiche complète : contacts, saisie de temps inline, annulation (origine + motif + note), finalisation « Fait ». |
| **Interventions** | Recherche multi-critères (référence, client, site, collaborateur, état, type), onglets « Récentes » et « Épinglées », fiche complète, **création / modification / archivage offline-first**. |
| **Dossiers, clients, sites** | Listes avec recherche et épinglage local, fiches détaillées, **carte géographique** (Mapsui) et lancement d'itinéraire. |
| **Équipe** | Équipes de l'utilisateur, membres, fiches collaborateurs. |
| **Temps et comptes rendus** | Saisie de temps avec gestion de la pause déjeuner, compte rendu individuel ou groupe/journée avec anti-doublon. |
| **Documents et photos** | Téléchargement à la demande, cache hors ligne, ajout offline-first, **éditeur d'image plein écran** (annotation + signature), date réelle lue dans les métadonnées EXIF. |
| **Courriels** | Composition depuis un modèle, un rapport ou un contact, envoi SMTP, brouillons. |
| **Rapports** | Remplissage de modèles DOCX par champs/rubriques. |
| **Synchronisation** | File Outbox, badge du nombre d'opérations en attente, déclenchement manuel, reconstruction de la base locale par **snapshot**. |
| **Paramètres** | Thème clair/sombre/système, couleur principale, compte et licence, limite de poids des photos, horaires de pause, maintenance des données (purge, réinitialisation), export des journaux vers le support. |
| **Traduction hors ligne** | Traduction FR ⇄ 32 langues directement sur l'appareil (ONNX Runtime), sans réseau. |
### 1.2 Principe directeur : offline-first
Toute écriture métier part d'abord dans la **base SQLite locale** et dans l'**Outbox**, puis remonte
au serveur à la première occasion. L'utilisateur n'attend jamais le réseau.
- **Snapshot** : le serveur renvoie une photographie complète des données métier pour reconstruire
la base locale.
- **Outbox** : file locale des changements à pousser, rejouable après coupure.
- **Idempotence** : chaque opération porte un `OperationId` unique ; la rejouer ne produit pas de
doublon.
---
## 2. Architecture
```
┌──────────────────────────────────────────────────────────────────────┐
│ TÉLÉPHONE / POSTE DE BUREAU │
│ │
│ Omika.App.Desktop · Omika.App.Android · Omika.App.iOS │
│ │ hôtes plateformes │
│ ▼ │
│ Omika.App Vues + ViewModels + Navigation + Contrôles │
│ │ │
│ ▼ │
│ Omika.App.Local SQLite (omika.db) + SyncEngine + Outbox │
│ + cache documents + traduction ONNX │
└──────────────────────────────┬───────────────────────────────────────┘
│ HTTP / JSON + Bearer token
▼
┌──────────────────────────────────────────────────────────────────────┐
│ SERVEUR DU CLIENT (HFSQL) │
│ │
│ Omika.Api Web service · licence · bootstrap · snapshot │
│ │ │ sync │
│ ▼ ▼ │
│ Omika.Core (métier) Omika.Worker (application des ops) │
│ │ │ │
│ └────────► Omika.Data (HFSQL par ODBC / OLE DB) ◄───────────┘
└──────────────────────────────┬───────────────────────────────────────┘
│ forwarding HTTPS des diagnostics
▼
┌──────────────────────────────────────────────────────────────────────┐
│ SERVEUR CENTRAL OMIKA │
│ Omika.Diagnostics.Api → Omika.Diagnostics.Worker → PostgreSQL │
│ └──► Omika.Diagnostics.Web │
│ Omika.Langues.Api distribution des modèles de langue (ONNX) │
│ (optionnel) OpenTelemetry → Collector → SigNoz → ClickHouse │
└──────────────────────────────────────────────────────────────────────┘
```
**À retenir :**
- Le **mobile ne parle jamais directement à HFSQL** : il passe toujours par `Omika.Api`.
- Le **desktop** accède à HFSQL **directement** (chemin historique).
- `Omika.Api` **reçoit** les opérations ; `Omika.Worker` les **applique**.
- `Omika.Core` est le cerveau métier ; `Omika.Data` est la seule couche qui touche HFSQL.
- Tout ce qui est **hors** métier (diagnostics, observabilité, langues) est **fail-open** : l'arrêter
ne casse jamais l'application.
---
## 3. Les projets
### 3.1 Projets de la solution (`Omika.slnx`)
| Projet | TFM | Rôle |
|---|---|---|
| `src/Omika.Core` | `net10.0` | **Noyau métier**, sans dépendance UI ni base : entités de domaine, value objects, commands, DTO (`Contracts/`), interfaces, services métier — dont le **cœur serveur de la synchronisation mobile** (`Services/Mobile/` : licence, jetons, bootstrap, snapshot, documents, opérations de sync) — configuration typée, constantes, `Runtime/` (Batik vs Omika), sécurité, politiques d'observabilité. |
| `src/Omika.Data` | `net10.0` | **Accès HFSQL** : options de connexion et validation, connexion ODBC / OLE DB, repositories, mapping, **modèles physiques générés** (Batik 48 tables / Omika 58 tables), migrations Batik → Omika, détection de schéma. |
| `src/Omika.App.Local` | `net10.0` | **Cerveau local du client** : SQLite (`omika.db`), schéma, `SyncEngine`, `OutboxService`, cache documents, un service local par entité, traduction ONNX, licence de développement, diagnostics locaux. |
| `src/Omika.App` | `net10.0` | **Bibliothèque UI partagée** : 38 vues XAML, 48 ViewModels, navigation (`PageViewModelFactory`), contrôles réutilisables (dont la carte), styles, services d'interface. |
| `src/Omika.App.Desktop` | `net10.0` | Hôte **bureau** (`WinExe`, manifeste Windows 10). |
| `src/Omika.App.Android` | `net10.0-android` | Hôte **Android** — min SDK 23, `com.applilogik.omika.app`, format APK, scan QR via ZXing. |
| `src/Omika.App.iOS` | `net10.0-ios` | Hôte **iOS** — min 14.0. **La compilation d'un `.app` exige macOS + Xcode.** |
| `src/Omika.Api` | `net10.0` | **API métier et mobile**, installée chez chaque client : licence, bootstrap, snapshot, sync, documents, courriels, rapports, aide contextuelle. OpenAPI. |
| `src/Omika.Worker` | `net10.0` | **Service de synchronisation** : dépile `TOSRV`, exécute le handler métier, journalise dans `MobLog`. Service Windows. |
| `src/Omika.Observability.External` | `net10.0` | **Seul projet autorisé** à référencer OpenTelemetry : adaptateur OTLP HTTP/protobuf, `RemoteDiagnosticForwarder`, câblage DI. |
| `tests/Omika.Tests` | `net10.0` | Tests xUnit de la solution métier et du client. |
| `tools/Omika.HfSqlProbe` | `net10.0` | Sonde de connexion et d'inspection HFSQL. |
| `tools/HfSqlModelAudit` | `net10.0` | Audit des modèles physiques (attributs de mapping). |
| `tools/HfSqlOleDbAudit` | `net10.0` | Audit du schéma par OLE DB (mode `connection-test` inclus). |
| `tools/Omika.LanguesProbe` | `net10.0` | Validation hors ligne d'un couple de traduction (vocabulaire SentencePiece, paire FR⇄ES). |
### 3.2 Projets compilés hors solution
Ces projets existent, se compilent et se testent, mais **ne sont pas référencés par `Omika.slnx`** :
un `dotnet build Omika.slnx` ne les couvre pas. Les compiler explicitement par leur chemin.
| Projet | TFM | Rôle |
|---|---|---|
| `src/Omika.Diagnostics.Core` | `net10.0` | Modèles, abstractions de repository, importeur JSONL → PostgreSQL. Aucune logique métier. |
| `src/Omika.Diagnostics.Data` | `net10.0` | Persistance PostgreSQL du Diagnostic Center (base dédiée `omika_diagnostics`), Npgsql direct. |
| `src/Omika.Diagnostics.Api` | `net10.0` | API **centrale** : reçoit les lots des serveurs clients, authentifie (`ClientCode` + `ApiKey`), écrit le spool central. |
| `src/Omika.Diagnostics.Worker` | `net10.0` | Import asynchrone du spool central JSONL → PostgreSQL, déduplication par `event_id`, backoff borné. |
| `src/Omika.Diagnostics.Web` | `net10.0` | Interface support (Razor Pages) : Dashboard, Diagnostics, Erreurs, Traces, Synchronisation, Telemetry, Parc, Versions, Référentiel, Utilisateurs, Clients Diagnostics, Système, Mon compte. |
| `src/Omika.Langues.Api` | `net10.0` | Service **stateless** de distribution des modèles de langue ONNX (`/api/langues`, `/api/langues/{code}/{sens}/{fichier}`). Sans base ni authentification. |
| `tests/Omika.Diagnostics.Tests` | `net10.0` | Tests du Diagnostic Center (faux repositories, PostgreSQL simulé en panne, mappers, checkpoint, sécurité, pagination). |
| `tools/*` (21 autres) | `net10.0` | Sondes de diagnostic : `ClientSnapshotProbe`, `CollaborateurBulkProbe`, `CountProbe`, `DiagnosticHashTool`, `FileAccessProbe`, `FilePasswordProbe`, `IdempotenceProbe`, `IdentityProbe`, `LieuProbe`, `MessageExterneProbe`, `OleDbSchemaProbe`, `RdvProbeJour`, `RendezVousBulkProbe`, `RendezVousProbe`, `SiteSnapshotProbe`, `SmtpMobileConfigProbe`, `SmtpRealProbe`, `StatusProbe`, `TosrvProbe`, `Verif.Dictee`, `Verif.Langues`. |
---
## 4. Prérequis
| Besoin | Détail |
|---|---|
| **.NET SDK 10** | SDK de référence : **10.0.302** (voir `global.json.bak`). Le dépôt ne contient pas encore de `global.json` actif : renommer le `.bak` si vous voulez figer la version. |
| **Workloads mobiles** | `dotnet workload install android` pour l'APK. iOS demande **macOS + Xcode**. |
| **Serveur HFSQL** | HFSQL Client/Server (port **4900**) + pilote ODBC « HFSQL Client/Server », pour le développement local et les tests d'intégration. |
| **Windows** | Requis pour le client desktop (OLE DB, manifeste Windows) et pour les services Windows déployés. |
| **PostgreSQL** | Uniquement pour le Diagnostic Center (`omika_diagnostics`). Optionnel pour le métier. |
| **Docker** | Uniquement pour la pile d'observabilité externe (optionnelle). |
Packages : gestion **centralisée** via `Directory.Packages.props`. Les `.csproj` référencent les
packages **sans version** — ne jamais ajouter de `Version=` dans un `.csproj`.
---
## 5. Démarrage rapide
### 5.1 Tout-en-un (mode test local)
Les scripts de `docs/` compilent et lancent les trois composants (API, Worker, desktop) :
```powershell
# Compiler (arrête les processus Omika en cours pour libérer les DLL)
powershell -NoProfile -ExecutionPolicy Bypass -File .\docs\build_omika_test.ps1
# Lancer : API (http://localhost:5097) + Worker + application de bureau
powershell -NoProfile -ExecutionPolicy Bypass -File .\docs\start_omika_test.ps1 -NoBuild
# Arrêter
powershell -NoProfile -ExecutionPolicy Bypass -File .\docs\stop_omika_test.ps1
```
Options utiles de `start_omika_test.ps1` :
| Option | Effet |
|---|---|
| `-NoBuild` | Ne pas recompiler. |
| `-SkipDesktop` | Lancer seulement l'API et le Worker. |
| `-SkipWorker` | Lancer seulement l'API et le desktop. |
| `-Clean` | Purger `omika.db` et `omika-diagnostics.db` avant lancement (changement d'environnement). |
Le script crée automatiquement, si absent, le fichier de licence de développement
`%LOCALAPPDATA%\Omika\development-license.json` :
```json
{
"Enabled": true,
"ClientCode": "LOCAL-DEV",
"UserDisplayName": "<nom affiché>",
"ExpirationDays": 365,
"ApiUrl": "http://localhost:5097"
}
```
### 5.2 Commandes `dotnet` directes
```powershell
# Restauration
dotnet restore .\Omika.slnx
# Compiler toute la solution (client + API + Worker + bibliothèques + tests + 4 outils)
dotnet build .\Omika.slnx
# Composants pris isolément
dotnet build .\src\Omika.Api\Omika.Api.csproj
dotnet build .\src\Omika.Worker\Omika.Worker.csproj
dotnet build .\src\Omika.App.Desktop\Omika.App.Desktop.csproj
dotnet build .\src\Omika.App.Android\Omika.App.Android.csproj # APK
dotnet build .\src\Omika.App.iOS\Omika.App.iOS.csproj # macOS + Xcode requis
# Projets hors solution
dotnet build .\src\Omika.Diagnostics.Web\Omika.Diagnostics.Web.csproj
dotnet build .\src\Omika.Langues.Api\Omika.Langues.Api.csproj
# Lancer
dotnet run --project .\src\Omika.Api\Omika.Api.csproj # http://localhost:5097/health
dotnet run --project .\src\Omika.Worker\Omika.Worker.csproj
dotnet run --project .\src\Omika.App.Desktop\Omika.App.Desktop.csproj
```
### 5.3 Ports de développement
| Service | Port |
|---|---|
| `Omika.Api` | **5097** (HTTP) · 7160 (HTTPS) |
| `Omika.Diagnostics.Api` | **5098** |
| `Omika.Diagnostics.Web` | **5080** |
| `Omika.Langues.Api` | **5099** (derrière Apache sur `/langues/`) |
| HFSQL Client/Server | **4900** |
En production, Kestrel reste en **HTTP sur loopback** ; l'exposition HTTPS est assurée par un
reverse proxy **Apache**.
---
## 6. Configuration
### 6.1 `config/hfsql-test.local.json` — non versionné
Les `appsettings.json` ne contiennent que des **placeholders** (hôtes `localhost`, mots de passe
vides). Les vraies connexions de test vivent dans `config/hfsql-test.local.json`, **exclu du dépôt**
par `.gitignore` (`/config/`).
Le fichier est chargé par `HfSqlTestConfigurationLoader` **uniquement** en environnement
`Development` ou `Test`, jamais en `Production`, et les **variables d'environnement restent
prioritaires**. Il est localisé de deux façons :
1. variable d'environnement `OMIKA_HFSQL_TEST_CONFIG` = chemin explicite (fait foi) ;
2. sinon, `config/hfsql-test.local.json` en remontant jusqu'à 6 niveaux depuis le répertoire courant.
Structure attendue pour reconstituer ce fichier :
```json
{
"Server": "<serveur HFSQL>",
"Port": 4900,
"FilePasswords": { "ProtectionStd": "", "ProtectionPlus": "" },
"Batik": { "Database": "", "User": "", "Credential": "" },
"Omika": { "DatabaseVersion": "Auto", "Database": "", "User": "", "Credential": "" },
"Hfsql": {
"ConnectionName": "Business", "Server": "", "Port": 4900, "DatabaseName": "",
"Login": "", "Password": "", "Driver": "HFSQL Client/Server",
"ConnectionTimeoutSeconds": 30,
"FilePasswords": { "ProtectionStd": "", "ProtectionPlus": "" }
},
"LicenseConnection": { "Server": "", "Port": 4900, "DatabaseName": "Licence", "Login": "", "Password": "", "FilePasswords": { "ProtectionStd": "", "ProtectionPlus": "" } },
"SyncConnection": { "Server": "", "Port": 4900, "DatabaseName": "Sync", "Login": "", "Password": "", "FilePasswords": { "ProtectionStd": "", "ProtectionPlus": "" } },
"ServiceConnection": { "Server": "", "Port": 4900, "DatabaseName": "", "Login": "", "Password": "", "FilePasswords": { "ProtectionStd": "", "ProtectionPlus": "" } },
"MobileAuth": { "SigningKey": "" },
"DevelopmentAuth": { "Enabled": true, "DevCollaborateurPkId": 0, "DevCodeClient": "" },
"E2E": { "AllowHfSqlWrites": false, "ServiceDatabaseConfirmedTest": false, "WebServiceDatabaseConfirmedTest": false }
}
```
> **Garde-fou E2E** : `E2E:AllowHfSqlWrites` doit rester à `false`. Il n'est activé que
> temporairement, et explicitement, pour un test end-to-end qui écrit réellement dans HFSQL.
### 6.2 Variables d'environnement
La convention .NET `__` (double souligné) permet de surcharger n'importe quelle clé :
```powershell
$env:ASPNETCORE_ENVIRONMENT = 'Development' # charge config/hfsql-test.local.json
$env:DOTNET_ENVIRONMENT = 'Development'
$env:ASPNETCORE_URLS = 'http://localhost:5097'
$env:Omika__DatabaseVersion = 'Auto' # Auto | Batik | Omika
$env:Sync__RetryDelaySeconds = '5' # accélère le Worker en test E2E
$env:OMIKA_HFSQL_TEST_CONFIG = 'D:\chemin\vers\hfsql-test.local.json'
$env:DiagnosticsForwarding__ApiKey = '<secret>' # serveur client, jamais dans un fichier versionné
```
### 6.3 Sélection de base : Batik ou Omika
Deux notions distinctes, à ne pas confondre :
- **`DatabaseSchemaSelection`** (`Omika:DatabaseVersion`) — la sélection **demandée** :
`Auto` (détection automatique, défaut sûr), `Batik` (forcer l'ancienne base), `Omika` (forcer la
nouvelle).
- **`DatabaseSchemaVersion`** — la version **réellement détectée**. Tant que la détection n'a pas eu
lieu, elle reste `Unknown`, même si une sélection forcée est configurée. En mode forcé, une base
détectée différente provoque un échec explicite.
### 6.4 Secrets — ce qui ne doit jamais être versionné
| Fichier / clé | Statut |
|---|---|
| `config/*.local.json` | **Exclu.** Contient les identifiants HFSQL réels (dont mots de passe de fichiers). |
| `src/Omika.Diagnostics.Web/appsettings.Development.json` | **Exclu.** Contient un `PasswordHash` d'administrateur local. |
| `appsettings.*.local.json`, `secrets.json`, `.env`, `*.pfx`, `*.p12`, `*.key` | **Exclus.** |
| `DiagnosticsForwarding:ApiKey`, `MobileAuth:SigningKey`, `DiagnosticsIdentity:HmacKey`, `Diagnostics:ConnectionString` | **Vides dans les fichiers versionnés.** Injectés sur le serveur par variables d'environnement. |
---
## 7. Tests
```powershell
# Tests métier et client (~3 400 tests)
dotnet test .\tests\Omika.Tests\Omika.Tests.csproj
# Tests du Diagnostic Center (~540 tests, sans PostgreSQL réel)
dotnet test .\tests\Omika.Diagnostics.Tests\Omika.Diagnostics.Tests.csproj
# Tests internes d'un outil
dotnet test .\tools\HfSqlOleDbAudit\tests\HfSqlOleDbAudit.Tests\HfSqlOleDbAudit.Tests.csproj
```
**Échecs attendus hors environnement complet** — ce ne sont pas des régressions :
| Type | Cause |
|---|---|
| Tests HFSQL / OLE DB | Exigent un serveur HFSQL réel et `config/hfsql-test.local.json`. Ils se désactivent d'eux-mêmes si le fichier est absent. |
| Tests Avalonia headless | Peuvent échouer selon la configuration graphique de la machine. |
| `DevelopmentLicenseTests` en **Release** | Le contournement de licence de développement est compilé en `#if DEBUG` : comportement voulu. |
**Vérifications hors xUnit** — deux outils rejouent des tests sans `testhost` (contournement d'un
`Win32Exception 5` sur certains postes) :
```powershell
dotnet run --project .\tools\Omika.Verif.Dictee
dotnet run --project .\tools\Omika.Verif.Langues
```
---
## 8. Publier et déployer
Les scripts de `infra/deploy/` installent les services **Windows**. Chacun accepte une simulation
(`-WhatIf` / `-Simulation`) et s'appuie sur le module commun `Omika.Deploy.Common.psm1`.
| Script | Service Windows créé |
|---|---|
| `Install-OmikaApi.ps1` | `OmikaApi` |
| `Install-OmikaWorker.ps1` | `OmikaWorker` |
| `Install-OmikaLanguesApi.ps1` | `OmikaLanguesApi` |
| `Install-OmikaDiagnosticsApi.ps1` | `OmikaDiagnosticsApi` |
| `Install-OmikaDiagnosticsWorker.ps1` | `OmikaDiagnosticsWorker` |
| `Install-OmikaDiagnosticsWeb.ps1` | `OmikaDiagnosticsWeb` |
| `Install-OmikaServices.ps1` | Orchestration de l'ensemble |
| `Install-OmikaServerFiles.ps1` | Arborescence serveur (données, documents, journaux) |
| `Install-DatabaseSchema.ps1` | Application des migrations PostgreSQL `001` → `016` |
| `Harden-DatabaseRoles.ps1` | Rôles et droits PostgreSQL |
| `New-OmikaLanguesManifeste.ps1` | Manifeste des packs de langues à distribuer |
| `Test-PortDisponible.ps1` | Contrôle de disponibilité des ports |
Le schéma PostgreSQL vit dans `infra/postgresql/` : appliquer les migrations **dans l'ordre**
(`001_diagnostics_schema.sql` → `016_diagnostics_event_delete.sql`). Elles sont idempotentes.
Procédures détaillées :
- `docs/DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` — déploiement du Diagnostic Center, rôles, ports,
bootstrap du premier administrateur.
- `docs/T15-RUNBOOK-DEPLOIEMENT-PRODUCTION.md` — runbook de mise en production.
- `docs/DEPLOIEMENT_API_LANGUES.md` — API de distribution des modèles de langue.
- `infra/deploy/tests/` — tests des scripts de déploiement.
---
## 9. Observabilité
Trois niveaux, **durables et fail-open** :
1. **Journaux locaux JSONL** — `logs/` côté serveur, base `omika-diagnostics.db` côté appareil.
2. **Diagnostic Center** — remontée des diagnostics vers le serveur central
(`Omika.Diagnostics.Api` → spool → `Omika.Diagnostics.Worker` → PostgreSQL →
`Omika.Diagnostics.Web`).
3. **OpenTelemetry (optionnel)** — `Observability:External:Enabled=false` par défaut. Activable vers
un Collector OTLP HTTP/protobuf (port 4318) puis SigNoz / ClickHouse.
> **Règle absolue** : *les journaux servent Omika, Omika ne dépend jamais des journaux.* Arrêter le
> Collector, SigNoz, ClickHouse ou PostgreSQL Diagnostics ne casse **jamais** le métier.
Pile de référence : `infra/observability/docker-compose.yml` + `otel-collector-config.yaml`.
Documentation : `docs/observability/` (configuration, déploiement, guide support, données exportées,
procédure de débranchement).
Le flux mobile ne passe **jamais** par OTLP : `Mobile → POST /api/diagnostics → spool JSONL serveur
→ ACK`, le forwarding externe étant asynchrone et best-effort **après** l'acquittement.
---
## 10. Traduction hors ligne et packs de langues
La traduction FR ⇄ 32 langues s'exécute **sur l'appareil** via `Microsoft.ML.OnnxRuntime`
(SentencePiece + modèles encodeur/décodeur). Le moteur n'est compilé que si le symbole
`OMIKA_ONNX_RUNTIME` est défini — il l'est dans `Omika.App.Local.csproj`. Sans lui, la traduction
répond « indisponible ».
Les modèles (`*.onnx`, `*.spm`, environ 0,5 à 1,1 Go **par langue**) sont **hors dépôt** :
| Élément | Statut |
|---|---|
| `packs/` (≈ 26 Go, 32 langues × `commun` / `versFrancais` / `depuisFrancais`) | **Non versionné.** Distribué par `Omika.Langues.Api` / GitHub Releases. |
| `packs.zip` (≈ 23 Go) | **Non versionné.** |
| `tests/fixtures/sentencepiece/*.spm`, `encoder.onnx` | **Non versionnés** — seuls les `<modele>.fixtures.json` le sont. Les tests se désactivent silencieusement en leur absence. |
Régénération des packs :
```powershell
.\scripts\Exporter-Packs-Langues.ps1 # export des packs
.\scripts\Completer-Packs-Langues.ps1 # complétion des langues manquantes
.\scripts\Generer-Fixtures-SentencePiece.ps1
```
Voir `docs/TRADUCTION_HORS_LIGNE_MOBILE.md`, `docs/LIVRAISON_MODELES_LANGUES.md` et
`docs/VALIDATION_TRADUCTION_ONNX.md`.
---
## 11. Bases de données
| Base | Technologie | Rôle |
|---|---|---|
| **HFSQL « Batik »** | HFSQL C/S (48 tables) | Ancienne base WINDEV, toujours lue et écrite. |
| **HFSQL « Omika »** | HFSQL C/S (58 tables) | Nouvelle base cible. |
| **`Licence`** | HFSQL C/S | Licences et inscriptions. |
| **`Sync`** | HFSQL C/S (`TOSRV`, `MobReception`, `MobLog`) | File d'opérations de synchronisation. |
| **`omika.db`** | SQLite | Base locale de l'appareil (offline-first). |
| **`omika-diagnostics.db`** | SQLite | Diagnostics locaux de l'appareil. |
| **`omika_diagnostics`** | PostgreSQL | Diagnostic Center central. |
> **Règle d'or** : la base HFSQL existante **n'est jamais modifiée**. Aucune table n'est créée,
> supprimée ni altérée par le nouveau code — il ne fait que lire et écrire dans le schéma existant.
> Les migrations présentes dans `Omika.Data/Migrations` concernent la **compatibilité des données**
> Batik → Omika, pas la structure.
Le dictionnaire machine-readable du schéma est `docs/schema-compatibilite-batik-omika.json`
(582 Ko) ; les 106 modèles physiques de `src/Omika.Data/HfSql/Models/` en sont générés.
---
## 12. Arborescence du dépôt
```
Omika.slnx Solution (format .slnx) — 15 projets
Directory.Build.props Version unique : OmikaVersion 1.0.0 / OmikaBuild 1
Directory.Packages.props Gestion centralisée des versions NuGet
.gitignore Exclusions (build, secrets, runtime, packs, Batik)
fix-sdk-locators.ps1 Correctif MSB4276 (poste de développement, admin)
src/ Code source (16 projets)
Omika.Core/ Métier, contrats, services (dont sync mobile)
Omika.Data/ HFSQL : connexion, repositories, mapping, migrations
Omika.App.Local/ SQLite, SyncEngine, Outbox, traduction ONNX
Omika.App/ UI Avalonia partagée (Views, ViewModels, Navigation)
Omika.App.Desktop/ Hôte bureau
Omika.App.Android/ Hôte Android
Omika.App.iOS/ Hôte iOS
Omika.Api/ API métier et mobile
Omika.Worker/ Service de synchronisation
Omika.Observability.External/ Adaptateur OpenTelemetry (isolé)
Omika.Diagnostics.*/ Diagnostic Center (Core, Data, Api, Worker, Web)
Omika.Langues.Api/ Distribution des modèles de langue
tests/
Omika.Tests/ Tests métier et client (~3 400)
Omika.Diagnostics.Tests/ Tests du Diagnostic Center (~540)
fixtures/sentencepiece/ Fixtures de traduction (LISEZMOI + *.fixtures.json)
tools/ 25 sondes console de diagnostic
docs/ Documentation (~64 documents)
infra/
deploy/ Scripts d'installation des services Windows
postgresql/ Migrations 001 → 016
observability/ Pile OTel / SigNoz / ClickHouse (optionnelle)
collector/ Exemple de configuration collector
scripts/ Export des packs de langues, seeds, publication
config/ Secrets locaux — NON versionné
packs/ Modèles de langue ONNX (≈ 26 Go) — NON versionné
Batik/ Projet WinDev historique — NON versionné
artifacts/ Sorties de publication — NON versionné
logs/ Journaux runtime — NON versionné
```
---
## 13. Règles d'architecture
Ces règles sont **vérifiées par des tests** dans `tests/Omika.Tests/Architecture/` :
1. **`Omika.Core` ne référence ni Avalonia, ni ASP.NET Core, ni `Omika.Data`.**
C'est le noyau partagé, sans dépendance technique.
2. **Le métier ne référence jamais OpenTelemetry.** Les packages OTel sont confinés à
`Omika.Observability.External` ; seules des politiques pures vivent dans `Core`.
3. **L'UI ne référence jamais `Omika.Data`.** L'application passe par l'API (HTTP) ou par
`Omika.App.Local`.
4. **Les contrats publics ne contiennent ni nom de table HFSQL, ni champ « zombie ».** Les DTO
exposés ne laissent pas fuiter le schéma physique.
5. **`Omika.Data` est la seule couche qui parle HFSQL.**
6. **Résultats d'opération** : les services renvoient `Result` / `Result<T>` plutôt que de lever des
exceptions pour les cas métier.
7. **Pas de conteneur DI dans l'UI partagée** : une composition racine manuelle unique
(`AppServices.cs`).
8. **Hors métier = fail-open.** Diagnostics, observabilité, distribution des langues : leur
indisponibilité ne doit jamais dégrader l'application.
---
## 14. Documentation
| Document | Contenu |
|---|---|
| `docs/ARCHITECTURE_PROJET.md` | **Guide complet** : rôle de chaque projet, flux, où chercher quand un bug apparaît. Le meilleur point d'entrée. |
| `docs/architecture-solution.md` | Architecture initiale de la solution, conventions, gestion de la base Batik/Omika. |
| `docs/LOT_MOBILE_0.md` | Architecture technique mobile : offline-first, SQLite, sync, identités, design system. |
| `docs/MOBILE_FUNCTIONAL_STATUS.md` | État fonctionnel réel de l'application mobile, écran par écran. |
| `docs/E2E_SYNC_VALIDATION.md` | Validation end-to-end du pipeline de synchronisation. |
| `docs/TRADUCTION_HORS_LIGNE_MOBILE.md` | Traduction ONNX embarquée. |
| `docs/DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` | Déploiement multi-serveurs du Diagnostic Center. |
| `docs/T15-RUNBOOK-DEPLOIEMENT-PRODUCTION.md` | Runbook de mise en production. |
| `docs/dictionnaire-compatibilite-batik-omika.md` | Dictionnaire de compatibilité des schémas. |
| `docs/observability/` | Observabilité externe (configuration, déploiement, support, débranchement). |
| `docs/BATIK.md`, `docs/OMIKA.md`, `docs/Documentation_*.md` | **Exports WINDEV de l'ancien système** — référence historique uniquement. |
| `ANALYSE-OMIKA-APP.md` | Analyse technique complète de l'application (écrans, pile, limites). |
| `ANALYSE_OMIKA_BATIK/` | Études comparatives Batik / Omika. |
---
## 15. Dépannage
| Symptôme | Cause probable / solution |
|---|---|
| **MSB4276** à la compilation | Workload Android/iOS corrompu sur le poste. Contournement utilisé par les scripts : `dotnet build <projet> --no-restore -m:1`. Solution durable : `dotnet workload repair`, ou exécuter `fix-sdk-locators.ps1` **en administrateur**. |
| **MSB3027** (fichier verrouillé) | Une instance d'Omika tourne encore. `stop_omika_test.ps1`, ou `build_omika_test.ps1` sans `-NoStop`. |
| L'API démarre mais les données sont vides | `config/hfsql-test.local.json` absent ou non résolu. Vérifier `OMIKA_HFSQL_TEST_CONFIG`, et que `ASPNETCORE_ENVIRONMENT=Development`. |
| Traduction « indisponible » | Le symbole `OMIKA_ONNX_RUNTIME` n'est pas défini, ou les modèles de langue ne sont pas installés sur l'appareil. |
| `omika.db` contient des données de la mauvaise base | Relancer avec `start_omika_test.ps1 -Clean` après un changement Batik ⇄ Omika. |
| Le Worker ne traite pas les opérations | Vérifier la connexion `SyncConnection` et la table `TOSRV`. En test E2E, `Sync__RetryDelaySeconds=5` accélère la boucle. |
| Diagnostics.Web : pages « indisponible » | PostgreSQL est en panne. **Comportement attendu** (fail-open) : l'outil support ne bloque jamais le métier. |
| `dotnet build Omika.slnx` ne compile pas les Diagnostics | Normal : ces projets sont **hors solution**. Les compiler par leur chemin explicite. |
| L'application Android ne se compile pas | `dotnet workload install android`. iOS exige macOS + Xcode. |
---
## Licence
Projet propriétaire — © Applilogik. Tous droits réservés.