gateway-llm 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. gateway_llm-0.1.0/.github/workflows/ci.yml +97 -0
  2. gateway_llm-0.1.0/.github/workflows/secret-scan.yml +29 -0
  3. gateway_llm-0.1.0/.github/workflows/update-benchmarks.yml +48 -0
  4. gateway_llm-0.1.0/.gitignore +84 -0
  5. gateway_llm-0.1.0/CHANGELOG.md +202 -0
  6. gateway_llm-0.1.0/CONTRIBUTING.md +330 -0
  7. gateway_llm-0.1.0/LICENSE.txt +202 -0
  8. gateway_llm-0.1.0/PKG-INFO +348 -0
  9. gateway_llm-0.1.0/README.MD +314 -0
  10. gateway_llm-0.1.0/README.md +314 -0
  11. gateway_llm-0.1.0/benchmarks_cache/f5_safety.json +6 -0
  12. gateway_llm-0.1.0/benchmarks_cache/rws_translation.json +6 -0
  13. gateway_llm-0.1.0/config/models.example.yaml +105 -0
  14. gateway_llm-0.1.0/config/policy.example.yaml +26 -0
  15. gateway_llm-0.1.0/docs/GUIDE_EN.md +103 -0
  16. gateway_llm-0.1.0/docs/GUIDE_FR.md +103 -0
  17. gateway_llm-0.1.0/docs/THREAT_MODEL.md +201 -0
  18. gateway_llm-0.1.0/pyproject.toml +115 -0
  19. gateway_llm-0.1.0/scripts/refresh.py +101 -0
  20. gateway_llm-0.1.0/scripts/refresh_rws.py +106 -0
  21. gateway_llm-0.1.0/src/gateway_llm/__init__.py +80 -0
  22. gateway_llm-0.1.0/src/gateway_llm/batch.py +487 -0
  23. gateway_llm-0.1.0/src/gateway_llm/benchmarks/__init__.py +0 -0
  24. gateway_llm-0.1.0/src/gateway_llm/benchmarks/aggregator.py +75 -0
  25. gateway_llm-0.1.0/src/gateway_llm/benchmarks/base.py +49 -0
  26. gateway_llm-0.1.0/src/gateway_llm/benchmarks/benchlm.py +75 -0
  27. gateway_llm-0.1.0/src/gateway_llm/benchmarks/cache.py +58 -0
  28. gateway_llm-0.1.0/src/gateway_llm/benchmarks/f5_safety.py +65 -0
  29. gateway_llm-0.1.0/src/gateway_llm/benchmarks/normalizer.py +54 -0
  30. gateway_llm-0.1.0/src/gateway_llm/benchmarks/rankllms.py +67 -0
  31. gateway_llm-0.1.0/src/gateway_llm/benchmarks/rws_translation.py +55 -0
  32. gateway_llm-0.1.0/src/gateway_llm/budget.py +81 -0
  33. gateway_llm-0.1.0/src/gateway_llm/checkpoint.py +57 -0
  34. gateway_llm-0.1.0/src/gateway_llm/classifier.py +232 -0
  35. gateway_llm-0.1.0/src/gateway_llm/cli.py +654 -0
  36. gateway_llm-0.1.0/src/gateway_llm/config.py +93 -0
  37. gateway_llm-0.1.0/src/gateway_llm/doctor.py +241 -0
  38. gateway_llm-0.1.0/src/gateway_llm/guardrails/__init__.py +9 -0
  39. gateway_llm-0.1.0/src/gateway_llm/guardrails/base.py +51 -0
  40. gateway_llm-0.1.0/src/gateway_llm/guardrails/nemo.py +88 -0
  41. gateway_llm-0.1.0/src/gateway_llm/guardrails/noop.py +21 -0
  42. gateway_llm-0.1.0/src/gateway_llm/gui.py +604 -0
  43. gateway_llm-0.1.0/src/gateway_llm/hardware.py +114 -0
  44. gateway_llm-0.1.0/src/gateway_llm/installer.py +106 -0
  45. gateway_llm-0.1.0/src/gateway_llm/intake.py +224 -0
  46. gateway_llm-0.1.0/src/gateway_llm/logging.py +68 -0
  47. gateway_llm-0.1.0/src/gateway_llm/policy.py +64 -0
  48. gateway_llm-0.1.0/src/gateway_llm/providers/base.py +64 -0
  49. gateway_llm-0.1.0/src/gateway_llm/providers/cloudflare.py +84 -0
  50. gateway_llm-0.1.0/src/gateway_llm/providers/ollama.py +75 -0
  51. gateway_llm-0.1.0/src/gateway_llm/providers/openai_compat.py +111 -0
  52. gateway_llm-0.1.0/src/gateway_llm/quota.py +49 -0
  53. gateway_llm-0.1.0/src/gateway_llm/router.py +228 -0
  54. gateway_llm-0.1.0/src/gateway_llm/secrets.py +339 -0
  55. gateway_llm-0.1.0/tests/__init__.py +0 -0
  56. gateway_llm-0.1.0/tests/conftest.py +32 -0
  57. gateway_llm-0.1.0/tests/fixtures/.gitkeep +0 -0
  58. gateway_llm-0.1.0/tests/helpers.py +37 -0
  59. gateway_llm-0.1.0/tests/test_budget.py +106 -0
  60. gateway_llm-0.1.0/tests/test_classifier.py +162 -0
  61. gateway_llm-0.1.0/tests/test_doctor.py +147 -0
  62. gateway_llm-0.1.0/tests/test_guardrails.py +128 -0
  63. gateway_llm-0.1.0/tests/test_installer.py +81 -0
  64. gateway_llm-0.1.0/tests/test_policy.py +132 -0
  65. gateway_llm-0.1.0/tests/test_providers.py +197 -0
  66. gateway_llm-0.1.0/tests/test_quota.py +82 -0
  67. gateway_llm-0.1.0/tests/test_router.py +275 -0
  68. gateway_llm-0.1.0/tests/test_security.py +338 -0
@@ -0,0 +1,97 @@
1
+ # SPDX-FileCopyrightText: 2026 Amandine Dennieau
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: CI
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ branches: [main]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ test:
17
+ name: Tests (Python ${{ matrix.python-version }})
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ python-version: ["3.11", "3.12", "3.13"]
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: ${{ matrix.python-version }}
29
+ cache: pip
30
+
31
+ - name: Installer (sans guardrails)
32
+ run: |
33
+ python -m pip install --upgrade pip
34
+ pip install -e ".[dev]"
35
+
36
+ - name: Pytest
37
+ run: pytest tests/ -v --cov=gateway_llm --cov-report=term-missing
38
+
39
+ test-guardrails:
40
+ name: Tests avec NeMo Guardrails
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: actions/setup-python@v5
45
+ with:
46
+ python-version: "3.12"
47
+ cache: pip
48
+ - name: Installer avec extra [guardrails]
49
+ run: |
50
+ python -m pip install --upgrade pip
51
+ pip install -e ".[dev,guardrails]"
52
+ - name: Pytest
53
+ run: pytest tests/ -v -m "guardrails or not guardrails"
54
+
55
+ lint:
56
+ name: Lint (ruff)
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+ - uses: actions/setup-python@v5
61
+ with:
62
+ python-version: "3.12"
63
+ cache: pip
64
+ - run: pip install ruff
65
+ - run: ruff check src/ tests/
66
+ - run: ruff format --check src/ tests/
67
+
68
+ typecheck:
69
+ name: Type check (mypy)
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+ - uses: actions/setup-python@v5
74
+ with:
75
+ python-version: "3.12"
76
+ cache: pip
77
+ - run: |
78
+ pip install -e ".[dev]"
79
+ - run: mypy src/
80
+
81
+ security:
82
+ name: Sécurité (bandit + pip-audit)
83
+ runs-on: ubuntu-latest
84
+ steps:
85
+ - uses: actions/checkout@v4
86
+ - uses: actions/setup-python@v5
87
+ with:
88
+ python-version: "3.12"
89
+ cache: pip
90
+ - name: Installer
91
+ run: |
92
+ pip install bandit pip-audit
93
+ pip install -e .
94
+ - name: Bandit
95
+ run: bandit -r src/ -c pyproject.toml
96
+ - name: pip-audit
97
+ run: pip-audit --strict --progress-spinner=off
@@ -0,0 +1,29 @@
1
+ # SPDX-FileCopyrightText: 2026 Amandine Dennieau
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Secret Scan
5
+
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ pull_request:
10
+ schedule:
11
+ - cron: "0 3 * * 1" # chaque lundi 3h UTC
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ gitleaks:
18
+ name: Gitleaks
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ - name: Télécharger gitleaks
25
+ run: |
26
+ curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz \
27
+ | tar -xz -C /usr/local/bin gitleaks
28
+ - name: Scanner
29
+ run: gitleaks detect --source . --verbose --redact
@@ -0,0 +1,48 @@
1
+ # SPDX-FileCopyrightText: 2026 Amandine Dennieau
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Update Benchmarks (F5 / RWS)
5
+
6
+ on:
7
+ schedule:
8
+ - cron: "0 4 */14 * *" # tous les 14 jours à 4h UTC
9
+ workflow_dispatch: # manuel possible
10
+
11
+ permissions:
12
+ contents: write
13
+
14
+ jobs:
15
+ update:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ token: ${{ secrets.GITHUB_TOKEN }}
21
+
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.12"
25
+ cache: pip
26
+
27
+ - name: Installer dépendances de scraping
28
+ run: pip install requests beautifulsoup4
29
+
30
+ - name: Rafraîchir F5
31
+ continue-on-error: true
32
+ run: python scripts/refresh_f5.py
33
+
34
+ - name: Rafraîchir RWS
35
+ continue-on-error: true
36
+ run: python scripts/refresh_rws.py
37
+
38
+ - name: Commit si changements
39
+ run: |
40
+ git config user.name "gateway-llm-bot"
41
+ git config user.email "bot@users.noreply.github.com"
42
+ git add benchmarks_cache/f5_safety.json benchmarks_cache/rws_translation.json || true
43
+ if git diff --cached --quiet; then
44
+ echo "Aucun changement, skip commit."
45
+ else
46
+ git commit -m "chore: auto-update F5/RWS benchmarks ($(date +%Y-%m-%d))"
47
+ git push
48
+ fi
@@ -0,0 +1,84 @@
1
+ # SPDX-FileCopyrightText: 2026 Amandine Dennieau
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0.
5
+
6
+ # ─── Python byte-compiled / cache ────────────────────────────────
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ *.so
11
+
12
+ # ─── Distribution / packaging ────────────────────────────────────
13
+ .Python
14
+ build/
15
+ dist/
16
+ *.egg-info/
17
+ *.egg
18
+ .eggs/
19
+ wheels/
20
+
21
+ # ─── Environnements virtuels ─────────────────────────────────────
22
+ .venv/
23
+ venv/
24
+ env/
25
+ ENV/
26
+
27
+ # ─── Tests & couverture ──────────────────────────────────────────
28
+ .pytest_cache/
29
+ .coverage
30
+ .coverage.*
31
+ htmlcov/
32
+ coverage.xml
33
+ .tox/
34
+ .nox/
35
+
36
+ # ─── Linters & typage ────────────────────────────────────────────
37
+ .mypy_cache/
38
+ .ruff_cache/
39
+ .dmypy.json
40
+
41
+ # ─── IDE / éditeurs ──────────────────────────────────────────────
42
+ .idea/
43
+ .vscode/
44
+ *.swp
45
+ *~
46
+ *.code-workspace
47
+
48
+ # ─── Secrets & config locale ─────────────────────────────────────
49
+ .env
50
+ .env.*
51
+ !.env.example
52
+ config/models.yaml
53
+ config/policy.yaml
54
+ secrets.yaml
55
+ *.key
56
+ *.pem
57
+ *.p12
58
+
59
+ # ─── Données locales de batch (I/O) ──────────────────────────────
60
+ data/
61
+ inputs/
62
+ outputs/
63
+ reports/
64
+ *.jsonl
65
+ !tests/fixtures/*.jsonl
66
+
67
+ # ─── Benchmarks : on garde uniquement les exemples manuels ───────
68
+ # Les fichiers f5_safety.json et rws_translation.json sont COMMITTÉS
69
+ # (ce sont des exemples/documentation, pas des caches).
70
+ # Les caches auto-fetchés (BenchLM, RankLLMs) sont ignorés.
71
+ benchmarks_cache/benchlm_*.json
72
+ benchmarks_cache/rankllms_*.json
73
+
74
+ # ─── Logs ────────────────────────────────────────────────────────
75
+ *.log
76
+ logs/
77
+
78
+ # ─── OS ──────────────────────────────────────────────────────────
79
+ .DS_Store
80
+ Thumbs.db
81
+
82
+ # ─── Artefacts de build ──────────────────────────────────────────
83
+ *.whl
84
+ *.tar.gz
@@ -0,0 +1,202 @@
1
+ # Changelog
2
+
3
+ Toutes les évolutions notables de ce projet sont documentées dans ce fichier.
4
+
5
+ Le format s'inspire de [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
6
+ et ce projet adhère à [Semantic Versioning](https://semver.org/lang/fr/).
7
+
8
+ ## [Unreleased]
9
+
10
+ _(Rien pour l'instant — les prochaines évolutions seront ajoutées ici.)_
11
+
12
+ ## [0.1.0] - 2026-01-01
13
+
14
+ Première version publique de `gateway-llm`, après refactorisation complète
15
+ du projet initial (`pipeline/`, `process_batch.py` de 880 lignes).
16
+
17
+ ### Added
18
+
19
+ #### Architecture
20
+
21
+ - Package Python installable (`src/gateway_llm/`, `pyproject.toml` avec hatchling).
22
+ - Layout `src/` pour éviter les imports accidentels et supprimer les `sys.path.insert` dans les tests.
23
+ - Exports publics centralisés dans `gateway_llm/__init__.py`.
24
+
25
+ #### Providers
26
+
27
+ - Classe abstraite `Provider` avec `complete(model, prompt, max_tokens, temperature, image_b64)`.
28
+ - `OpenAICompatibleProvider` couvrant Groq, OpenRouter, Mistral, NVIDIA, Google AI Studio.
29
+ - `OllamaProvider` avec désactivation du Thinking (`think: false`) et support multimodal (`images`).
30
+ - `CloudflareProvider` avec format de réponse spécifique.
31
+ - Support multimodal : `image_b64` transmis à `/chat/completions` (format OpenAI) ou `/api/chat` (format Ollama).
32
+
33
+ #### Router et orchestration
34
+
35
+ - Classe `Router` avec cascade par domaine, filtres policy/quota/hardware, guardrail en filtre final.
36
+ - `QuotaManager` avec **cooldown temporel** par provider (corrige le bug de compteur 429 cumulatif).
37
+ - `BudgetTracker` avec plafond en euros et arrêt contrôlé (`budget_exceeded`).
38
+ - `PolicyConfig` avec wildcards (`groq-*`), règle `default`, et `default_allow`.
39
+ - `HardwareInfo` avec détection VRAM (`nvidia-smi`, `rocm-smi`) et estimation de fit non bloquante.
40
+ - `BatchRunner` avec checkpointing, reprise (`--resume`), dry-run, et rapport final.
41
+ - `Checkpoint` avec écriture append + fsync.
42
+
43
+ #### Benchmarks dynamiques
44
+
45
+ - Module `benchmarks/` avec `BenchmarkSource` (ABC) et 4 adaptateurs :
46
+ - `BenchLMAdapter` (BenchLM.ai)
47
+ - `RankLLMsAdapter` (RankLLMs)
48
+ - `F5SafetyAdapter` (F5 Labs CASI/ARS)
49
+ - `RWSTranslationAdapter` (RWS TrainAI M-GATE)
50
+ - `BenchmarkCache` avec TTL 24h et refetch forcé.
51
+ - `BenchmarkAggregator` avec fusion multi-sources (moyenne) et re-ranking des chaînes.
52
+ - `normalize_model_name()` et `fuzzy_match()` pour appariement automatique des noms de modèles sans table d'alias manuelle.
53
+ - **Refresh lazy au démarrage d'un batch** : si le cache a plus de 14 jours (`gateway_llm_BENCHMARK_TTL_DAYS`), il est rafraîchi automatiquement.
54
+ - Workflow GitHub Actions `.github/workflows/update-benchmarks.yml` pour mise à jour bi-hebdomadaire des caches F5 et RWS.
55
+
56
+ #### Secrets
57
+
58
+ - Classe abstraite `SecretBackend` avec `get()`, `is_available()`, `set()` (défaut : retourne `False`).
59
+ - **6 backends** :
60
+ - `PowerShellVaultBackend` (Windows)
61
+ - `OnePasswordBackend` (multi-OS)
62
+ - `HashiCorpVaultBackend` (entreprise)
63
+ - `AWSSecretsManagerBackend` (cloud AWS)
64
+ - `AzureKeyVaultBackend` (cloud Azure)
65
+ - `EnvSecretBackend` (fallback explicite, déconseillé)
66
+ - Imports cloud **lazy** : `import gateway_llm.secrets` fonctionne sans `boto3` ni `azure`.
67
+ - `get_backend()` avec résolution explicite (aucune bascule silencieuse vers `.env`).
68
+ - `save_backend_config()` qui persiste le choix dans `~/.gateway-llm/secrets.yaml` (hors repo, non commité).
69
+ - `missing_requirements()` qui détecte les packages pip manquants avant que l'utilisateur ne choisisse un backend.
70
+ - Commande CLI `gateway-llm setup-secrets` avec assistant interactif (machine perso / entreprise / cloud).
71
+
72
+ #### Classification
73
+
74
+ - `TaskClassifier` avec mode LLM (qwen3:4b-instruct) + fallback regex.
75
+ - 9 domaines supportés dont `multimodal_extraction` (images, screenshots, KPI).
76
+ - Priorité humaine, flags de risque (`MULTIMODAL_BLOCKED` supprimé, `POST_2024_FACT_CHECK`, `HIGH_RISK`, `SUBJECTIVE_NORMAL`).
77
+
78
+ #### Guardrails
79
+
80
+ - Classe abstraite `Guardrail` avec `GuardrailResult`.
81
+ - `NoOpGuardrail` (défaut, aucune dépendance).
82
+ - `NemoGuardrail` (extra `[guardrails]`), avec normalisation `str` / `dict` / `GenerationResponse` et fail-open sur exception.
83
+
84
+ #### Intake (convertisseur de données)
85
+
86
+ - `intake_from_folder` : dossier d'images → JSONL.
87
+ - `intake_from_text` : dossier de fichiers texte → JSONL.
88
+ - `intake_from_csv` : colonne CSV → JSONL.
89
+ - `intake_from_urls` : liste d'URLs → JSONL, avec vérification `robots.txt` par défaut.
90
+ - Commande CLI `gateway-llm intake from-folder|from-text|from-csv|from-urls`.
91
+
92
+ #### Diagnostic et installation
93
+
94
+ - `Doctor` avec checks deps Python, binaire Ollama, daemon Ollama, modèles locaux, stockage des secrets.
95
+ - `Installer` avec téléchargement `ollama pull` interactif ou automatique (`--yes`).
96
+ - Commande CLI `gateway-llm doctor` et `gateway-llm setup`.
97
+
98
+ #### Interface graphique
99
+
100
+ - Application `tkinter` unifiée (`python -m gateway_llm.gui`) avec **4 onglets** :
101
+ 1. Configuration (backend de secrets)
102
+ 2. Préparer les données (intake)
103
+ 3. Lancer le traitement (batch)
104
+ 4. Voir les résultats (rapport, à revoir, tout)
105
+ - Ouverture automatique de l'onglet Configuration au premier lancement.
106
+ - Boutons Accepter / Rejeter pour les tâches `human_review`, décisions écrites dans `decisions.jsonl`.
107
+
108
+ #### CLI
109
+
110
+ - `gateway-llm doctor` : diagnostic.
111
+ - `gateway-llm setup` : installation des modèles Ollama manquants.
112
+ - `gateway-llm setup-secrets` : configuration du backend de secrets.
113
+ - `gateway-llm intake` : convertisseur de données (4 sous-commandes).
114
+ - `gateway-llm benchmarks refresh` : rafraîchissement forcé.
115
+ - `gateway-llm batch run` : traitement par lot avec `--resume`, `--dry-run`, `--max-cost-eur`, `--no-classifier`, `--classifier-model`, `--no-doctor`, `--no-install`, `--yes`, `--verbose`.
116
+ - `--help` exhaustif pour chaque commande avec épilogues et exemples.
117
+
118
+ #### Tests
119
+
120
+ - Suite complète de tests unitaires avec mocks (aucun réseau requis).
121
+ - `test_router.py`, `test_quota.py`, `test_budget.py`, `test_policy.py`, `test_classifier.py`, `test_checkpoint.py`, `test_benchmarks.py`, `test_hardware.py`, `test_providers.py`, `test_security.py`, `test_doctor.py`, `test_installer.py`.
122
+ - Tests de sécurité explicites : pas de `shell=True`, échappement d'apostrophes, absence d'import cloud au niveau module.
123
+
124
+ #### CI/CD
125
+
126
+ - `.github/workflows/ci.yml` : matrice Python 3.11/3.12/3.13, ruff, mypy, bandit, pip-audit.
127
+ - `.github/workflows/secret-scan.yml` : gitleaks hebdomadaire.
128
+ - `.github/workflows/update-benchmarks.yml` : mise à jour automatique F5/RWS tous les 14 jours.
129
+
130
+ #### Documentation
131
+
132
+ - `README.md` : installation, quickstart, CLI complet, architecture, OOP, GUI, tests.
133
+ - `docs/THREAT_MODEL.md` : 15 menaces documentées (T1 à T15), actifs, hors périmètre, recommandations.
134
+ - `docs/GUIDE_FR.md` : guide utilisateur non technique (français).
135
+ - `docs/GUIDE_EN.md` : guide utilisateur non technique (anglais).
136
+ - `benchmarks_cache/f5_safety.json` et `rws_translation.json` : exemples documentés, mis à jour par CI.
137
+
138
+ ### Changed
139
+
140
+ - **Refactorisation complète** du projet initial (`process_batch.py` de 880 lignes) en 20+ modules de < 200 lignes chacun.
141
+ - **Programmation orientée objet** systématique : chaque responsabilité est une classe, aucune variable module-level mutable.
142
+ - **Logging** remplace les 92 `print` du projet initial : `NullHandler` sur le logger racine, `dictConfig` pour le CLI, format texte ou JSON.
143
+ - `guardrail_passed=False` **arrête la cascade** au lieu de relancer sur le modèle suivant (comportement fidèle au projet original, corrigé par rapport à une première itération erronée).
144
+ - Le fichier de sortie JSONL contient désormais `status` (`approved` / `human_review` / `failed` / `budget_exceeded`) au lieu d'un booléen `success`.
145
+ - `models.example.yaml` : `qwen2.5vl:7b` remplacé par `qwen2.5vl:7b-q4_K_M` (quantification explicite Q4_K_M, ~6 Go).
146
+ - `policy.yaml` accepte trois formes : `{allowed_providers: [...]}`, `[...]`, ou `ResidencyRule`.
147
+
148
+ ### Removed
149
+
150
+ - `Playwright` et toutes les dépendances de navigateur (`playwright`, `playwright-stealth`).
151
+ - Patches de stealth (`add_stealth_patches`, `USER_AGENT_BRAVE`, `PROFIL_ISOLE`, `BRAVE_PATH`).
152
+ - `extract_sources.py`, `auto_detect_selectors.py`, `config_urls.json` (scraping web).
153
+ - `Nemoguardrails` en dépendance obligatoire → devenu extra `[guardrails]`.
154
+ - Dossiers `approved/`, `sent/`, `human_review/`, `history/`, `site/` du projet initial.
155
+ - Scripts `run_batch.bat` et `run_batch.sh` (remplacés par la GUI et le CLI).
156
+ - `APScheduler` (le refresh lazy + GitHub Actions couvrent le besoin).
157
+ - Toute trace de `shell=True` dans le code.
158
+ - Compteur 429 cumulatif (`_PROVIDER_CALLS["__429_xxx"]`) remplacé par cooldown temporel.
159
+
160
+ ### Fixed
161
+
162
+ - **Bug du compteur 429** : le compteur original n'était jamais remis à zéro, bannissant un provider pour la session entière après 2× 429. Corrigé par `QuotaManager` avec `time.monotonic()` et expiration naturelle.
163
+ - **`shell=True` avec f-string** dans `_get_secret` : remplacé par `subprocess.run([...])` avec liste d'arguments et échappement d'apostrophes.
164
+ - **`sys.path.insert` dans les tests** : supprimé par le layout `src/` + installation editable.
165
+ - **État global mutable** (`_SECRET_CACHE`, `_GUARDRAILS_APP`, `_PROVIDER_CALLS`) : encapsulé dans des instances injectables.
166
+ - **Imports Azure au niveau module** : déplacés en lazy import pour ne pas casser `import gateway_llm.secrets` si azure n'est pas installé.
167
+ - **Incohérence `success` booléen vs réponse partielle** : introduction du champ `status` explicite.
168
+
169
+ ### Security
170
+
171
+ - Modèle de menace documenté (`docs/THREAT_MODEL.md`) avec 15 entrées T1–T15.
172
+ - Vérification `gitleaks` en CI (workflow hebdomadaire).
173
+ - `pip-audit --strict` en CI.
174
+ - `bandit -r src/` en CI.
175
+ - Pas de `shell=True` nulle part.
176
+ - Backends de secrets à choix explicite : aucune bascule silencieuse vers `.env`.
177
+ - `~/.gateway-llm/secrets.yaml` ne contient jamais de secret final, seulement la config du backend.
178
+ - Recommendation `chmod 600` documentée pour le fichier de config.
179
+ - Support `confidential` → `[ollama]` uniquement pour les données sensibles (y compris screenshots avec KPI).
180
+
181
+ ---
182
+
183
+ ## Notes de migration depuis le projet original
184
+
185
+ Si vous venez du projet `pipeline/` initial, voici les correspondances :
186
+
187
+ | Projet original | `gateway-llm` |
188
+ | :--- | :--- |
189
+ | `process_batch.py` (880 lignes) | 15+ modules sous `src/gateway_llm/` |
190
+ | `_get_secret()` | `PowerShellVaultBackend.get()` |
191
+ | `call_llm_with_fallback()` | `Router.route()` |
192
+ | `classify_and_route_task()` | `TaskClassifier.classify()` |
193
+ | `check_response_with_guardrails()` | `NemoGuardrail.check()` |
194
+ | `generate_summary_report()` | `BatchRunner._print_report()` + `ResultsTab._refresh()` |
195
+ | `tasks.json` | `tasks.jsonl` (une ligne par tâche) |
196
+ | `approved/`, `sent/` | `results.jsonl` (champ `status`) |
197
+ | `human_review/human_review_summary.*` | `ResultsTab` onglet « À revoir » |
198
+ | `history/tasks_*.json` | Non conservé (chaque sortie JSONL est un historique) |
199
+ | `scrape.py` / `auto_detect_selectors.py` | Non conservé (supprimé) |
200
+
201
+ [Unreleased]: https://github.com/Darki0n1/gateway-llm/compare/v0.1.0...HEAD
202
+ [0.1.0]: https://github.com/Darki0n1/gateway-llm/releases/tag/v0.1.0