Commit Graph
22 Commits
Author SHA1 Message Date
Johan LEROY f21a843fc2 Fusionne dev dans test/integration-api-db-ml
La PR #123 (MLflow) est arrivée sur dev entre-temps. Un seul conflit, la liste
.PHONY du Makefile : elle garde `migrate-test` d'ici et `mlflow-up` de dev, les
deux cibles existant chacune de leur côté.

Rien d'autre ne se recoupe : le test de chaîne passait déjà son propre
`--mlflow-tracking-uri` sur un SQLite jetable, et `modele_jetable` entraîne son
Booster sans passer par `train()`, qui journalise dans MLflow sans garde.
2026-09-22 15:34:38 +02:00
ValentinDeFariaandGitHub 57b9735804 Merge pull request #123 from ineszang/feat/entrainement-du-modele
feat(ml): enregistrer le modèle dans le MLflow Model Registry
2026-09-22 15:21:24 +02:00
Valentin 44163bfb98 fix(ml): corrige le build MLflow (psycopg2), le garde-fou Makefile, la doc et la fuite de mot de passe
ML / Analyse statique de sécurité (push) Successful in 6s
SonarQube / test-ml (push) Failing after 6m4s
SonarQube / build-front (push) Successful in 9m44s
SonarQube / build-back (push) Successful in 9m50s
ML / Lint, typage et tests (push) Successful in 11m41s
SonarQube / test-front (push) Failing after 5m1s
SonarQube / test-back (push) Failing after 5m11s
SonarQube / SonarQube (push) Skipped
2026-09-22 15:04:21 +02:00
Johan LEROY 68239371f6 docs(ml,backend,etl): ordonnance la derive et corrige ce que le depot disait faux
Trois phrases du depot annonçaient une surveillance de derive inexistante, et une quatrieme
disait qu'aucune base PostgreSQL n'etait joignable pour tester le chargement ML. Les quatre
sont maintenant fausses, donc reecrites plutot que laissees en dette.

- ADR 0011 : ou vit le calcul et pourquoi pas dans `ml/`, les deux dedoublonnages qu'impose la
  jointure, et quatre alternatives ecartees avec la contrainte qui les interdit (la metrique
  MLflow n'est pas la meme grandeur, `alert` borne ses valeurs et refuse un site nul, Prometheus
  n'a pas de collecteur, ne rien persister ne repond pas a la question du jury).
- DAG `derive` quotidien, hors du DAG `alertes` : un echec de derive y ferait croire que la
  detection a echoue, et la fenetre de 168 h ne se recalcule pas toutes les heures.
- ML-START : la limite de `--now` est dite au lieu d'etre decouverte en demonstration. Elle ne
  decale que l'instant de reference, pas la fenetre de lecture, donc aucun rattrapage ne peut
  fabriquer de paires prevu/realise sur un jeu fige.
- 50-cicd : pourquoi le job ML installe aussi le backend (le schema n'a qu'une source), et ce
  que coute le filtre de chemins qui l'accompagne.
2026-09-22 14:27:13 +02:00
Johan LEROY 0db69fd023 feat(infra): Terraform provisionne la VM, GitHub Actions continue de déployer
Le seul Terraform du dépôt installait un cluster k3s que rien ne consomme, et
sa racine ne passait même pas `terraform init` : depuis Terraform 1.x, un
provisioner `destroy` impose que tout le bloc `connection` ne lise que `self`,
et celui du module k3s lisait `var.*`. Il est corrigé en batissant la connexion
sur `triggers`, où ne figurent que l'adresse, le port, l'utilisateur et le
chemin de la clé : jamais la clé ni un mot de passe.

`environments/vm-eni` provisionne la machine qui porte la recette et la
production : Docker et le plugin Compose, `scripts/provision-host.sh`, puis
l'enregistrement du runner. Rien n'y construit d'image ni ne lance de
conteneur, et un `apply` n'interrompt pas la stack qui tourne. Le déploiement
continu ne bouge pas : `deploy.yml` reste le seul chemin de livraison.

`environments/dev` devient `k3s-cible`, parce qu'il provisionnait un cluster et
pas un environnement applicatif, et que `rec` et `prod` vivent sur la même
machine. `environments/prod`, dossier vide, disparaît.

`infra.yml` formate et valide chaque racine à chaque push : c'est l'absence
d'un tel job qui a laissé ce Terraform cassé sans que rien ne le dise. La
boucle parcourt `environments/*`, une racine ajoutée est couverte sans y
toucher.

ADR 0010 pour la frontière entre provisionnement et livraison, et la doc
d'architecture alignée dessus.
2026-09-22 11:27:21 +02:00
Valentin 8760ebc701 fix(ml): applique les corrections de la review MLflow (securite, documentation, robustesse) 2026-09-22 10:41:02 +02:00
Johan LEROY f81959c1a9 Merge branch 'main' into dev
Rapatrie #135 : migration vers Airflow 3.3.2 (api-server, dag-processor,
secret JWT, FabAuthManager, DAGs et tests sur le SDK). Conflit Makefile :
la cible airflow-up garde le prérequis db-ensure-airflow de dev et les
services renommés de main.
2026-09-22 09:05:50 +02:00
Johan LEROY 154deca511 docs(architecture): décrit les composants Airflow 3
Quatre services au lieu de trois (api-server, dag-processor), le secret JWT
partagé et le choix du FabAuthManager. Le Python 3.12 d'etl/airflow est celui
de l'image retenue, plus une limite d'Airflow.
2026-09-22 09:01:07 +02:00
Johan LEROY d2ca2644d2 Merge remote-tracking branch 'origin/dev' into feat/deploy-rec-prod
# Conflicts:
#	docs/architecture/00-vue-ensemble.md
2026-09-22 08:21:59 +02:00
Meryemel-gham fe100653d0 fix(etl): traite les retours de revue du DAG historique
Airflow / Lint et intégrité des DAGs (push) Successful in 57s
Airflow / Construction de l'image (push) Successful in 2m52s
SonarQube / build-back (push) Successful in 1m17s
SonarQube / test-ml (push) Failing after 1m50s
SonarQube / build-front (push) Successful in 9m44s
SonarQube / test-back (push) Failing after 55s
SonarQube / test-front (push) Failing after 5m3s
SonarQube / SonarQube (push) Skipped
2026-09-21 16:05:55 +02:00
Johan LEROY bccf7ed774 fix(infra,ci): le déploiement migre la base, et la doc cesse de dire déployé
`make stack-up` enchaîne `alembic upgrade head` dans le conteneur backend. Rien ne
migrait la base sur le chemin de déploiement, et `/api/v1/health/ready`, qui ne teste
que la connexion et l'extension TimescaleDB, aurait laissé passer un déploiement vert
sur une base sans schéma applicatif.

deploy.yml borne le job à 30 minutes et sort les journaux du backend et du proxy quand
la sonde échoue. provision-host.sh rappelle la création du premier administrateur, et
la propriété de /srv/enervision sans laquelle le runner ne peut ni manipuler les clones
ni lire un `.env` en 600.

Les statuts de livraison continue repassent à `En cours` : le code est écrit, la machine
n'est pas provisionnée, le runner n'est pas enregistré, rien n'a été déployé. À basculer
sur `Fait` au premier déploiement vert. Décompte des jobs corrigé, 18 et non 17.

Refs #21, #22
2026-09-21 15:58:03 +02:00
Johan LEROY cb23895026 feat(infra,ci): deux environnements rec et prod sur la VM ENI, déployés par un runner auto-hébergé
Un projet Compose par environnement sur la même machine : ports du proxy et origine
publique en variables dans docker-compose.prod.yml, réglage mémoire des deux bases
TimescaleDB et du webserver Airflow. Le workflow deploy.yml déploie dev en recette et
main en production depuis un runner installé sur la VM, jamais sur pull_request.
scripts/provision-host.sh prépare les deux dossiers, secrets et certificats compris,
sans rien démarrer.

L'image frontend quitte dhi.io/nginx, registre authentifié dont personne n'a l'accès,
pour nginx:1.28-alpine : elle n'avait jamais été construite.

ADR 0009, vues infra et CI/CD, README et .env.example mis à jour.

Refs #21, #22
2026-09-21 14:59:32 +02:00
Meryemel-gham cb4df846cb docs(etl): documente l'orchestration de l'import historique 2026-09-21 14:41:38 +02:00
Johan LEROY f8d08c8686 fix(etl): borne le DAG alertes sur son pire cas et couvre sa seconde commande en CI
Airflow / Lint et intégrité des DAGs (push) Successful in 56s
Airflow / Construction de l'image (push) Successful in 3m20s
`execution_timeout` plafonne une tentative, pas la tâche. Avec deux reprises, quinze
minutes par tentative autorisaient quarante-neuf minutes par tâche et quatre-vingt-dix-huit
pour l'enchaînement, quand le commentaire annonçait une somme tenant sous le pas horaire.
Le plafond passe à cinq minutes, ce qui borne le pire cas à trente-huit minutes, et le test
d'intégrité calcule désormais ce pire cas plutôt que la somme des plafonds : reprises et
délais d'attente compris, c'est la durée qu'un `max_active_runs=1` fait payer à l'exécution
suivante.

La CI vérifie aussi `app.cli generate-recommendations --help` sans réseau. C'est la seconde
commande du DAG, et son import tire FastAPI, les repositories et les services, donc une part
de l'environnement `/opt/backend` que la détection seule ne touche pas.

`10-infra.md` nomme enfin ce que le décalage de quinze minutes ne garantit pas : le plafond
de `ml_score` valant trente minutes, un scoring qui déborde prive la règle `anomaly` de la
prédiction de l'heure, qu'elle ne retrouvera au passage suivant que si sa fenêtre la couvre
encore.
2026-09-21 13:28:23 +02:00
Johan LEROY 306c5a52e5 Merge remote-tracking branch 'origin/dev' into feat/dag-alertes
# Conflicts:
#	.env.example
#	Makefile
#	docs/README.md
2026-09-21 12:16:58 +02:00
Johan LEROY 2686880185 docs: acte l'ordonnancement des alertes par l'ADR 0008 et met à jour les vues
L'ADR 0008 décide qu'Airflow exécute le code du backend en sous-processus plutôt
que d'appeler l'API, et assume ce que cela coûte : une image plus lourde, la CI
Airflow déclenchée par les changements du backend, une clé applicative de plus.

Les vues suivent. Trois DAGs dans 10-infra.md et dans la vue d'ensemble, avec le
motif du décalage horaire. La détection n'est plus « lancée à la main » dans
20-backend.md. La génération des recommandations gagne son troisième déclencheur
dans 40-data.md. La dette de cantonnement ETL et ML porte l'aggravation comme
l'atténuation. L'affirmation selon laquelle `etl/airflow/` ne contient que des
`.gitkeep`, fausse depuis l'issue #115, disparaît.

L'index des décisions omettait les ADR 0005 et 0006, il les récupère au passage.
2026-09-21 12:14:06 +02:00
Johan LEROY c528ed239b Merge remote-tracking branch 'origin/dev' into feat/reverse-proxy-nginx-tls
Rapatrie la #118 (DAGs Airflow). Quatre conflits, tous additifs sauf un :

- `.env.example` et `.gitignore` : les blocs Airflow et proxy cohabitent.
- `Makefile` : `AIRFLOW` rejoint les variables de dossier, les cibles Airflow
  et TLS cohabitent dans `.PHONY`.
- `00-vue-ensemble.md` : la ligne ML de `dev` est retenue, la ligne Infra de
  cette branche aussi, chacune portant sa propre mise à jour.

L'interface Airflow rejoint la base et Mailpit sur `127.0.0.1` dans l'overlay :
elle n'a pas d'authentification à publier derrière le proxy.
2026-09-21 11:24:42 +02:00
Dorian 901ceffd72 fix(etl): fiabilise airflow-init, borne les DAGs ML et ajoute la CI Airflow
Airflow / Lint et intégrité des DAGs (push) Successful in 1m10s
Airflow / Construction de l'image (push) Successful in 1m47s
2026-09-21 11:18:02 +02:00
Dorian b941880c22 feat(etl,ml): orchestre l'entrainement et le scoring LightGBM via deux DAGs Airflow 2026-09-21 10:03:23 +02:00
Johan LEROY 0c487fa7be docs: acte la terminaison TLS par l'ADR 0007 et met à jour les vues
L'ADR 0007 tranche le reverse proxy en Compose plutôt que l'ingress k3s, qui
supposait un registre et des manifestes inexistants, et referme la première
question ouverte de 10-infra.md.

Les vues suivent : troisième topologie et ports 80/443 dans 10-infra.md, TLS,
HSTS et CSP passent d'« Absent, et assumé » à « En place » dans la vue
d'ensemble, la ligne API8 transport rejoint les points couverts de la
traçabilité OWASP.

Trois affirmations périmées disparaissent au passage : le compose a bien un
service frontend, environment.ts ne pointe plus sur localhost:8000, et le
Dockerfile du front n'est plus mono-étage sur une branche.
2026-09-21 09:51:19 +02:00
Johan LEROY 5e7cb005ac feat(build): branche le frontend sur make dev
Ajoute install-frontend/dev-frontend au Makefile, dev/install deviennent
composites (backend + frontend lances ensemble), et met a jour README et
docs/architecture en consequence.

Closes #75
2026-09-16 10:25:22 +02:00
Johan LEROY 4c72fbbb69 docs: fonde les vues d'architecture du monorepo
Cinq vues Mermaid dans docs/architecture (vue d'ensemble, infra, backend,
frontend, donnees), plus leur index, les conventions de statut et la regle
de maintenance en PR.

Reprend les jalons J1-J4, disparus de dev lors de la reecriture du README
(2670483) et restes seulement sur main : plus rien sur la branche de travail
ne disait ce que le projet doit prouver.

Fige les decisions du module Terraform k3s, qui ne vivaient jusqu'ici que
dans des commentaires de code et des description de variables : version
epinglee obligatoire, Traefik desactive, kubeconfig en 600/root, state local.

Corrige trois affirmations devenues fausses : le frontend classe
"a initialiser" alors que le squelette existe depuis 49f4697, le port 4200
dit attendu par docker-compose.yml qui n'a aucun service frontend, et
l'arborescence core/ prescrite par TESTING.md sans exister.
2026-09-15 11:56:18 +02:00