100 Commits
Author SHA1 Message Date
david 5112c2aa7c docs(vigie): dedicated Gitea account for the vigie token
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 9s
Gate — evals et acceptance réelles / revue (push) Successful in 8s
Gate — evals et acceptance réelles / evaluation (push) Successful in 4m54s
CD — Staging / build (push) Successful in 32s
CD — Staging / deploy (push) Successful in 34s
Mise en service de la vigie faite le 23/10 côté Gitea et serveur : compte
dédié `vigie` (restreint, Écriture sur le seul dépôt qualicheck), jeton à
la seule portée « tickets », secrets du dépôt, étiquette `simulation`,
entrée DNS et bloc Caddy du sous-domaine. La procédure de mise en service
le dit désormais.
2026-10-23 14:46:58 +02:00
david a383579c31 feat(vigie): describe each signal in a tooltip on the health page
Chaque ligne des trois tableaux de la page « Santé du service » porte une
pastille « i » dont l'infobulle dit en une phrase ce que mesure le signal
(clé `description` de chaque signal dans config.yml).

Infobulle en CSS seul (pas de JavaScript sur la page, CSP) : ouverte au
survol de la cellule et au focus clavier de la pastille, lue par les
lecteurs d'écran au focus, placée au-dessus de la ligne pour ne pas être
coupée par le défilement horizontal du tableau. Écart assumé : Échap ne
la ferme pas (RGAA 10.13). L'état « Mesure » prend l'icône « – » pour ne
pas répéter le « i ».
2026-10-23 14:22:51 +02:00
david e34f12485c docs(vigie): close card 61 after its pull request
Clôture de la carte #61 (vigie, brief 5) après la PR #112 : ligne du
CHANGELOG (contrôle de la page, temps reconstitué, critère des alertes en
état de marche attendu de l'essai réel en staging), entrées C20 et C11,
index des compétences, notes de l'oral (vigie dans le compose, moindre
privilège, Langfuse en panne), burndown et curseur de l'agenda.
2026-10-23 14:05:03 +02:00
david cd73c5563f fix(vigie): least-privilege env, per-process temp page, review fixes
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 15s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Successful in 2m41s
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 9s
Corrections de la revue finale de la vigie (carte #61) :
- le service vigie ne reçoit plus tout le .env (env_file retiré) mais
  seulement les variables qu'il lit (moindre privilège) ;
- fichier provisoire de la page nommé d'après le processus (démo et boucle
  en parallèle) ;
- textes périmés corrigés (docstrings, feuille de style, .env.example) ;
- limites documentées : Langfuse injoignable, démo sans jeton, retour
  arrière et copie de l'override du serveur ;
- tests : bloc de l'override borné, cas du jeton vide.
2026-10-23 13:22:57 +02:00
david dc22c8dea8 docs(vigie): commissioning of the vigie subdomain and service
La page de la vigie a son sous-domaine (DNS + bloc Caddy posé par un script
serveur testé en local). Documentation alignée sur le service docker-compose :
exploitation, déploiement du staging (secrets VIGIE_*, override lu dans le
dépôt), surveillance, fiches de conception (phrases datées du 2026-10-23),
liste des modules de app/CLAUDE.md et entrée du CHANGELOG.
2026-10-23 13:13:25 +02:00
david 5a7909c36f feat(vigie): run the monitor as a compose service with a manual demo
La vigie devient un service du docker-compose (qualicheck-vigie, page sur
8884, boucle toutes les 15 minutes, journal de purge en lecture seule).
L'image copie scripts/vigie.py ; le staging tire l'image de l'API business
pour la vigie et lit l'override dans le dépôt (COMPOSE_FILE). Le déploiement
écrit les secrets VIGIE_*, tire l'image et contrôle la page.
Démo par un workflow manuel (vigie-demo.yml) ; le workflow planifié et son
test sont retirés. make vigie passe par le conteneur.
2026-10-23 13:07:43 +02:00
david e1f50a2d89 feat(vigie): serve the health page and loop as a service
Serveur HTTP de la bibliothèque standard pour sante.html et sante.css
(503 avant le premier passage, 404 ailleurs, aucun journal de requêtes).
Ajout de boucler et de l'option --boucle. Les alertes ne partent que si
VIGIE_GITEA_TOKEN est posé et hors --a-blanc. Écriture de la page atomique.
2026-10-23 13:03:49 +02:00
david ad165d1738 feat(vigie): read the watched environment from APP_ENV
L'environnement surveillé est passé en paramètre de lire_traces (APP_ENV, dev par défaut) au lieu de la config. La config perd vigie.environnement, pointe /health sur l'API business par le réseau interne et gagne le bloc page (port 8884, messages absente/introuvable).
2026-10-23 12:56:38 +02:00
david 41998fd2b4 docs(vigie): read the staging override from the repository
Décision du 2026-10-23 : le déploiement lit le fichier de surcharge du
staging dans le dépôt (COMPOSE_FILE), un changement du compose du staging
part avec le code. La copie du serveur reste pour les retours arrière vers
un ancien run. Fiche (sections 10 et 14) et plan de reprise mis à jour.
2026-10-23 12:54:38 +02:00
david a7d1100f54 docs(vigie): rework plan for the compose service
Plan de reprise en quatre tâches : environnement lu dans APP_ENV, serveur
de la page et boucle, service compose et démo manuelle, script Caddy et
documentation.
2026-10-23 12:52:06 +02:00
david ed1e36c177 docs(vigie): run the monitor as a compose service with its own subdomain
Révision de la fiche de la vigie, validée le 2026-10-23 : la vigie devient
un service du docker-compose (même image que les API), sert sa page sur le
port 8884 derrière vigie.qualicheck.koabana.fr, n'envoie d'alertes que si
VIGIE_GITEA_TOKEN est défini, et sa démo passe par un workflow manuel.
Le workflow planifié et le dépôt par scp sont retirés. Schéma mis à jour.
2026-10-23 12:47:27 +02:00
david 19a4e3224c docs(vigie): renumber the operations guide sections
Les sections du guide d'exploitation vont de 1 à 9 dans l'ordre, les renvois internes (retour arrière, limites) suivent. Une ligne trop longue du guide de déploiement est recoupée sans changer les mots.
2026-10-23 12:17:00 +02:00
david 41f773f128 docs(vigie): commissioning steps, relapse cycle and guide fixes
Mise en service décrite avant la fusion, cycle de la rechute dans la fiche et le guide, montage du dossier de la page à faire à la main, corrections des fiches (citations, jeton refusé, seuil des refus, changement de seuil).
2026-10-23 12:15:41 +02:00
david ac8d4497f1 feat(vigie): signal a relapse and mark simulated passes
Une panne qui revient avant la fermeture du ticket est signalée par un commentaire « Revenu » et un e-mail. La page dit qu'un passage est simulé. Les booléens de Langfuse en texte sont acceptés, « 1 compte » s'accorde, SMTP_EXPEDITEUR est vérifiée, et les chemins d'échec de passer sont testés.
2026-10-23 12:15:41 +02:00
david 006598088a docs(vigie): operations guide, one sheet per signal, decided thresholds
Ajoute docs/exploitation.md (page d'entrée et une fiche par signal, avec ancre), son test de garde, les seuils décidés (metriques_seuils.md section 6), les renvois dans surveillance.md, app/CLAUDE.md et docs/README.md, l'entrée du CHANGELOG et l'amendement du plan sur intervalle_min.
2026-10-23 11:54:22 +02:00
david 769cdb3b02 docs(deploy): serve the service health page from its own folder 2026-10-23 11:49:27 +02:00
david 7341b4ed82 ci(vigie): schedule the watch every 15 minutes
Le workflow Vigie tourne toutes les 15 minutes (cron lu depuis
intervalle_min de la config) et sur demande avec l'option simulation.
La page est publiée même quand le passage échoue, et le passage tourne
avec uv run --no-project : un test vérifie que la vigie n'importe que
la bibliothèque standard, httpx, yaml, dotenv et app.observability.
2026-10-23 11:47:28 +02:00
david e1ea61e492 feat(vigie): run a full pass, with a simulated drift for the demo
Le passage évalue les signaux, écrit la page puis ouvre ou commente les tickets et envoie les e-mails. Démo de 25 questions dont 4 coupées. Cibles make vigie et acceptance-vigie, étape CI.
2026-10-23 11:44:13 +02:00
david 3d7d77dd73 fix(vigie): read the pass interval from the config
Le pied de page de la page « Santé du service » disait « toutes les 15
minutes » en dur, alors que la fréquence des passages est fixée par le
cron de la vigie. L'intervalle passe dans la section `vigie` de la
config (`intervalle_min`) et est transmis à `rendre_page`.
2026-10-23 11:40:16 +02:00
david db5360519e feat(vigie): collect the traces, the health probe and the purge log
Collecte de la vigie : lecture des spans du staging dans Langfuse (API v2,
filtrée par environnement), essais de /health, dernière ligne datée du
journal de la purge, et fichier de traces simulées pour la démo.
2026-10-23 11:37:08 +02:00
david 8b147d1ecb feat(vigie): render the public service health page
Ajoute la page « Santé du service » : rendre_page (fonction pure qui
transforme les états des signaux en HTML statique, sans JavaScript) et
ecrire_page (écrit sante.html et copie sante.css). L'état se lit en icône
et en mot, chaque tableau a sa légende, et la mise en forme est dans
sante.css pour respecter la politique de sécurité (pas de style en ligne).
2026-10-23 11:31:00 +02:00
david 6b5f4a3ee0 fix(vigie): refuse to open a ticket without its label
Gitea.ouvrir lève ValueError si l'étiquette est absente du dépôt, au lieu de créer un ticket sans étiquette que la vigie ne reverrait jamais. La liste des étiquettes demande aussi 50 entrées.
2026-10-23 11:26:54 +02:00
david 6662057a92 feat(vigie): open incident tickets and send the alert e-mails
Ajout du client Gitea de la vigie (lecture des tickets ouverts, ouverture, commentaire, adresse du ticket) et de l'envoi SMTP des e-mails d'alerte, avec un faux Gitea en mémoire pour les tests.
2026-10-23 11:25:06 +02:00
david a6c1779887 feat(vigie): decide which alerts to raise, once per incident
Ajoute le module alertes.py : decider() applique les quatre lignes du cycle (ouvrir, retablir, sinon rien), et les textes des tickets, commentaires et e-mails ne portent que des nombres, des états et des heures.
2026-10-23 11:20:55 +02:00
david bcf8ee2fc0 feat(vigie): evaluate the drift signals and the unthresholded measures
Ajout des dérives (parts, centiles, fidélité, refus d'authentification, latence par groupe) sous un minimum de questions, des mesures sans seuil et de evaluer(), qui enchaîne pannes, dérives puis mesures.
2026-10-23 11:17:15 +02:00
david 40b1f22c7c feat(vigie): evaluate the outage signals
Section vigie de config.yml (fenêtres, seuils, libellés, ancres de la fiche). Nouveau paquet app/observability/vigie : charger_config lit cette section, signaux.pannes évalue les 9 pannes (alerte dès la première occurrence dans les 30 dernières minutes, /health et purge à part). Fonctions pures, sans accès réseau. Tests unitaires des pannes, RED puis GREEN.
2026-10-23 11:10:43 +02:00
david 3b62bbbfa4 feat(observability): read the span level and start time
lire_metadonnees demande fields=core,basic,metadata et rend, pour chaque span, les clés niveau (niveau du span, ERROR…) et debut (startTime complet). Prépare le script de vigie (carte #61).
2026-10-23 11:04:37 +02:00
david d13062f421 feat(juge): put the fidelity scores on the judge span
Le span questions_libres.juge porte désormais les attributs fidelite et
provenance, lus par la vigie (carte #61) : le Langfuse du staging ne rend
pas les scores par l'API.
2026-10-23 11:01:02 +02:00
david 9e83d2c6ff docs: implementation plan of the watch (card 61)
Plan en 14 tâches, TDD, pour la vigie de la carte #61.

Fiche complétée (section 13) : le Langfuse du staging (v4, mode
events_only) refuse la lecture des scores par l'API, la fidélité se lit
donc sur le span du juge ; la page /sante a son propre bloc Caddy et sa
feuille de style à part (CSP) ; la latence compte pour deux signaux ; le
workflow lit le journal de la purge et dépose la page ; option --a-blanc
pour l'essai local.
2026-10-23 10:52:45 +02:00
david f112f8a502 docs: design of the watch (card 61)
Fiche de conception de la vigie (carte #61, brief 5), validée le
2026-10-23 : vigie maison planifiée par Gitea Actions toutes les
15 minutes, page « Santé du service » statique et publique sur /sante,
9 pannes et 6 dérives, minimum de 20 questions par fenêtre de dérive,
tickets « incident » comme mémoire entre deux passages, démo par traces
simulées. Schéma draw.io joint.

CHANGELOG : la vigie et la fusion de la PR #111.
2026-10-23 10:36:58 +02:00
david 7cc31ffeac fix(observability): name the page auditor's spans after its package
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Successful in 1m17s
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 9s
Les spans de l'auditeur de page portaient questions_libres.appel_llm et questions_libres.appel_outil.*, y compris dans l'audit. Ils portent désormais auditeur_page.* ; l'orchestrateur garde questions_libres.*. Traces et span_outil reçoivent un préfixe obligatoire. make traces-agent et l'acceptance lisent les deux préfixes, pour les traces d'avant le changement. Vérifié sur un audit local dans le Langfuse de dev.
2026-10-23 10:12:54 +02:00
david a778113f1b chore: ignore the staging Langfuse keys file
Clés du projet Langfuse du staging, lisibles en local dans .env.langfuse, jamais versionnées.
2026-10-23 10:12:54 +02:00
david c624cbc913 docs: spec for the page auditor's span names
Spec validée le 23/10 : les appels de l'auditeur de page, partagé par la question libre et l'audit, portent le nom de son paquet (auditeur_page.*) au lieu de questions_libres.*.
2026-10-23 10:12:54 +02:00
david fb08cfa0ec docs: course sheets for the OWASP Top 10 of web applications
Une fiche par risque du Top 10 OWASP:2025 dans docs/owasp/web/, sur
le modèle des fiches de l'IA ; index élargi aux trois listes, avec les
correspondances entre risques web et risques de l'IA.
2026-10-22 15:08:19 +02:00
david 02ae57d0b6 docs: card 106 closed after its pull request
Carte #106 en Done (0,69 h), critères cochés, fiche et schéma joints ;
décision et leçon de l'essai réel ajoutées aux notes de l'oral.
2026-10-22 14:49:56 +02:00
david 047e3c4028 docs: D1 real test on the local API
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 9s
Gate — evals et acceptance réelles / revue (push) Successful in 8s
Gate — evals et acceptance réelles / evaluation (push) Successful in 1m28s
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
CD — Staging / build (push) Successful in 1m55s
CD — Staging / deploy (push) Successful in 32s
Essai réel fait depuis le client (audit d'une page et d'une règle) ;
relectures orphelines expliquées : rechargement à chaud de Vite
pendant les mutations, disparues au rechargement de la page.
2026-10-22 14:48:04 +02:00
david 94c7c8959e docs: D1 changelog, integrated mockups, plan deviations
Un arrêt du minuteur inutile retiré (mutation survivante : le premier
minuteur qui sonne annule l'autre), test ajouté sur l'annonce sans
hausse ; 20 mutations sur 20. Écarts de la maquette notés ; essai
réel d'un audit qui se termine en attente d'accord (lancement payant).
2026-10-22 14:31:36 +02:00
david 9d9e9040cc feat(client): refresh the header badge after deletion, end of analysis and validation
D1 (carte #106), tâche 3 : la pastille de l'en-tête est relue après
une suppression (réussie ou déjà faite ailleurs), quand la page
d'avancement voit la fin de l'analyse, et après la validation du
rapport ; sans attendre le minuteur de 60 s.
2026-10-22 14:20:49 +02:00
david 6147792db4 feat(client): badge on the Mes audits link of the header
D1 (carte #106), tâche 2 : nombre d'audits à relire en pilule
d'accent, sinon horloge cerclée pendant une analyse ; état dit par le
nom du lien (texte masqué, pastille aria-hidden) ; annonce polie de la
fin d'une analyse, sauf sur la page d'avancement ; relecture à chaque
changement de page. Scénarios Gherkin de la fiche et axe-core.
2026-10-22 14:19:06 +02:00
david 8def866499 feat(client): shared state of the account's audits for the header badge
D1 (carte #106), tâche 1 : composable useEtatAudits. Nombre d'audits
à relire, audit en cours, relecture de GET /audits (rien sans jeton ;
jeton refusé : état vidé ; panne : état gardé), minuteur de 60 s
pendant une analyse, annonce d'une hausse vue par le minuteur.
2026-10-22 14:17:37 +02:00
david 3b6653998a docs: D1 spec validated, implementation plan
Fiche de D1 (carte #106) validée le 22/10 ; plan en 4 tâches :
composable partagé, pastille de l'en-tête, relecture après les
actions du client, vérifications et documentation.
2026-10-22 14:16:37 +02:00
david bc61f0b76f docs: D1 spec, the Mes audits badge in the header
Fiche de la marche D1 (carte #106) : pastille sur « Mes audits »
(nombre d'audits à relire, sinon horloge), relecture de GET /audits
au changement de page, après une action et toutes les 60 s pendant
une analyse ; annonce aux lecteurs d'écran. Client seulement, contrat
inchangé. Schéma dérivé de celui de C4. Statut : à valider.
2026-10-22 14:12:53 +02:00
david e43bc8cd57 docs: card 105 closed after its pull request
Carte #105 en Done (1,11 h) ; décision de C4 ajoutée aux notes de l'oral ; CHANGELOG.
2026-10-22 12:37:50 +02:00
david 851886be2c docs: C4 changelog, plan deviations, stronger tests
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Successful in 36s
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Deux mutations survivantes de C4 attrapées (ordre des pages par
identifiant, date du nom du fichier) ; écarts à l'exécution notés dans
le plan ; app/CLAUDE.md et CHANGELOG à jour.
2026-10-22 12:36:24 +02:00
david 2332c9d8e3 feat(client): download the validated report as a spreadsheet
Rapport validé (A18, C4, carte #105) : boutons « Télécharger le tableur
(ODS) » et « (XLSX) » sous le bandeau, et leur phrase d'aide. Le fichier
est demandé avec le jeton en en-tête (lecture binaire dans api.js), son
nom lu dans Content-Disposition, puis enregistré par un lien temporaire.
Boutons inactifs pendant l'appel (aria-disabled : le focus reste),
pannes sous les boutons.
2026-10-22 12:22:26 +02:00
david fb205df286 feat(api): export the validated report as a spreadsheet
GET /audits/{id}/export?format=ods|xlsx (C4, carte #105) : 200 le
fichier et son nom (Content-Disposition), 404 hors du compte, 409 pour
un rapport pas validé, 422 pour un format inconnu, 503 si la base ou
l'API des règles ne répond pas. Content-Disposition exposé par le CORS.
Contrat 0.30.0 -> 0.31.0, miroir complété à la main (chemin identique
au schéma servi). Essai d'ouverture dans LibreOffice, sauté sans
LibreOffice.
2026-10-22 12:19:54 +02:00
david 60b4600ca5 feat(audit): build the report spreadsheet in ODS and XLSX
Module pur app/audit/export.py (C4, carte #105) : contrôle du statut,
une ligne par constat retenu dans l'ordre des écrans, écriture ODS
(odfpy) et XLSX (openpyxl), toute cellule de texte écrite en texte
(injection de formule), numéro de règle en nombre, caractères de
contrôle retirés, nom du fichier en ASCII. Réglages et message dans
config.yml ; dépendances openpyxl et odfpy.
2026-10-22 12:15:20 +02:00
david 30e0bf896d docs(audit): C4 card validated, implementation plan
Fiche de C4 (carte #105) passée en « validée » le 22/10 ; plan d'implémentation en 4 tâches (module d'export, route et contrat, client, vérifications et documentation).
2026-10-22 12:13:38 +02:00
david fadf482b07 docs(audit): C4 card, export the report (proposed)
Fiche de C4 (carte #105) : GET /audits/{id}/export?format=ods|xlsx,
une ligne par constat retenu, fichiers fabriqués par openpyxl et odfpy,
toute cellule écrite en texte (injection de formule), deux boutons sur
A18, téléchargement avec le jeton en en-tête et Content-Disposition
exposé par le CORS. Contrat 0.30.0 -> 0.31.0, sans migration. Schéma
dérivé de celui de C3, le nouveau en orange.
2026-10-22 12:06:28 +02:00
david 48cf5bd859 docs: course sheets on the OWASP AI top 10 lists
Une fiche par risque des deux listes de l'OWASP GenAI Security Project :
docs/owasp/llm/ (Top 10 pour les applications LLM, édition 2026) et
docs/owasp/asi/ (Top 10 pour les applications agentiques, édition 2026).
Fiches de cours, sans lien avec le code du projet. Index avec les
classements, l'évolution depuis 2025, les correspondances entre les deux
listes et les sources.
2026-10-22 11:25:48 +02:00
david 81c15021c7 docs: CORS fix pushed, weak point for the oral
Correctif CORS poussé avec la PR #108 ; temps ajouté à la carte #103 ;
point faible ajouté aux notes de l'oral (le même défaut de CORS deux
fois, et l'essai réel sur l'API reconstruite comme vérification).
2026-10-22 11:14:17 +02:00
david f65a0c0888 fix(api): allow PATCH in CORS to review a finding
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 15s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Valider, corriger ou écarter un constat (C2, carte #103) passe par un
PATCH ; la requête préliminaire du navigateur était refusée (400
« Disallowed CORS method ») et le client affichait « Votre décision n'a
pas été enregistrée ». PATCH ajouté aux méthodes autorisées, test
d'abord, comme pour le DELETE du 14/10.
2026-10-22 10:58:23 +02:00
david d7ded101f9 docs: card 104 closed after its pull request
Clôture de C3 (carte #104) après la PR #107 : entrée du CHANGELOG et
décision ajoutée aux notes de l'oral (synthèse calculée dans le client,
confirmation hors maquette, limite assumée, leçon du commit invisible
dans la même session).
2026-10-22 10:47:51 +02:00
david 9535ab528e docs: C3 changelog, plan deviations, stronger tests
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 56s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
C3 (carte #104) : entrée du CHANGELOG, écarts à l'exécution du plan,
lignes A15, A16 et A18 de maquettes_integrees.md. Trois tests renforcés
après les mutations survivantes : statut relu par une connexion à part
(le commit de la route), double clic avant la mise à jour de l'écran,
focus sur une carte quand le catalogue arrive après.
2026-10-22 10:46:27 +02:00
david 475b8e9100 feat(client): validate the report and read its summary
C3 (carte #104), côté écrans :
- vue d'ensemble (A15) : « Valider le rapport » en bas, jamais grisé ;
  « Il reste N constats à traiter. » sans appel (RM11), sinon une
  confirmation sur place comme la suppression d'un audit (focus sur
  « Non », Échap), puis POST ; pannes 409, 404, 503, jeton refusé ;
- rapport validé (A18), même adresse : bandeau, synthèse par thème en
  tableau accessible qui défile seul à 375 px, constats retenus en
  cartes sans crayon, retour à Mes audits ; focus sur « Rapport » ;
- page d'une règle d'un rapport validé : « Constats d'une règle »,
  lecture seule, retour « Le rapport » ;
- Mes audits : la ligne d'un rapport validé devient un lien ;
- indicateur d'étapes : 6 = toutes faites.

Scénarios Gherkin de la fiche sur les écrans, axe-core sur chaque état,
captures clair, sombre et 375 px comparées à A15 et A18.
2026-10-22 10:40:24 +02:00
david 5a443a3ad3 feat(client): logic of a validated report and its API call
C3 (carte #104), logique pure du client : src/services/rapport.js
(constats retenus, cartes et synthèse par thème, textes du bandeau, des
cartes et des thèmes, phrase « Il reste N constats à traiter. ») ;
validerRapport (POST /audits/{id}/validation) ; formaterJour ;
phraseRegle en lecture seule (« N retenus »). Fixture d'audit du contrat
complétée par date_validation (contrat 0.30.0).
2026-10-22 10:30:51 +02:00
david fb1a6f0f49 feat(audit): validate the report of an audit (POST)
C3 (carte #104), côté API : POST /audits/{audit_id}/validation passe un
audit « à relire » sans constat à traiter en « rapport validé », avec sa
date. Contrôle pur dans app/audit/validation.py : 409 pour une analyse pas
finie, un rapport déjà validé ou des constats à traiter (« Il reste N
constats à traiter. », RM11). GET /audits/{id} rend date_validation.
Contrat 0.30.0, miroir de conception patché par blocs. Sans migration.

Tests : unitaires du contrôle et de la route (refus, 503, span),
intégration sur la base de test (statut et date écrits, PATCH refusé
après validation, 404, 401, requête de la mesure du délai).
2026-10-22 10:27:45 +02:00
david 95d0d01524 docs(audit): C3 card validated, implementation plan
Fiche C3 passée en « validée » le 2026-10-22 ; plan d'implémentation en
quatre tâches (API, logique client, écrans, vérifications et documents).
2026-10-22 10:17:39 +02:00
david b267b185be docs(audit): C3 card, validate the report (proposed)
Fiche de la marche C3 (carte #104) : POST /audits/{id}/validation,
confirmation sur place, rapport validé (A18) avec synthèse calculée dans
le client, page d'une règle en lecture seule. Schéma repris de C2, le
nouveau en bordure orange. Statut : proposée, à valider.
2026-10-22 10:15:05 +02:00
david 390e8de8c2 docs: cards 102 and 103 closed after their pull request
Clôture de C1 et C2 (cartes #102 et #103) après la PR #106 : entrée
du CHANGELOG et décision ajoutée aux notes de l'oral (valider ou
écarter efface la correction, le verdict de l'agent n'est jamais
écrasé, pas de retour à « à traiter »).
2026-10-22 09:12:06 +02:00
david 4ce7bc0f3a docs: C2 changelog, plan deviations, stronger focus test
CI / ci (push) Skipped
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Entrée du CHANGELOG pour C2 (#103) ; écarts à l'exécution notés dans
le plan. Le test du passage à la règle suivante part du lien qui a le
focus : la mutation qui retirait le focus sur le titre survivait.
2026-10-22 08:58:40 +02:00
david c294a8485d feat(client): review a finding on the page of its rule
C2 (carte #103), écrans A16 et A17 : la page d'une règle
(/mes-audits/{id}/regles/{numero}) montre ses constats, un par page,
avec le verdict et le commentaire retenus, leur état et les actions
permises (valider, corriger, écarter) ; la correction s'ouvre sur
place (verdict, commentaire obligatoire, Échap pour annuler).
Annonce polie et focus gardé après chaque décision, un seul appel à
la fois, pannes affichées sous le constat ; règle précédente et
suivante. Dans la vue d'ensemble, la carte devient un lien avec le
crayon et reprend le focus au retour. Icône arrow-left ajoutée.
2026-10-22 08:53:54 +02:00
david 4d9176e6ab feat(client): logic of a finding's review and its API call
C2 (carte #103), logique pure du client : actions permises (RM10),
verdict et commentaire retenus, ligne d'état, libellé d'une page,
constats d'une règle dans l'ordre des pages, phrase de la règle,
règle précédente et suivante. La vue d'ensemble compte désormais les
verdicts retenus. traiterConstat appelle PATCH /audits/{id}/constats/{id}
et garde les messages de l'API pour 409 et 422.
2026-10-22 08:42:09 +02:00
david e50d8cbaa1 feat(audit): validate, correct or dismiss a finding (PATCH)
C2 (carte #103), côté serveur : PATCH /audits/{id}/constats/{id}
enregistre la décision de l'auditeur (RM10). app/audit/traitement.py
porte les passages permis et le contrôle d'une demande : 409 hors
relecture, 422 pour un passage impossible ou une correction sans
verdict ou sans commentaire (2 000 caractères au plus, en config).
Valider ou écarter efface la correction ; le verdict de l'agent est
gardé. GET /audits/{id} rend verdict_auditeur, commentaire_auditeur et
date_traitement. Contrat 0.28.0 -> 0.29.0, sans migration. Le test
d'intégration joue la requête de la mesure lue dans la fiche.
Plan d'implémentation joint.
2026-10-22 08:40:01 +02:00
david f3634fe3f3 docs(audit): C2 design, review a finding
Fiche de la marche C2 (#103), validée le 22/10 : route PATCH des
constats, contrat 0.29.0 sans migration, page d'une règle (A16) et
correction sur place (A17), requête de la mesure. Schéma joint.
2026-10-22 08:10:49 +02:00
david c59e7e1885 feat(client): open an audit to review on the overview of its findings
C1 (carte #102), tâche 2 du plan : vue d'ensemble (A15) sur /mes-audits/{id} dès que l'audit n'est plus en cours, bouton « Relire les constats » quand l'analyse finit sous les yeux, ligne « À relire » de Mes audits en lien. Résumé d'un thème calculé sur le thème entier. Tests d'abord (échec initial constaté), 16 mutations attrapées, captures clair, sombre et 375 px ; suivi des maquettes et CHANGELOG.
2026-10-22 07:24:42 +02:00
david 295c0d0d10 feat(client): group the findings by theme and rule
C1 (carte #102), tâche 1 du plan : logique pure de la vue d'ensemble (regroupement dans l'ordre du catalogue, verdicts comptés dans un ordre fixe, filtre, textes accordés), carte d'une règle sans lien avant C2, thème repliable ouvert au départ. Icônes dash-lg et question-lg ; couleurs du verdict non applicable lues dans Figma (contraste 4,78:1). Tests d'abord (25, échec initial constaté : modules absents).
2026-10-22 07:16:01 +02:00
david 43aa04ced1 docs(audit): C1 design, overview of the findings
Fiche de la carte #102, validée le 22/10 : vue d'ensemble des constats (A15) sur /mes-audits/{id} dès que l'audit est à relire, client seulement, contrat inchangé (0.28.0). Cartes sans lien jusqu'à C2, filtre « Règles à traiter » coché à l'ouverture, thèmes dépliés. Schéma repris de B6, le neuf en bordure orange.
2026-10-22 07:10:46 +02:00
david f710153ac5 docs: end-of-analysis e-mail received in a real mailbox
Essai fait le 22/10 : dernier point des secrets SMTP du staging, coché dans TODO.md.
2026-10-22 07:10:46 +02:00
david 715170f6bf docs: SMTP secrets created in Gitea
TODO : les six secrets du relais sont dans Gitea, authentification vérifiée sans envoi ; reste un e-mail reçu sur une vraie boîte au prochain déploiement.
2026-10-21 12:23:18 +02:00
david 27ad7f4aca docs: card 101 closed after its pull request
Clôture de B6 (carte #101) après la PR #105 : entrée du CHANGELOG et
décision ajoutée aux notes de l'oral (annonce de l'avancement par
quart, nombre de vérifications calculé par le client et vérifié contre
la règle du serveur, adresse du compte nommée sans être affichée).
2026-10-21 12:10:53 +02:00
david 7d52c8f9f6 docs: B6 in the changelog
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Gate — evals et acceptance réelles / revue (push) Successful in 7s
Gate — evals et acceptance réelles / evaluation (push) Successful in 5m24s
CD — Staging / build (push) Successful in 1m57s
CD — Staging / deploy (push) Successful in 46s
Ligne du CHANGELOG ; TODO : la ligne Caddy du serveur reçoit aussi /mes-audits/*.
2026-10-21 12:08:53 +02:00
david ef60b0f634 feat(client): check and launch an audit, then follow its progress
Étape 4 de « Préparer un audit » (A13, carte #101) : récapitulatif avec
« Modifier », nombre de vérifications calculé avec la portée des règles
(RM8), bloc « Être prévenu » (ajouter, retirer des adresses), lancement
par POST /audits avec les refus de l'API affichés tels quels.
Avancement (A14) sur /mes-audits/:id : relu toutes les 5 secondes,
barre native, annonce aux lecteurs d'écran à chaque quart et à la fin.
« Mes audits » mène à l'avancement d'un audit en cours. Ligne Caddy de
la documentation du déploiement complétée. Contrat inchangé.
2026-10-21 12:08:53 +02:00
david 0660e732c5 docs(audit): B6 design, check and launch the audit
Fiche de B6 (carte #101), validée le 2026-10-21 : récapitulatif de
l'étape 4 (A13), nombre de vérifications calculé avec la portée (RM8),
bloc « Être prévenu », lancement, page de l'avancement (A14) relue
toutes les 5 secondes et annoncée par quart. Client seulement, contrat
inchangé. Schéma tiré de celui de D2, plan d'implémentation.
2026-10-21 11:42:18 +02:00
david 6da668a3a4 feat(comptes): list the business API accounts
make comptes ARGS=lister : une ligne par compte, dans l'ordre de
création (identité, e-mail, actif ou désactivé, fin de validité du
jeton le plus durable ou « aucun jeton valide »). Lecture seule,
jamais d'empreinte. Tests d'abord.
2026-10-21 11:33:03 +02:00
david b618457a5f docs: card 107 closed after its pull request
Clôture de D2 (carte #107) après la PR #104 : entrée du CHANGELOG et
décision ajoutée aux notes de l'oral (adresses ajoutées effacées même en
cas d'échec, aucune adresse tracée).
2026-10-21 11:27:02 +02:00
david a3744720bc docs: D2 in the changelog
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Entrée D2 du CHANGELOG ; formulation de l'e-mail du compte et en-têtes
reportés dans la fiche ; lien « Mes audits » local par défaut en Docker.
2026-10-21 11:24:40 +02:00
david 264b353c5c feat(audit): e-mail the account and added addresses when the analysis ends
D2 (carte #107), côté serveur : POST /audits accepte adresses_notification
(facultatif, 5 au plus, contrôlées au lancement : adresse_invalide,
adresse_en_double, trop_d_adresses) ; quand l'audit passe à relire, un
e-mail en texte brut part au compte et à chaque adresse ajoutée, un par
destinataire, par smtplib (trois tentatives pour une panne passagère,
aucune pour un refus), puis les adresses ajoutées sont effacées. Un échec
d'envoi ne change rien à l'audit ; span audit.notification sans aucune
adresse. En-têtes Date et Message-ID. Contrat 0.27.0 -> 0.28.0.
2026-10-21 11:24:21 +02:00
david 5cf376cfe8 chore(audit): mail relay settings, Mailpit for local development
D2 (carte #107) : service Mailpit (profil dev, démarré par make up,
jamais en staging) qui reçoit les e-mails sans les transmettre ;
variables SMTP de l'API (Mailpit par défaut en local), écrites dans le
.env du staging depuis les secrets Gitea ; .env.example, procédure et
secrets documentés. Décision 10 de la fiche amendée : le traitement de
la notification va dans le volet anticipé du registre interne, publié
avec l'audit à sa mise en ligne (TODO.md).
2026-10-21 11:08:01 +02:00
david 60717d7c8e docs(audit): D2 design, the end-of-analysis e-mail
Fiche D2 (carte #107) validée le 21/10 : e-mail au compte et aux
adresses ajoutées quand l'audit passe à relire, adresses effacées dès
l'envoi, relais SMTP de la messagerie du domaine, Mailpit en local,
registre des traitements complété ; schéma et plan d'implémentation.
2026-10-21 11:04:58 +02:00
david e422dfbb2a docs: card 100 closed after its pull request
Clôture de B5 (carte #100) après la PR #103 : entrée du CHANGELOG,
décision ajoutée aux notes de l'oral (règles non auditables montrées,
nombres jamais en dur) et couleur des cases à cocher notée dans TODO.md.
2026-10-21 10:48:05 +02:00
david 28506b5d9a docs: B5 in the changelog and the integrated mockups
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 9s
Entrée B5 du CHANGELOG et ligne A11 / A12 de la table des maquettes
intégrées.
2026-10-21 10:41:32 +02:00
david bf1bcde5e5 feat(client): choose the rules to check by theme
B5 (carte #100), côté client : l'étape 3 de « Préparer un audit »
(maquettes A11 et A12). Thèmes repliés avec une case à trois états,
règles auditables à cocher ligne entière, les autres listées sans case,
raccourcis, compteur annoncé, nombres comptés sur la réponse de
GET /audits/regles. Catalogue lu une fois, « Réessayer » en cas d'échec,
choix gardé en allers et retours. « Continuer » mène à l'étape 4, vide
jusqu'à B6.
2026-10-21 10:41:32 +02:00
david 668df8068f feat(audit): list the rules an audit can check (GET /audits/regles)
B5 (carte #100), côté API : GET /audits/regles rend les thèmes du
référentiel et leurs règles, auditables ou non, avec leur portée, lus
dans l'API des règles par le client HTTP des outils. Thèmes dans l'ordre
alphabétique français (accents et casse ignorés), règles par numéro ;
un plan d'outils vide n'est pas auditable, comme au lancement. 503
regles_indisponibles si l'API des règles ne répond pas ; rien n'est
écrit en base. Contrat 0.26.0 -> 0.27.0.
2026-10-21 10:25:41 +02:00
david 70c4204867 docs(audit): B5 design, choosing the rules to check
Fiche B5 (carte #100) validée le 21/10 : GET /audits/regles (thèmes et
règles, auditables ou non, avec leur portée), étape 3 du client (thèmes
dépliables, case à trois états, raccourcis, compteur), schéma et plan
d'implémentation.
2026-10-21 10:12:49 +02:00
david 7a7ceed4eb docs: card 99 closed after its pull request
Clôture de B4 (carte #99) après la PR #102 : entrée du CHANGELOG,
décision ajoutée aux notes de l'oral (page ajoutée vérifiée en direct,
en 2xx) et contenu périmé des pages statiques noté dans TODO.md pour
plus tard.
2026-10-21 09:58:05 +02:00
david 7423b09d00 docs: B4 in the changelog and the integrated mockups
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
Entrée du CHANGELOG pour la carte #99 ; maquettes A07 à A10 marquées
intégrées, avec les écarts assumés (N lu, page ajoutée vérifiée, étape 3
vide).
2026-10-21 09:52:44 +02:00
david 66e10bae49 feat(client): choose the pages to audit and add one by hand
B4, carte #99 : l'étape 2 de « Préparer un audit » devient interactive.
Une case par page trouvée, toute la ligne cliquable ; compteur annoncé ;
limite de N pages lue dans la réponse de la détection, la case de trop ne
se coche pas et n'est jamais désactivée. Ajout d'une page à la main :
contrôles du client d'abord (aucune requête s'ils échouent), puis
vérification en direct par l'API ; la page s'affiche à son adresse finale
avec son titre. « Continuer » mène à l'étape 3, encore vide ; le choix est
gardé au retour. Sept scénarios Gherkin d'écran, axe-core sur chaque état.
2026-10-21 09:52:09 +02:00
david 25fcf72367 feat(audit): verify a page added by hand (POST /audits/pages/verification)
B4, carte #99 : la réponse de POST /audits/pages porte pages_max (RM6, lu
en configuration). POST /audits/pages/verification contrôle la déclaration
et les deux adresses (RM2, RM3), puis lit la page par la lecture protégée :
acceptée si elle répond 2xx sur le même nom d'hôte que l'adresse de départ,
avec son adresse finale et son titre nettoyé. Refus 422 url_refusee,
autre_site ou page_illisible ; une redirection vers un autre site est
reconnue par les refus notés par page_web. Contrat 0.26.0, quatre
scénarios Gherkin.
2026-10-21 09:40:15 +02:00
david 1e81c369b3 docs(audit): B4 design, choosing the pages to audit
Fiche de la carte #99 (étape 2 de la préparation d'un audit), validée le
2026-10-21 : cases, compteur, limite de N pages lue dans la réponse de la
détection (pages_max), ajout d'une page à la main vérifiée en direct
(POST /audits/pages/verification, 2xx), étape 3 vide. Schéma et plan
d'implémentation.
2026-10-21 09:17:34 +02:00
david d9646a3ae5 docs: card 98 closed after its pull request
Clôture de B3 (carte #98) après la PR #101 : entrée du CHANGELOG et
décision ajoutée aux notes de l'oral (liens vérifiés, étiquettes
traitées comme des données non sûres).
2026-10-21 08:46:08 +02:00
david 73c391239e docs: B3 sitemap amendment in the changelog
Evals au push — seules celles dont un fichier sensible est touché / tri (push) Successful in 14s
Evals au push — seules celles dont un fichier sensible est touché / evals (push) Skipped
CI / ci (push) Skipped
Revue — preuve d'approbation / revue-ok (pull_request_review) Successful in 8s
2026-10-21 08:42:39 +02:00
david 98214d1f9c feat(client): optional sitemap search when preparing an audit
Amendement de B3 (carte #98, décisions 13 à 19) : case décochée
« Chercher aussi les pages dans le plan du site (sitemap.xml) » à
l'étape 1, envoyée à POST /audits/pages ; pages trouvées en deux
groupes (accueil, plan du site) ; message quand aucun plan n'a pu être
lu ; avertissement de A10 seulement si rien d'autre que l'accueil.
Une page sans titre affiche son chemin en texte courant.
2026-10-21 08:42:39 +02:00
david 6bc641f763 feat(audit): pages from the sitemap on request (POST /audits/pages)
Amendement de B3 (carte #98, décisions 13 à 19) : avec plan_du_site, la
détection lit robots.txt puis les plans déclarés, sinon /sitemap.xml,
un niveau d'index, 5 documents au plus. Les adresses du plan passent
les filtres des liens de l'accueil et la même vérification, sous le
plafond commun de 50. Chaque page porte sa source ; un plan absent ou
mal formé n'est pas une erreur (plan_du_site : introuvable). XML lu par
le module standard (entités externes et expansion abusive refusées).
Origine « accueil » redéfinie, sans migration. 7e scénario Gherkin.
2026-10-21 08:37:47 +02:00
david ba3f5a64ea docs(audit): B3 amendment, pages from the sitemap on request
Amendement validé le 2026-10-21 (décisions 13 à 19) : case décochée
pour chercher aussi les pages dans le plan du site (robots.txt puis
sitemap.xml, un niveau d'index), mêmes filtres et vérification que les
liens, plafond commun, origine « accueil » redéfinie, deux groupes à
l'affichage. RM4 de la spec et schéma mis à jour.
2026-10-21 08:30:01 +02:00
david db7e765452 docs: B3 done, the site and its pages
CHANGELOG de la réalisation de B3 (carte #98), suivi des maquettes
intégrées (A04 à A06, A07 et A10 en partie), ligne Caddy du serveur à
mettre à jour au prochain déploiement (TODO).
2026-10-21 08:14:47 +02:00
david 38527ef2bb feat(client): prepare an audit, step 1: the site and the pages found
B3 (carte #98), côté client :
- barre « Adresse du site à auditer » + « Préparer l'audit » dans Mes
  audits, sans audit en cours (A01, A02) ;
- écran « Préparer un audit » (/mes-audits/nouveau, réservé) avec
  l'indicateur d'étapes : adresse et déclaration (A04, A05), détection
  annulable (A06, AbortController), pages trouvées en lecture seule,
  avertissement quand seul l'accueil est proposé, liens non vérifiés ;
- titres de pages affichés en texte, jamais en HTML (test avec une
  étiquette <img onerror>, vérifié en cassant le code) ;
- « Mes audits » reste marqué dans l'en-tête sur ses sous-pages
  (aria-current=true) ; libellé et message de la déclaration partagés
  avec la question libre ; route ajoutée à la ligne Caddy documentée.
2026-10-21 08:14:13 +02:00
david 1c66d76b4e feat(audit): detect the pages of a site from its home page (POST /audits/pages)
B3 (carte #98), côté API : la route lit l'accueil du site déclaré
(lecture protégée de la question libre) et propose les pages qu'il
relie, après la déclaration (RM2) et le contrôle de l'adresse (RM3).
- chaque lien est lu (5 à la fois, 50 au plus) et gardé seulement s'il
  répond 2xx en HTML sur le même nom d'hôte, à son adresse finale ;
- fichiers écartés par l'extension puis par le type ; adresses à secret
  ou donnée personnelle écartées avant lecture ;
- étiquettes nettoyées à la source (texte brut, Cc/Cf retirés, 255) ;
- 422 url_refusee ou site_illisible avec un message pour l'auditeur.
Contrat 0.25.0. Six scénarios Gherkin en intégration, faux site.
2026-10-21 08:04:33 +02:00
david 88232db567 docs(audit): design and plan of B3, the site and its pages
Fiche de B3 (carte #98) validée le 2026-10-21 : POST /audits/pages lit
l'accueil du site déclaré et propose les pages qu'il relie, chaque lien
vérifié (2xx et HTML), fichiers écartés, étiquettes nettoyées. Schéma
B3_site_et_pages.drawio et plan d'implémentation.
2026-10-21 07:54:30 +02:00
david b22da8ab73 docs: coverage threshold of app/ is 95 %, not 94 %
La section 1 de docs/developpement/couverture.md donnait encore le seuil
du 2026-10-05 (94 %) ; pyproject.toml est à 95 % depuis le 2026-10-18
(97 % mesurés en CI sur la PR #91). Vérifications du 2026-10-05 gardées,
avec le seuil d'alors.
2026-10-21 07:35:16 +02:00